The problem worktrees solve
You are mid-feature when an urgent hotfix request arrives. Stashing or context-switching is risky and slow. Worktrees let you check out additional branches into separate directories, all sharing one underlying object database. Each worktree has its own HEAD, index, and working tree.
Adding a worktree
git worktree add ../hotfix main
cd ../hotfix
git checkout -b hotfix/urgent
# fix the bug, push, return
cd -
git worktree remove ../hotfix
The new directory is a full working copy. .git there is a small file pointing into the main repo's .git/worktrees/<name> metadata.
Listing and pruning
git worktree list
git worktree list --porcelain
git worktree prune
git worktree remove ../old-feature
git worktree lock ../release # prevent prune
git worktree unlock ../release
Lock worktrees on removable media to prevent prune from clearing them when offline.
Detached worktrees
Need a quick read-only checkout of a tag?
git worktree add --detach ../v1.0 v1.0.0
No branch is created; HEAD is detached at the tag.
Branch sharing rules
The same branch cannot be checked out in two worktrees simultaneously, by design — it would let two indexes claim authority over one branch ref. Force this with --force only if you understand the consequences.
Use cases
- Long-running CI build in one worktree while you keep coding.
- Side-by-side comparison of two branches in your editor.
- Bisecting in a worktree while your main checkout stays put.
- Running multiple language versions or container builds in parallel.
Configuration
Per-worktree config (Git 2.20+) keeps machine-specific settings isolated:
git config --worktree user.email [email protected]
Enable with git config extensions.worktreeConfig true.
Common mistakes
Removing a worktree directory with rm -rf instead of git worktree remove leaves stale metadata; git worktree prune cleans up. Trying to share a hooks directory across worktrees: hooks live under the main .git and run for all worktrees, which can be surprising. Bare repositories make excellent worktree hubs — git clone --bare then add worktrees off it.
Related
See "Sparse checkout: working with subsets of a large repo" and "Background maintenance: git maintenance run/start/stop", which is worktree-aware.