Skip to content

Make worktree removal survive read-only directories - #268

Merged
haacked merged 1 commit into
mainfrom
haacked/worktree-remove-readonly
Oct 28, 2026
Merged

haacked merged 1 commit into
mainfrom
haacked/worktree-remove-readonly

Conversation

@haacked

@haacked haacked commented Oct 28, 2026

Copy link
Copy Markdown
Owner

git worktree remove fails partway through a read-only directory, and git deletes the worktree's admin dir anyway. The checkout stays on disk with a .git file that points at nothing, so tree-me and git worktree list stop seeing it. Go makes its module cache read-only, so posthog worktrees created before posthog's flox manifest set GOFLAGS=-modcacherw hit this when removed. One orphan I found was 5.2G.

worktree_remove in bin/lib/git-worktree.sh gives the owner write permission on every read-only directory and then calls git. tree-me and git-bclean-local both remove worktrees through it. It leaves permissions alone when git will refuse anyway (main worktree, locked, or uncommitted changes without -f). If a directory can't be made writable, it doesn't call git, so it never leaves a worktree half-deleted. It doesn't predict git's refusal for populated submodules, so in that case the directories become writable and git removes nothing.

git-bclean-local now learns about uncommitted changes from git's refusal message instead of running git status itself. As a result, it reports a worktree that is both locked and dirty as locked.

I think disk-cleanup's make_writable_cmd could switch to the new make_writable later, since both run the same find command.

Test plan

  • bin/lib/test-tree-me-remove.sh and the new bin/lib/test-git-bclean-local.sh cover a worktree with a read-only directory, a worktree whose directory is already gone, and refused removals that keep their permissions. The removal tests failed before the fix.
  • The tree-me suite passes under macOS /bin/bash 3.2.

https://claude.ai/code/session_01AovXvX6L3zUjLxi9RCBWt6

git worktree remove fails partway through a read-only directory, such as
Go's module cache, and still deletes the worktree's admin dir, which
orphans the checkout. Add worktree_remove to lib/git-worktree.sh, which
makes every directory writable before it calls git, unless git will
refuse the removal or the directory is already gone. tree-me and
git-bclean-local now remove worktrees through it.

git-bclean-local now detects uncommitted changes from git's refusal, as
it already did for locks.

disk-cleanup's make_writable_cmd prints the same find command as the
new make_writable helper and could switch to it.

Claude-Session: https://claude.ai/code/session_01AovXvX6L3zUjLxi9RCBWt6
@haacked
haacked marked this pull request as ready for review October 28, 2026 23:34
@haacked
haacked merged commit 907b359 into main Oct 28, 2026
1 check passed
@haacked
haacked deleted the haacked/worktree-remove-readonly branch October 28, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant