Git Worktrees: Check Out Multiple Branches Without Stashing
Git worktree creates a second working directory sharing the same object store, so you can check out a different branch without disturbing your current one.
04 Aug 2026, 15:36 UTC

The problem: branch switching interrupts your flow
Mid-task, a hotfix lands on main while you are deep in a feature branch. The usual options are disruptive: stash your changes, commit a work-in-progress snapshot, or clone the repository again and wait for the object download. If your build tools cache artifacts per directory, even a quick git checkout forces a rebuild.
git worktree removes that friction. It attaches a second working directory to the same repository, letting you check out a different branch in a separate folder while your original directory stays exactly as you left it.
The fix: git worktree add
Run git worktree add <path> <branch> from your existing repository. Git creates a new directory at <path> with <branch> checked out. Your current working tree is untouched. No clone, no stash, no second download of history.
How it works: shared objects, separate checkouts
A worktree is not a copy. When you add one, Git creates a lightweight pointer directory that references the original repository's .git directory. Both worktrees share the same object database—commits, trees, blobs, and tags are stored once. Each worktree maintains its own HEAD, index, and working files.
Think of it as two doors into the same storage room. The shelves (objects) are identical, but what sits on the workbench (the checked-out files) is independent in each room.
A worked example
Assume you are in /srv/app on branch main and need to review a pull request in feature/payments. From the main worktree, run:
git worktree add ../app-payments feature/payments
Git creates /srv/app-payments and checks out feature/payments there. Changing into that directory and running git rev-parse --abbrev-ref HEAD returns feature/payments. Returning to /srv/app and running the same command still returns main. The two directories now track different branches from one shared history.
Verify the setup
After adding a worktree, confirm the state from either directory:
git worktree listshows every registered worktree with its path, commit hash, and branch. You should see the original path and the new path. If an entry is markedprunable, its administrative metadata is stale.git rev-parse HEADin each worktree returns different commit hashes that match the intended branches.git fsck --unreachablerun in the main worktree and in the linked worktree reports the same unreachable objects, confirming they share one object database.
Limits and common mistakes
Bare repositories and detached HEAD
Worktrees are designed for standard non-bare repositories. A bare repository lacks a conventional working tree, and git worktree add will fail or behave unexpectedly there. Likewise, keep the main worktree on a proper branch rather than a detached HEAD—a state where HEAD points directly to a commit instead of a branch name—because some Git versions produce errors or confusing metadata when adding worktrees from that state.
Stale locks and manual deletion
Each worktree has an administrative directory under .git/worktrees/<name>/ containing a lock file. If you delete the working directory with rm -rf instead of using Git's removal command, the lock remains. git worktree list will then show the entry as prunable. Clean it with git worktree prune. If pruning is insufficient, manually remove the stale lock file inside .git/worktrees/<name>/.
Shared object store and garbage collection
Because both worktrees share objects, running git gc --prune=now in one worktree can delete objects that are only referenced by the other worktree's index or refs. Avoid aggressive garbage collection across worktrees. If you must run GC, do it from the main worktree and avoid --prune=now unless you are certain no other worktree holds unreferenced-but-needed objects.
Concurrent edits
Git does not prevent you from editing the same file in two worktrees. If you modify src/app.js in both, there is no merge conflict warning—you simply have two divergent copies. Treat each worktree as a separate checkout and avoid editing identical paths simultaneously.
Removing a worktree cleanly
When you no longer need the linked directory, remove it from the main worktree:
git worktree remove ../app-payments
This deletes the working directory and its administrative metadata. If you already deleted the directory manually, run git worktree prune to clear stale entries. After removal, git worktree list should show only the original repository, and git status in the main worktree should be unchanged.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.