← BlogGuides · 4 min

git worktree remove, prune and lock: delete a worktree and fix what blocks it

Delete a git worktree and its branch, and fix what blocks it: modified files, locked trees, folders deleted by hand, and branches still in use.

To delete a worktree, run git worktree remove <path>, then git branch -d <branch>: removing the folder doesn’t delete the branch. If Git refuses, it’s for one of four reasons, each with its own fix: the worktree has uncommitted files (--force), it’s locked (--force --force, or lift the lock), you already deleted the folder by hand (git worktree prune), or you’re deleting the branch before the worktree. Below is each one with the real error and the command that clears it.

New to worktrees? Start with how to use git worktree, and git worktree add for creating them.

Remove a worktree, then its branch

A clean worktree goes without a word. The branch stays until you delete it:

Terminal window
$ git worktree remove ../app-quick
$ git branch -d app-quick
Deleted branch app-quick (was 85f04f1).

You can run git worktree remove from the main folder or from any other worktree of the same repository. The one folder you can’t remove is the main one:

Terminal window
$ git worktree remove .
fatal: '.' is a main working tree

If the branch has commits that aren’t merged anywhere, -d stops you, as it should:

Terminal window
$ git branch -d feature/wip
error: the branch 'feature/wip' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/wip'
hint: Disable this message with "git config set advice.forceDeleteBranch false"

Use -D only if you’re sure that work isn’t needed. When an AI agent did the work, that’s usually the moment to look at its diff one last time.

“contains modified or untracked files”

Terminal window
$ git worktree remove ../app-fix-login
fatal: '../app-fix-login' contains modified or untracked files, use --force to delete it

Git says the same thing for a modified tracked file and for a single new file nobody added. --force deletes the folder anyway, uncommitted work included:

Terminal window
$ git worktree remove --force ../app-feature-search

Before you force it, look: git -C ../app-fix-login status --short. If anything there matters, commit it on the worktree’s branch. A stash works too, but remember that the stash is shared by every worktree of the repository.

Delete the worktree before the branch

If you delete the branch first, Git stops you with cannot delete branch … used by worktree, and -D doesn’t help. Remove the worktree, then the branch. Every case of that error, with the fix for each, is in its own guide: cannot delete branch used by worktree.

Folders deleted by hand: git worktree prune

Deleting a worktree folder with rm -rf or the Finder works, but Git keeps its record in .git/worktrees/. git worktree list marks it prunable:

Terminal window
$ git worktree list
~/code/app 85f04f1 [main]
~/code/app-feature-x 85f04f1 [feature-x]
~/code/app-fix-login 85f04f1 [fix-login]
~/code/app-track 85f04f1 [feature/remote-x]
~/code/app-v1 774398e (detached HEAD) prunable

git worktree prune clears those records. See what it would do first:

Terminal window
$ git worktree prune --dry-run -v
Removing worktrees/app-v1: gitdir file points to non-existent location
$ git worktree prune -v
Removing worktrees/app-v1: gitdir file points to non-existent location

Prune only touches records whose folder is missing, and it skips locked worktrees. Git also prunes these records on its own after a while, as part of garbage collection (the gc.worktreePruneExpire setting), so a leftover record isn’t harmful; it just blocks that branch until it’s gone (git-worktree docs).

Locked worktrees

A lock tells Git not to prune, move or remove a worktree. Git’s docs give the reason it exists: a worktree on a portable drive or a network share that isn’t always mounted. Locking one, with a reason:

Terminal window
$ git worktree lock --reason 'on an external drive' ../app-usb
$ git worktree list
~/code/app 85f04f1 [main]
~/code/app-fix-login 85f04f1 [fix-login]
~/code/app-moved-by-hand 85f04f1 [feature/remote-x]
~/code/app-usb 85f04f1 [feature/usb] locked

git worktree list --verbose shows the reason on the next line. Removing it needs two --force flags, not one:

Terminal window
$ git worktree remove ../app-usb
fatal: cannot remove a locked working tree, lock reason: on an external drive
use 'remove -f -f' to override or unlock first
$ git worktree remove --force ../app-usb
fatal: cannot remove a locked working tree, lock reason: on an external drive
use 'remove -f -f' to override or unlock first
$ git worktree remove --force --force ../app-usb

Or lift the lock and remove it normally:

Terminal window
git worktree unlock ../app-usb
git worktree remove ../app-usb

If you use Claude Code, it locks the worktrees its subagents and background sessions work in while they run, and releases the lock when they finish (Claude Code docs). A locked worktree you didn’t lock yourself may still be in use: check before you force it.

Moved a worktree? Use move, or repair

git worktree move moves the folder and updates Git’s records together:

Terminal window
$ git worktree move ../app-track ../app-remote-x

Move it with mv or the Finder instead and Git loses track of it: the old path shows as prunable, and a prune would forget the worktree entirely. Run git worktree repair with the new path to reconnect it:

Terminal window
$ mv ../app-remote-x ../app-moved-by-hand
$ git worktree list
~/code/app 85f04f1 [main]
~/code/app-fix-login 85f04f1 [fix-login]
~/code/app-remote-x 85f04f1 [feature/remote-x] prunable
$ git worktree repair ../app-moved-by-hand
repair: gitdir incorrect: ~/code/app/.git/worktrees/app-track/gitdir
$ git worktree list
~/code/app 85f04f1 [main]
~/code/app-fix-login 85f04f1 [fix-login]
~/code/app-moved-by-hand 85f04f1 [feature/remote-x]

(The record is still called app-track, the folder’s first name. Git keeps the internal name; only the path changes.)

Worktrees with submodules can’t be moved with git worktree move, and can only be removed with --force. Git’s own docs call submodule support in worktrees incomplete.

A cleanup routine

What I run when a batch of worktrees is done:

Terminal window
git worktree list # what's there
git worktree remove ../app-<task> # each finished one
git branch -d <branch> # each merged branch
git worktree prune -v # records of folders deleted by hand

If you create a lot of worktrees, for example one per AI agent task, this is the part worth automating. How Claude Code and Codex clean up the worktrees they create, and how I avoid doing it by hand, is in the worktrees guide. For when a worktree is the right tool in the first place, see git worktree vs branch, stash and clone.

Questions people ask

How do I delete a git worktree?

Run git worktree remove <path> from any worktree of the repository, then delete its branch with git branch -d <branch>. Removing the worktree doesn't delete the branch.

What does git worktree prune do?

It deletes Git's records of worktrees whose folders no longer exist. It never touches a folder that still exists, and it skips locked worktrees. Add --dry-run -v to see what it would remove.

Does git worktree remove delete uncommitted changes?

Not without asking. Git refuses to remove a worktree with modified or untracked files unless you add --force, and with --force those changes are gone. Commit or stash them first if you want them.

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…