git worktree remove: delete a worktree and fix every error

The exact command, then every error you can hit, with the message as git prints it. All of it was run on git 2.50.1.

To remove a git worktree, run git worktree remove with its path, from any checkout of the repository:

git worktree remove ../repo-feature-a

That deletes the worktree folder and git's record of it. It does not delete the branch. It refuses if the worktree has uncommitted changes (add --force) or is locked (unlock it first). There is no git worktree delete: remove is the command. Every error below is pasted from a real run.

Quick fixes

Remove a worktree

Pass the path exactly as git worktree list shows it. Absolute and relative paths both work.

git worktree list
git worktree remove ../repo-feature-a

A clean remove prints nothing. Run git worktree list again to confirm. Four things worth knowing:

fatal: '../repo-feature-a' contains modified or untracked files, use --force to delete it

The worktree has a changed tracked file or an untracked file that is not ignored, so git worktree remove will not delete it. See what it would lose:

git -C ../repo-feature-a status --short

To keep the work, commit it, or stash it. Stashes belong to the repository, not the worktree, so a stash survives the removal:

git -C ../repo-feature-a stash -u
git worktree remove ../repo-feature-a

To throw the work away, force it. This deletes the uncommitted changes for good, with no undo:

git worktree remove --force ../repo-feature-a

--force does not override a lock (see locked worktrees) and it is not needed for ignored files.

error: cannot delete branch 'feature-a' used by worktree at '/Users/you/code/repo-feature-a'

Git will not delete a branch that a worktree has checked out. Both git branch -d and git branch -D fail with this message. Remove the worktree first, then the branch:

git worktree remove ../repo-feature-a
git branch -d feature-a

If the branch has commits that are not merged, -d stops again:

error: the branch 'feature-a' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature-a'

Use git branch -D feature-a only when you are sure you do not need those commits. Two variations of the same error:

The mirror image, checking a branch out in a second worktree, is covered in the git worktree cheat sheet.

fatal: cannot remove a locked working tree

The full message has two lines. With no lock reason:

fatal: cannot remove a locked working tree;
use 'remove -f -f' to override or unlock first

With a reason, the first line carries it:

fatal: cannot remove a locked working tree, lock reason: on usb drive
use 'remove -f -f' to override or unlock first

Someone, or some tool, ran git worktree lock on it. git worktree list shows locked next to it, and git worktree list -v shows the reason. Unlock it, then remove it:

git worktree unlock ../repo-feature-a
git worktree remove ../repo-feature-a

Or do both in one step by passing force twice. A single --force is still refused:

git worktree remove -f -f ../repo-feature-a

Worktree folder deleted by hand: prunable

If you deleted the folder with rm -rf or Finder instead of git worktree remove, git still has a record of it. git worktree list marks it:

/Users/you/code/repo               097e9f9 [main]
/Users/you/code/repo-feature-a     097e9f9 [feature-a] prunable

Clear every stale record with prune. Add -n -v first to preview:

git worktree prune -n -v
git worktree prune

The preview prints one line per record, such as Removing worktrees/repo-feature-a: gitdir file points to non-existent location. git worktree remove ../repo-feature-a also works on a missing folder. Neither deletes the branch.

If you try to create the worktree again before pruning, git stops you:

fatal: '../repo-feature-a' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear

Run git worktree prune and repeat the add.

fatal: '../repo-feature-a' is a missing but locked worktree

The folder is gone and the worktree was locked, for example one on a drive that is not mounted. The full message:

fatal: '../repo-feature-a' is a missing but locked worktree;
use 'add -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear

git worktree prune skips a locked worktree without saying anything, which is why it seems to do nothing. Unlock first, then prune:

git worktree unlock ../repo-feature-a
git worktree prune

Or remove it in one step with git worktree remove -f -f ../repo-feature-a. If the drive is only unplugged, plug it back in instead: a lock exists to protect exactly that case.

fatal: '../repo' is a main working tree

You pointed git worktree remove at the original checkout, the one that holds the .git directory. Only linked worktrees can be removed. Check which one is which with git worktree list: the main worktree is always the first line. To get rid of the whole repository, remove the linked worktrees first, then delete the folder yourself.

fatal: '../repo-feature-b' is not a working tree

The path does not match any worktree, usually a typo or a path relative to the wrong directory. A plain folder that is not a worktree gives the same message. Copy the path from git worktree list.

fatal: working trees containing submodules cannot be moved or removed

Git refuses to remove a worktree that has an initialized submodule, even when nothing is uncommitted. Check the submodule for unpushed work, then force it:

git worktree remove --force ../repo-feature-a

Worktree folder moved by hand: git worktree repair

Moving a worktree folder with mv breaks the link between it and the main repository. Git then lists it as prunable at the old path, and pruning would forget it. Do not prune. Run repair from the main repository and pass the new path:

git worktree repair ../repo-feature-a-renamed
repair: gitdir incorrect: /Users/you/code/repo/.git/worktrees/repo-feature-a/gitdir

The repair: line confirms what was fixed. Without a path, git worktree repair found nothing to fix in this case, so pass the path. Next time use git worktree move ../repo-feature-a ../repo-feature-a-renamed, which updates both sides.

If you moved the main repository instead, every worktree breaks, and commands inside them print:

fatal: not a git repository: /old/path/repo/.git/worktrees/repo-feature-a

Run repair from the moved main repository and pass each worktree's path:

cd /new/path/repo
git worktree repair ../repo-feature-a
repair: .git file broken: /new/path/repo-feature-a

Remove many worktrees at once

This script, run from your main checkout, removes every worktree whose branch is already merged into main and then deletes that branch. It never forces: worktrees with uncommitted changes or a lock print their error and are skipped, and unmerged ones are not touched. Paths with spaces are fine.

#!/usr/bin/env bash
# Remove every linked worktree whose branch is already merged into main.
base=main
git worktree prune
main_path=$(git worktree list --porcelain | awk '/^worktree /{print substr($0,10); exit}')
git worktree list --porcelain |
  awk -v RS= -F'\n' '{
    path = ""; branch = ""
    for (i = 1; i <= NF; i++) {
      if ($i ~ /^worktree /) path = substr($i, 10)
      if ($i ~ /^branch refs\/heads\//) branch = substr($i, 19)
    }
    if (path != "" && branch != "") print path "\t" branch
  }' |
while IFS=$'\t' read -r path branch; do
  [ "$path" = "$main_path" ] && continue
  if git merge-base --is-ancestor "$branch" "$base"; then
    git worktree remove "$path" && git branch -d "$branch"
  fi
done

One catch: a branch with no commits of its own counts as merged, so a worktree you created a minute ago and have not touched is removed too. Read the list from git worktree list before you run it. To clear only stale records, a plain git worktree prune is enough.

Cleaning up after AI coding agents

Agent worktrees are ordinary git worktrees, so everything above applies, and they show up in git worktree list even when the tool created them somewhere else.

Clean up worktrees without the terminal

teebe is a free native macOS app that lists the worktrees of every repo you add. From teebe 0.8 it can also tell you which ones are safe to delete and remove them, using the same git worktree remove described above, never with --force.

A clean worktree that is not merged yet can still be removed from its right-click menu, with Remove Worktree…. Only the folder goes, and its branch is kept. teebe does not run git worktree repair or unlock anything for you. See git worktree managers for macOS for how it compares to the alternatives.

Frequently asked questions

Is there a git worktree delete command?

No. The command is git worktree remove <path>. It deletes the worktree folder and git's record of it, and leaves the branch alone. Typing git worktree delete prints error: unknown subcommand: `delete' and the list of real subcommands.

Does git worktree remove delete the branch?

No. The branch and its commits stay. Delete the branch afterwards with git branch -d <branch>, or git branch -D <branch> if it is not merged. Git refuses to delete a branch while a worktree still has it checked out, so remove the worktree first.

How do I remove a worktree that has uncommitted changes?

Either commit or stash the changes first, or run git worktree remove --force <path>, which deletes the folder and the uncommitted changes for good. Stashes are shared by all worktrees of a repository, so a stash made inside the worktree survives its removal.

What does git worktree prune do?

It deletes git's records of worktrees whose folder no longer exists, for example one you removed with rm -rf or Finder. It never touches a locked worktree or a branch. Run git worktree prune -n -v first to see what it would remove.

How do I remove a locked worktree?

Run git worktree unlock <path>, then git worktree remove <path>. To do it in one step, pass force twice: git worktree remove -f -f <path>. A single --force is not enough for a locked worktree.

How do I delete a worktree I already deleted by hand?

Run git worktree prune. Git still lists the worktree, marked prunable, until you do. git worktree remove <path> also works for a missing folder. Neither deletes the branch.

curl -fsSL https://teebe.io/install.sh | bash

Free · open source · macOS 14+. Back to teebe.io →