How to Remove a Git Worktree (The Right Way)

TL;DR

git worktree remove <path>          # clean removal
git worktree remove --force <path>  # with uncommitted changes
git worktree prune                  # clean up stale references

These three commands cover 99% of worktree removal. The rest of this article explains when to use each, what can go wrong, and how to recover.


Why Not Just rm -rf?

The #1 worktree mistake is treating it like a normal folder:

rm -rf ../myapp-old-feature  # ❌ DON'T DO THIS

This deletes the files but leaves metadata inside the main repo pointing at the now-missing worktree:

.git/worktrees/myapp-old-feature/

Now Git thinks the worktree still exists. You'll see:

  • git worktree list shows a ghost entry
  • git branch -d feat/old-feature fails with "Cannot delete branch checked out at ..."
  • Some Git operations may produce odd warnings

Correct flow: use git worktree remove — it handles both the files and the metadata.


The Clean Path: git worktree remove

git worktree remove ../myapp-old-feature

This succeeds when:

  • ✅ The worktree has no uncommitted changes
  • ✅ The worktree has no untracked files (or they're all gitignored)
  • ✅ The worktree isn't locked

Git deletes the folder and the metadata in one atomic step. No stale state.

After removal, the branch itself still exists:

git branch -d feat/old-feature   # merged branches
git branch -D feat/old-feature   # force (unmerged)

For the specific "Cannot delete branch" error during branch -d, see Fix: Cannot Delete Branch Used by Worktree.


When Clean Remove Refuses: --force

If the worktree has uncommitted changes:

$ git worktree remove ../myapp-old-feature
fatal: '../myapp-old-feature' contains modified or untracked files, use --force to delete it

Your options:

cd ../myapp-old-feature
git status                    # what's uncommitted?
git stash                     # stash it
# or
git add . && git commit -m "WIP"
# or
git push origin HEAD          # back it up remotely

cd -
git worktree remove ../myapp-old-feature

Option B: Force it (if you know changes are disposable)

git worktree remove --force ../myapp-old-feature

--force deletes the folder along with any uncommitted work. There is no recovery — the changes are gone.


Cleaning Up Stale Worktrees: prune

git worktree prune scans .git/worktrees/ and removes metadata for worktrees whose folders no longer exist:

git worktree prune

Use this when:

  • You (or a teammate) accidentally rm -rf'd a worktree folder
  • You moved the worktree to external media that's now disconnected
  • A crash left orphaned metadata

Add -v to see what's being pruned:

git worktree prune -v
# Removing worktrees/myapp-crashed: gitdir file points to non-existent location

For a preview without actually pruning:

git worktree prune --dry-run --verbose

Locked Worktrees Need Unlocking First

Worktrees can be locked to protect them from accidental pruning (e.g., a worktree on a USB drive that isn't always connected):

$ git worktree remove ../myapp-on-usb
error: cannot remove a locked working tree, lock reason: USB drive

Unlock, then remove:

git worktree unlock ../myapp-on-usb
git worktree remove ../myapp-on-usb

Or force past the lock (risky if the folder is legitimately unavailable):

git worktree remove --force ../myapp-on-usb

Real-World Scenarios

Scenario 1: Finished a feature, merging cleanly

cd ~/projects/myapp-feat-auth
git push origin feat/auth
# create PR, get it merged
cd ~/projects/myapp
git fetch origin && git pull
git worktree remove ../myapp-feat-auth
git branch -d feat/auth

Scenario 2: Abandoned experiment

cd ~/projects/myapp
git worktree remove --force ../myapp-crazy-idea
git branch -D experiment/crazy-idea

Scenario 3: Recovering from rm -rf

git worktree list            # shows ghost entry
git worktree prune -v        # cleans metadata
git branch -D feat/lost      # now you can delete the branch

Scenario 4: Worktree on unplugged external drive

git worktree list
# /Volumes/USB/myapp-backup  (unavailable: lock reason: USB offline)

git worktree unlock /Volumes/USB/myapp-backup
git worktree remove --force /Volumes/USB/myapp-backup
# or, if you just want to forget it exists:
git worktree prune

Removing Worktrees in Bulk

For cleanup day, when you have 10 worktrees to kill:

Script: Remove all worktrees except the main one

git worktree list --porcelain | awk '
  /^worktree / { wt=$2 }
  /^bare/ { next }
  /^$/ { if (wt && wt != main) print wt; wt="" }
  NR==1 { main=$2 }
  END { if (wt && wt != main) print wt }
' | xargs -I{} git worktree remove --force {}

⚠️ This deletes uncommitted changes in every worktree except main. Dry-run first:

git worktree list --porcelain | awk '/^worktree / && $2 != "'"$(pwd)"'" { print $2 }'

Interactive: pick-and-delete with fzf

git worktree list | fzf -m | awk '{print $1}' | xargs -I{} git worktree remove {}

-m allows multi-select with tab. Much safer than bulk-kill.


What git worktree remove Does NOT Do

  • ❌ Does not delete the branch (that's git branch -d)
  • ❌ Does not push your branch to origin (commit/push first!)
  • ❌ Does not recover after --force — gone is gone
  • ❌ Does not prune OTHER stale worktrees (that's prune)

Be explicit about each step in cleanup scripts.


Why Bulk Cleanup Gets Annoying

If you're using worktrees heavily — say, one per AI coding task — you'll accumulate them fast. After a week:

myapp                       # main
myapp-feat-auth             # merged 3 days ago
myapp-feat-search           # abandoned
myapp-bug-203               # merged 2 days ago
myapp-explore-postgres      # maybe use later?
myapp-refactor-api          # WIP
myapp-docs-update           # merged yesterday

Terminal cleanup rituals get old fast. This is what ParallelCode solves: all your worktrees in one dashboard, with status, last-activity, merge state, and a one-click "archive" or "delete" for each.

Download ParallelCode → — free, and worth the 30 seconds of install to never git worktree prune by hand again.


Summary: Removal Checklist

Before running git worktree remove:

  • Have you committed or pushed your work? (git status in the worktree)
  • Do you also want to delete the branch? (git branch -d after)
  • Is the worktree locked? (git worktree unlock)
  • Is the folder still there? (if not → git worktree prune)

Commands:

git worktree remove <path>          # 99% of the time
git worktree remove --force <path>  # accept data loss
git worktree prune                  # if folder is already gone
git worktree unlock <path>          # if locked
git branch -d <branch>              # after removal, delete branch

Related posts