Skip to content

Remove empty directories after discarding untracked files#5408

Merged
stefanhaller merged 3 commits intomasterfrom
remove-empty-dirs-after-discarding
Mar 30, 2026
Merged

Remove empty directories after discarding untracked files#5408
stefanhaller merged 3 commits intomasterfrom
remove-empty-dirs-after-discarding

Conversation

@stefanhaller
Copy link
Copy Markdown
Collaborator

When discarding untracked files, remove any directories that have become empty because of this.

Fixes #1964.

@DusanLesan
Copy link
Copy Markdown

It works. The only pause this gave me was when deleting the go telemetry directory after a go run command. But Go created an empty directory named upload that apparently blocked removal of the whole tree, and only local ended up being removed. I am fine with that

@stefanhaller
Copy link
Copy Markdown
Collaborator Author

@DusanLesan Yeah, I was actually unsure if removing those empty directories unconditionally is always what you want. Like, you might create a new directory src/lib/my-new-module and create a first source file in there; then, after hacking for a bit you realize you want to start over with a differently named source file, and discard the file. You'd then have to recreate the directories to create that new file, which could be annoying.

Maybe we should make it dependent on what you selected when you hit discard: selecting the my-new-module folder would delete it when it becomes empty, but selecting the file inside would not. I'll look into changing that.

I didn't understand your example enough to tell whether it would be affected by this.

@DusanLesan
Copy link
Copy Markdown

I didn't understand your example enough to tell whether it would be affected by this

DP-0_recording.mp4

Here is exact case I've tried to explain. I would expect for whole go dir to be removed but it is left there because of the empty directory created by go.

@stefanhaller stefanhaller force-pushed the remove-empty-dirs-after-discarding branch 3 times, most recently from ee79e76 to 23cfd10 Compare March 23, 2026 12:54
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Mar 23, 2026

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for dd7a3fa1 85.71%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (dd7a3fa) Report Missing Report Missing Report Missing
Head commit (2a6648f) 61023 53452 87.59%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#5408) 77 66 85.71%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

@stefanhaller stefanhaller force-pushed the remove-empty-dirs-after-discarding branch from fe05f2a to 8768799 Compare March 23, 2026 13:03
@stefanhaller
Copy link
Copy Markdown
Collaborator Author

Ok, this gets tricky now. I made the change I mentioned above, where directories are only removed if you select them explicitly for discarding (or one of their parent directories). If you select the last untracked file in a directory and discard it, the directory is not removed; so far so desirable, I'd say.

The problem is that if you do want to get rid of the go directory or the telemetry directory in your example (assuming this upload folder didn't exist), there'd be no way to do that, because you can't select those (because of the directory collapsing that lazygit does). The only directory that you can select is local, so only that gets removed.

Not sure how much of a problem this is, or what to do about it. Input welcome.

@DusanLesan
Copy link
Copy Markdown

Not sure how much of a problem this is, or what to do about it. Input welcome

It is just a slight inconvenience to me and I guess it is safer not to remove even if it were easy to implement as some users might expect only the files on the displayed path to be removed. upload was not even shown in the TUI so some could say it should stay unaffected by discarding

@stefanhaller
Copy link
Copy Markdown
Collaborator Author

Yes, but I'm not talking about your upload folder here, I think the behavior wrt that is fine. There's no reason for the discard feature to delete it, since it's a sibling of the thing that you are discarding.

I'm talking about the case where you have

▼ a/b/c
  ?? x.txt

and want to select a to discard it; you can't, you can only select c. So it will keep a and b, and only delete c.

@stefanhaller stefanhaller force-pushed the speed-up-discarding-files branch from 9f2a987 to 4d46f5a Compare March 27, 2026 13:38
Base automatically changed from speed-up-discarding-files to master March 27, 2026 13:40
@stefanhaller stefanhaller force-pushed the remove-empty-dirs-after-discarding branch from 8768799 to 314ee07 Compare March 27, 2026 13:42
When discarding untracked files, remove any directories that have become empty
because of this.
@stefanhaller stefanhaller force-pushed the remove-empty-dirs-after-discarding branch from 314ee07 to 2a6648f Compare March 30, 2026 15:50
@stefanhaller stefanhaller enabled auto-merge March 30, 2026 15:50
@stefanhaller stefanhaller merged commit d42851d into master Mar 30, 2026
13 checks passed
@stefanhaller stefanhaller deleted the remove-empty-dirs-after-discarding branch March 30, 2026 15:53
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Apr 8, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit) | minor | `v0.60.0` → `v0.61.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jesseduffield/lazygit (jesseduffield/lazygit)</summary>

### [`v0.61.0`](https://github.com/jesseduffield/lazygit/releases/tag/v0.61.0)

[Compare Source](jesseduffield/lazygit@v0.60.0...v0.61.0)

<!-- Release notes generated using configuration in .github/release.yml at v0.61.0 -->

The big one in this release is support for GitHub pull requests. They are shown as little GitHub icons next to each branch that has one, and you can open a MR in the browser by pressing shift-G. To enable this, all you need to do is install the [`gh`](https://cli.github.com/) tool if you haven't already, and log in using `gh auth login`.

#### What's Changed

##### Features ✨

- Show pull requests against branches by [@&#8203;jesseduffield](https://github.com/jesseduffield) in [#&#8203;2781](jesseduffield/lazygit#2781)

##### Enhancements 🔥

- Add support for clicking on arrows in the file list to expand/collapse directories by [@&#8203;blakemckeany](https://github.com/blakemckeany) in [#&#8203;5365](jesseduffield/lazygit#5365)
- Remove empty directories after discarding untracked files by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5408](jesseduffield/lazygit#5408)
- Make file sort order and case sensitivity configurable, and default to mix files and folders by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5427](jesseduffield/lazygit#5427)
- Allow customizing the window width/height thresholds for when to use portrait mode by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5452](jesseduffield/lazygit#5452)
- Log hashes of local branches when deleting them by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5441](jesseduffield/lazygit#5441)
- Add condition field to custom command prompts by [@&#8203;mrt181](https://github.com/mrt181) in [#&#8203;5364](jesseduffield/lazygit#5364)

##### Fixes 🔧

- Fix staging only some lines of a block of consecutive changes by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5396](jesseduffield/lazygit#5396)
- Fix the expanded layout of the branches panel (half and full screen modes) by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5413](jesseduffield/lazygit#5413)
- Fix searching commits or main view after switching repos by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5424](jesseduffield/lazygit#5424)
- Scroll to top when showing subcommits by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5425](jesseduffield/lazygit#5425)
- Fix patch commands when git config has color=always by [@&#8203;matthijskooijman](https://github.com/matthijskooijman) in [#&#8203;5405](jesseduffield/lazygit#5405)
- Don't stage out-of-date submodules when asking user to auto-stage after resolving conflicts by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5440](jesseduffield/lazygit#5440)

##### Maintenance ⚙️

- Remove go-git dependency by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5420](jesseduffield/lazygit#5420)
- Make Debian/Ubuntu install command architecture-independent by [@&#8203;discapes](https://github.com/discapes) in [#&#8203;5386](jesseduffield/lazygit#5386)
- Bump github.com/buger/jsonparser from 1.1.1 to 1.1.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5423](jesseduffield/lazygit#5423)
- fix: pin 7 unpinned action(s), extract 1 inline secret to env var by [@&#8203;dagecko](https://github.com/dagecko) in [#&#8203;5439](jesseduffield/lazygit#5439)
- Fix dependabot config file by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5443](jesseduffield/lazygit#5443)
- Bump actions/cache from 4 to 5 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5444](jesseduffield/lazygit#5444)
- Bump actions/download-artifact from 7 to 8 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5445](jesseduffield/lazygit#5445)
- Bump actions/upload-artifact from 6 to 7 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5446](jesseduffield/lazygit#5446)
- Bump github.com/lucasb-eyer/go-colorful from 1.3.0 to 1.4.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5447](jesseduffield/lazygit#5447)
- Bump github.com/spf13/afero from 1.9.5 to 1.15.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5448](jesseduffield/lazygit#5448)
- Bump github.com/creack/pty from 1.1.11 to 1.1.24 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5449](jesseduffield/lazygit#5449)
- Bump github.com/stretchr/testify from 1.10.0 to 1.11.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5450](jesseduffield/lazygit#5450)
- Bump github.com/sanity-io/litter from 1.5.2 to 1.5.8 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5451](jesseduffield/lazygit#5451)
- Bump github.com/adrg/xdg from 0.4.0 to 0.5.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5456](jesseduffield/lazygit#5456)
- Bump github.com/spkg/bom from 0.0.0-20160624110644-59b7046e48ad to 1.0.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5457](jesseduffield/lazygit#5457)
- Bump github.com/integrii/flaggy from 1.4.0 to 1.8.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5458](jesseduffield/lazygit#5458)
- Bump github.com/sahilm/fuzzy from 0.1.0 to 0.1.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5459](jesseduffield/lazygit#5459)
- Bump github.com/sasha-s/go-deadlock from 0.3.6 to 0.3.9 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5460](jesseduffield/lazygit#5460)

##### Docs 📖

- Add a note about AI to CONTRIBUTING.md by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5404](jesseduffield/lazygit#5404)
- Update redo keybinding in README.md by [@&#8203;unikitty37](https://github.com/unikitty37) in [#&#8203;5387](jesseduffield/lazygit#5387)
- Fix grammar in the contributor guide by [@&#8203;Rohan5commit](https://github.com/Rohan5commit) in [#&#8203;5392](jesseduffield/lazygit#5392)

##### I18n 🌎

- Update translations from Crowdin by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5476](jesseduffield/lazygit#5476)

##### Performance Improvements 📊

- Improve performance of discarding many files by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5407](jesseduffield/lazygit#5407)

#### New Contributors

- [@&#8203;blakemckeany](https://github.com/blakemckeany) made their first contribution in [#&#8203;5365](jesseduffield/lazygit#5365)
- [@&#8203;discapes](https://github.com/discapes) made their first contribution in [#&#8203;5386](jesseduffield/lazygit#5386)
- [@&#8203;unikitty37](https://github.com/unikitty37) made their first contribution in [#&#8203;5387](jesseduffield/lazygit#5387)
- [@&#8203;Rohan5commit](https://github.com/Rohan5commit) made their first contribution in [#&#8203;5392](jesseduffield/lazygit#5392)
- [@&#8203;matthijskooijman](https://github.com/matthijskooijman) made their first contribution in [#&#8203;5405](jesseduffield/lazygit#5405)
- [@&#8203;dagecko](https://github.com/dagecko) made their first contribution in [#&#8203;5439](jesseduffield/lazygit#5439)
- [@&#8203;mrt181](https://github.com/mrt181) made their first contribution in [#&#8203;5364](jesseduffield/lazygit#5364)

**Full Changelog**: <jesseduffield/lazygit@v0.60.0...v0.61.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDQuOCIsInVwZGF0ZWRJblZlciI6IjQzLjEwNC44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

discard all changes on an untracked directory deletes only files in it

2 participants