Git worktrees in practice

· git

The reflex when you need to look at another branch mid-task is git stash, switch, look, switch back, git stash pop — and hope nothing went sideways with the stash. Worktrees remove the whole dance: one repository, several checked-out directories, each sitting on its own branch, all sharing a single object store.

The core commands

# from inside the repo
git worktree add ../app-hotfix hotfix/login

../app-hotfix is now a complete working copy checked out on hotfix/login. You can build it, run it, open it in a second editor window — and your main checkout never moves. No stash, no half-finished work shoved aside.

To branch and create the worktree in one step:

git worktree add -b feature/search ../app-search origin/main

That creates a new branch feature/search off origin/main and checks it out into ../app-search. List what you've got and clean up when done:

git worktree list
git worktree remove ../app-hotfix

Where this actually pays off

Three situations where worktrees beat stashing every time:

  • An urgent hotfix while you're deep in a feature. Spin up a worktree on the release branch, fix, push, delete it. Your feature branch is untouched — no stash to forget about, no "wait, did I pop that?"
  • Long-running builds or test suites. Keep one worktree compiling or running the suite while you keep editing in another. They share history but have independent working trees, so a build in one doesn't lock the other.
  • Reviewing a colleague's branch. Check it out into a throwaway worktree, read and run it with your main work still open side by side, then remove it.

Because every worktree shares the same .git object store, adding one costs almost nothing — no re-clone, no duplicated history, just a fresh index and working copy.

The rules to know

You can't check out the same branch in two worktrees. Git refuses, and that's a feature: it stops you from having two directories fighting over what main should contain. If you need two views of the same branch, branch off it.

A detached worktree is fine. git worktree add --detach ../peek HEAD gives you a scratch checkout at a specific commit with no branch attached — handy for bisecting or testing an old state without disturbing anything.

Don't delete a worktree with rm -rf

This is the one that bites. A linked worktree directory looks exactly like a stray clone, so the instinct is to rm -rf it when you're done. Do that and Git keeps a dangling administrative entry pointing at a directory that no longer exists — git worktree list still shows it, and you get confusing errors later.

Remove it properly:

git worktree remove ../app-hotfix

If you already deleted the directory by hand, clean up the leftover bookkeeping:

git worktree prune

prune drops the stale entries for worktrees whose directories are gone. Run it and git worktree list is honest again.

A practical habit: before you ever rm -rf a directory that lives next to a repo, run git worktree list first. If the path shows up there, it's a linked worktree — use git worktree remove, not the file manager. That one check has saved me from a tangled .git/worktrees more than once.

When not to bother

For a quick one-line peek at another branch, git stash is still less ceremony. Worktrees earn their keep when the context switch is expensive — a dirty tree you don't want to disturb, a build you don't want to restart, a review you want open alongside your own work. Reach for them when stashing starts to feel risky, and skip them when it doesn't.

Common problems

fatal: 'main' is already checked out

You're trying to add a worktree on a branch that another worktree already has. Git allows a branch in only one worktree at a time. Either switch that other worktree off the branch, or create a new branch off it: git worktree add -b review ../peek main.

A deleted worktree still shows in git worktree list

You removed the directory with rm -rf instead of git worktree remove, leaving a stale admin entry behind. Clean it up with git worktree prune, then git worktree list is accurate again.

git worktree remove refuses because of changes

The worktree has uncommitted modifications or untracked files and Git won't throw them away silently. Commit or stash what you want to keep first; if you're sure it's disposable, git worktree remove --force ../path.