DEV Community

James Joyner
James Joyner

Posted on Originally published at moderngitacademy.com AI-assisted

Stop Stashing. Use a Second Working Directory for the Interruption.

"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
Enter fullscreen mode Exit fullscreen mode
 M wip.txt
Enter fullscreen mode Exit fullscreen mode

Now, instead of stashing, add a worktree for the hotfix, on a new branch from main:

git worktree add ../hotfix -b hotfix main
Enter fullscreen mode Exit fullscreen mode
Preparing worktree (new branch 'hotfix')
HEAD is now at 3b87f1e Initial commit
Enter fullscreen mode Exit fullscreen mode
git worktree list
Enter fullscreen mode Exit fullscreen mode
/home/you/app     f08c49f [feature/long-running]
/home/you/hotfix  3b87f1e [hotfix]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
## hotfix
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
4090a55 Fix login redirect
Enter fullscreen mode Exit fullscreen mode

Push it, open the pull request, whatever the process is. Then go back:

cd ../app
git status --short --branch
cat wip.txt
Enter fullscreen mode Exit fullscreen mode
## feature/long-running
 M wip.txt
wip
uncommitted
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
Preparing worktree (checking out 'feature/long-running')
fatal: 'feature/long-running' is already used by worktree at '/home/you/app'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
/home/you/app  f08c49f [feature/long-running]
* feature/long-running
  hotfix
  main
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)