"Can you look at the login bug on main? Five minutes." You are forty minutes into a feature, with edits in six files that do not compile yet. The usual answer is git stash, switch, fix, switch back, git stash pop — and a stash you forget about, or a pop that conflicts with something you did in between.
There is a better tool, and it has been in Git since 2.5: a second working directory for the same repository.
One repository, two directories
git worktree add checks out a branch into a new directory that shares the same .git database. Two checkouts, one history, no copying of objects, no second clone to keep in sync. Every command below was run in a disposable repository (git 2.43.0); the output is real, with the temporary directory shown as /home/you for readability.
Start where the interruption happens — on a feature branch with uncommitted work:
git status --short
M wip.txt
Now, instead of stashing, add a worktree for the hotfix, on a new branch from main:
git worktree add ../hotfix -b hotfix main
Preparing worktree (new branch 'hotfix')
HEAD is now at 3b87f1e Initial commit
git worktree list
/home/you/app f08c49f [feature/long-running]
/home/you/hotfix 3b87f1e [hotfix]
Two directories. Your feature checkout is untouched — wip.txt still has its uncommitted edit. The new one is a clean checkout of main on a fresh hotfix branch.
Fix, commit, push — without touching the feature
cd ../hotfix
git status --short --branch
## hotfix
Clean. Make the fix and commit it here:
echo "fix" > fix.txt
git add . && git commit -q -m "Fix login redirect"
git log --oneline -1
4090a55 Fix login redirect
Push it, open the pull request, whatever the process is. Then go back:
cd ../app
git status --short --branch
cat wip.txt
## feature/long-running
M wip.txt
wip
uncommitted
Exactly as you left it. No stash, no pop, no conflict, no context lost. The editor windows you had open are still open on the right files, because the files never changed.
The rule Git enforces
One branch can be checked out in one worktree at a time. Try to check the feature branch out again:
git worktree add ../dup feature/long-running
Preparing worktree (checking out 'feature/long-running')
fatal: 'feature/long-running' is already used by worktree at '/home/you/app'
This is the safety property: two directories can never race each other for the same branch pointer. If you genuinely want the same commit twice, --detach gives you a detached HEAD in the second directory.
Clean up
When the hotfix is merged, remove the worktree. The branch survives; only the directory and its registration go:
git worktree remove ../hotfix
git worktree list
git branch
/home/you/app f08c49f [feature/long-running]
* feature/long-running
hotfix
main
If you rm -rf a worktree directory by hand instead, Git notices on the next list and marks it:
/home/you/app f08c49f [feature/long-running]
/home/you/tmp-wt 4090a55 [tmp] prunable
git worktree prune clears the stale entry.
When to reach for it
- The interruption. The case above. Also code review: check the reviewer's branch out beside your own and run both.
- Long builds. Kick off a build in one worktree while you keep editing in another — no "don't touch anything, it's compiling".
- Comparing versions. Two worktrees, two versions, a diff tool pointed at both directories.
And when not to: a worktree shares the repository's config, hooks and index-independent state, so it is not a sandbox for experiments with .git itself, and it is not a substitute for a branch when what you need is just a branch.
The hands-on version — with a deliberate mistake to make and recover from — is the lab: Parallel work with Git worktrees. The concept it sits on, that a branch is a pointer and a checkout is a directory, is Git branches explained.
Top comments (0)