← BlogGuides · 6 min

"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
From the runs below, Git 2.50.1, October 5, 2026.

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.

Terminal window
$ git worktree add ../app-fix-login -b fix-login
Preparing worktree (new branch 'fix-login')
HEAD is now at 9a7331a Add readme line
$ git branch -d fix-login
error: 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:

Terminal window
$ git branch -D fix-login
error: 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:

Terminal window
$ git switch fix-login
fatal: 'fix-login' is already used by worktree at '~/code/app-fix-login'
$ git worktree add ../app-two fix-login
Preparing worktree (checking out 'fix-login')
fatal: 'fix-login' is already used by worktree at '~/code/app-fix-login'
$ git branch -f fix-login HEAD~1
fatal: 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:

Terminal window
$ git switch -q -c scratch
$ git branch -d scratch
error: 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:

Terminal window
$ git worktree remove ../app-search
$ git branch -d feature/search
Deleted 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:

Terminal window
$ git -C ../app-fix-login switch -c fix-login-2
Switched to a new branch 'fix-login-2'
$ git branch -d fix-login
Deleted branch fix-login (was 9a7331a).

Or onto no branch at all, with --detach:

Terminal window
$ git -C ../app-fix-login switch --detach
HEAD is now at 9a7331a Add readme line
$ git branch -d fix-login-2
Deleted 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:

Terminal window
$ rm -rf ../app-gone
$ git branch -d feature/gone
error: 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 -v
Removing worktrees/app-gone: gitdir file points to non-existent location
$ git branch -d feature/gone
Deleted 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:

Terminal window
$ git worktree lock --reason 'on an external drive' ../app-usb
$ rm -rf ../app-usb
$ git worktree prune -v
$ git branch -d feature/usb
error: 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 -v
Removing worktrees/app-usb: gitdir file points to non-existent location
$ git branch -d feature/usb
Deleted 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:

Terminal window
$ git -C ../app-rebase rebase main
Rebasing (1/1)Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply 1f9963e... Rewrite readme
hint: Resolve all conflicts manually, mark them as resolved with
hint: "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/rebase
error: 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.

Try it on your own repo.

Free for one card at a time.

Get Pro

Seats, you included (2–50)
3
VAT included. Businesses in the EU can add a VAT number on the payment page.Founding price, kept for as long as your subscription runs.

Checking your sign-in…