fix(worktree): allow force-closing orphaned worktrees#158
Draft
tomasfejfar wants to merge 1 commit into
Draft
Conversation
When a worktree's metadata entry is pruned from the main repo (e.g. by
`git worktree prune` while removing another worktree), its checkout
survives on disk with a dangling `.git` pointer. `git worktree remove`
then exits 128 ("not a git repository"), and okena's only auto-cleanup
fires when the directory is *gone* — so an orphaned-but-present worktree
stays stuck in the sidebar with no working removal path.
Add a destructive "Delete folder anyway" fallback that appears only
after the normal close fails: it resolves the checkout root without git
(walking up to the `.git` pointer), deletes the directory, prunes stale
metadata, and de-registers the project.
ce95fb7 to
691f370
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A worktree shown in the sidebar could get into a state where "Close Worktree" always failed and there was no way to remove it from the app:
Root cause
When a worktree's metadata entry (
<main-repo>/.git/worktrees/<name>) is pruned — e.g.git worktree pruneruns while removing a different worktree (prune wipes every stale entry, not just the one being removed) — the checkout directory survives on disk but its.gitpointer now dangles. Git no longer recognizes it as a worktree, sogit worktree removeexits 128.okena's existing auto-cleanup (
worktree_sync.rs→remove_stale_worktree) only fires when the directory no longer exists. An orphaned-but-present directory is never cleaned up, so the entry stays stuck in the sidebar with no working removal path.Changes
A two-step UX: the normal close runs exactly as before. Only after the final removal fails does the dialog reveal a destructive "Delete folder anyway" button.
okena-git—resolve_worktree_root_fs: resolves a worktree checkout root by walking up to the nearest.gitentry, without opening the repo via gix (which fails on a dangling pointer). Handles monorepo subdir projects too.okena-workspace—Workspace::force_remove_worktree_project: deletes the on-disk directory and prunes stale metadata (reusing the existingremove_worktree_fast), then de-registers the project. It deliberately bypasses git's dirty-state safety because git can no longer run that check on a worktree it doesn't track — hence the second click is required to reach it.okena-views-git(Close Worktree dialog) — ashow_force_removeflag set only on the final removal failure (not on stash/fetch/rebase/merge failures, which force-delete can't fix), an asyncforce_remove(), and the destructive footer button rendered only when that flag is set.No public behavior changes for healthy worktrees; the new button never appears unless a removal has already failed.
How to verify it
cargo test -p okena-git— newforce_removes_orphaned_worktreetest reproduces the exact status-128 failure and proves the fallback resolves the root and cleans up (119 passed)cargo test -p okena-workspace— no regressions (294 passed)cargo build -p okena-git -p okena-workspace -p okena-views-git— all changed crates compileChangelog
Fixed: orphaned worktrees (directory present but no longer tracked by git) can now be removed from the sidebar via a "Delete folder anyway" fallback that appears after a failed close.