"cannot delete branch used by worktree": why Git refuses, and four fixes
Why git branch -d says "cannot delete branch used by worktree", the variants (checked out at, already used by worktree), and the fix for each case.
Git prints error: cannot delete branch 'x' used by worktree at '<path>' when the branch you’re deleting is checked out in a worktree: your main folder or a linked one. Git won’t delete a branch some folder is standing on, and -D doesn’t change that. The fix is to free the branch first: remove that worktree, switch it to another branch, or, if you already deleted its folder by hand, run git worktree prune. Then git branch -d works. Older Git (2.42 and before) says the same thing as Cannot delete branch 'x' checked out at '<path>'.
Which fix to use
The path in the error tells you which worktree has the branch. Find it in git worktree list, then pick the row that matches:
What git worktree list shows for that path |
What you want | Run this, then git branch -d <branch> |
|---|---|---|
| A folder you’re done with | Delete the worktree too | git worktree remove <path> |
| A folder you still need | Keep the folder | git -C <path> switch <other-branch> or switch --detach |
prunable (you deleted the folder) |
Make Git forget it | git worktree prune |
locked, folder deleted |
Make Git forget it | Lift the lock (below), then git worktree prune |
(detached HEAD), yet Git still names it |
Finish or abort the rebase there | git -C <path> rebase --abort (or --continue) |
| Your main folder (the path is the repository itself) | Delete the branch you’re on | git switch main first |
The error, and why -D doesn’t help
Here’s the setup: a worktree for a login fix, and an attempt to delete its branch from the main folder.
$ git worktree add ../app-fix-login -b fix-loginPreparing worktree (new branch 'fix-login')HEAD is now at 9a7331a Add readme line$ git branch -d fix-loginerror: cannot delete branch 'fix-login' used by worktree at '~/code/app-fix-login'Running it from inside the worktree changes nothing, and neither does -D:
$ git branch -D fix-loginerror: cannot delete branch 'fix-login' used by worktree at '~/code/app-fix-login'In Git’s source (builtin/branch.c), the “used by worktree” check comes before the force flag is ever looked at, so a force-delete gets the same error.
The rule behind it: each branch can be checked out in only one worktree, and Git won’t pull a branch out from under a folder that has it. The same rule produces two related errors, with the same cause:
$ git switch fix-loginfatal: 'fix-login' is already used by worktree at '~/code/app-fix-login'$ git worktree add ../app-two fix-loginPreparing worktree (checking out 'fix-login')fatal: 'fix-login' is already used by worktree at '~/code/app-fix-login'$ git branch -f fix-login HEAD~1fatal: cannot force update the branch 'fix-login' used by worktree at '~/code/app-fix-login'Renaming is the exception: git branch -m fix-login fix-login2 worked, and the worktree simply showed the new name.
“checked out at” is the same error
Git 2.42 and older word it differently: Cannot delete branch 'fix-login' checked out at '<path>'. I compared builtin/branch.c at the v2.42.0 and v2.43.0 tags: the check is the same, only the message changed. I didn’t run an old Git; the source is my evidence here.
In current Git you also get this error for the branch you’re on in your main folder, because the main folder is a worktree too:
$ git switch -q -c scratch$ git branch -d scratcherror: cannot delete branch 'scratch' used by worktree at '~/code/app'Switch to another branch, then delete it.
Fix 1: remove the worktree
If you’re done with the folder, remove it, then the branch:
$ git worktree remove ../app-search$ git branch -d feature/searchDeleted branch feature/search (was 9a7331a).If the worktree has uncommitted or untracked files, git worktree remove refuses until you add --force, which throws them away. That case, and locked worktrees, are in git worktree remove, prune and lock.
Fix 2: keep the folder, switch its branch
If you still want the folder (it has node_modules installed, say), move the worktree off the branch instead. Either onto another branch:
$ git -C ../app-fix-login switch -c fix-login-2Switched to a new branch 'fix-login-2'$ git branch -d fix-loginDeleted branch fix-login (was 9a7331a).Or onto no branch at all, with --detach:
$ git -C ../app-fix-login switch --detachHEAD is now at 9a7331a Add readme line$ git branch -d fix-login-2Deleted branch fix-login-2 (was 9a7331a).git -C <path> runs the command as if you were in that folder, so you don’t have to cd there and back.
Fix 3: you deleted the folder by hand
This is the confusing one. The folder is gone, but Git still has its record in .git/worktrees/, so the branch still counts as used:
$ rm -rf ../app-gone$ git branch -d feature/goneerror: cannot delete branch 'feature/gone' used by worktree at '~/code/app-gone'$ git worktree list~/code/app 9a7331a [main]~/code/app-fix-login 9a7331a (detached HEAD)~/code/app-gone 9a7331a [feature/gone] prunable$ git worktree prune -vRemoving worktrees/app-gone: gitdir file points to non-existent location$ git branch -d feature/goneDeleted branch feature/gone (was 9a7331a).prunable in the list is the sign. git worktree prune only removes records whose folder is missing, so it’s safe to run.
Locked and deleted
A locked worktree survives a prune, even with its folder gone. Prune prints nothing and the branch stays blocked:
$ git worktree lock --reason 'on an external drive' ../app-usb$ rm -rf ../app-usb$ git worktree prune -v$ git branch -d feature/usberror: cannot delete branch 'feature/usb' used by worktree at '~/code/app-usb'$ git worktree list~/code/app 9a7331a [main]~/code/app-fix-login 9a7331a (detached HEAD)~/code/app-usb 9a7331a [feature/usb] locked$ git worktree unlock ../app-usb$ git worktree prune -vRemoving worktrees/app-usb: gitdir file points to non-existent location$ git branch -d feature/usbDeleted branch feature/usb (was 9a7331a).Lifting the lock works with the folder gone. Before you do it, make sure the folder isn’t just on a drive that isn’t mounted: that’s what locks are for (git-worktree docs). Claude Code also locks the worktrees its subagents run in while they run (Claude Code docs).
Fix 4: a rebase is still in progress
A worktree stopped in the middle of a rebase shows (detached HEAD) in the list, and Git still won’t delete the branch being rebased:
$ git -C ../app-rebase rebase mainRebasing (1/1)Auto-merging README.mdCONFLICT (content): Merge conflict in README.mderror: could not apply 1f9963e... Rewrite readmehint: Resolve all conflicts manually, mark them as resolved withhint: "git add/rm <conflicted_files>", then run "git rebase --continue".hint: You can instead skip this commit: run "git rebase --skip".hint: To abort and get back to the state before "git rebase", run "git rebase --abort".hint: Disable this message with "git config set advice.mergeConflict false"Could not apply 1f9963e... # Rewrite readme$ git worktree list~/code/app 2681611 [main]~/code/app-fix-login 9a7331a (detached HEAD)~/code/app-rebase 2681611 (detached HEAD)$ git branch -d feature/rebaseerror: cannot delete branch 'feature/rebase' used by worktree at '~/code/app-rebase'$ git -C ../app-rebase rebase --abort$ git worktree list~/code/app 2681611 [main]~/code/app-fix-login 9a7331a (detached HEAD)~/code/app-rebase 1f9963e [feature/rebase]Finish or abort the rebase, then use one of the fixes above. Git’s source (branch.c, prepare_checked_out_branches) treats a branch being bisected from in a worktree the same way; I tested the rebase case, not bisect.
Stop it happening
If you create a lot of worktrees, one per task or per AI agent, the order is the whole trick: remove the worktree first, delete the branch second.
Plyloft, the app I build, does that part for you: when a card ships, it moves the card’s worktree folder into .plyloft-worktrees/.trash/ and runs git worktree prune right away, so the branch is no longer used by a worktree (unless the worktree still has uncommitted changes or an open session, in which case Plyloft keeps it). Since version 1.162, once the worktree has left the trash, Plyloft also deletes the card’s branch itself, with a compare-and-delete, unless it has commits made after it shipped. If you turned that off, or the branch was kept, git branch -D is still the command: shipping usually squash-merges, so -d says it’s not fully merged.
The worktrees guide for Claude Code and Codex covers that workflow, and how to use git worktree walks through the basics once, start to finish.
Questions people ask
How do I fix "cannot delete branch used by worktree"?
Free the branch first, then delete it. Remove the worktree that has it checked out (git worktree remove <path>), or switch that worktree to another branch, or run git worktree prune if you already deleted its folder by hand. Then git branch -d works.
Does git branch -D force-delete a branch used by a worktree?
No. Git checks whether a worktree uses the branch before it looks at the force flag, so -D fails with the same error. The branch has to be free first.
Why does Git say the branch is used by a worktree I already deleted?
Deleting the folder doesn't delete Git's record of the worktree in .git/worktrees. git worktree list shows it as prunable. Run git worktree prune, then delete the branch. If the worktree was locked, lift the lock first, or prune skips it.
What is the difference between "checked out at" and "used by worktree at"?
They are the same error from different Git versions. Git 2.42 and older print "Cannot delete branch 'x' checked out at '<path>'"; Git 2.43 and later print "cannot delete branch 'x' used by worktree at '<path>'". The fixes are the same.