The Problem with `git stash`
You're deep in a feature, code scattered across half a dozen files, none of it compiling. Suddenly, a colleague asks you to drop everything and fix an urgent bug on the main branch. The immediate, ingrained response for many developers is git stash. Switch to main, fix the bug, commit, switch back, git stash pop. It's a familiar dance. But this ritual often leads to forgotten stashes, messy pop operations that create conflicts, and a general sense of unease about the state of your repository.
The core issue with git stash is that it's a temporary holding pen for your uncommitted changes. It doesn't represent a clean state, and managing multiple stashes, or even one that's been sitting for a while, can become a significant source of friction. What happens when the fix on main takes longer than five minutes? Or when you need to switch contexts again before popping the original stash? The complexity scales rapidly, and the risk of data loss or unexpected merge conflicts increases with each added layer.
This is not a new problem. Developers have grappled with context switching and managing unfinished work for years. The reliance on git stash, while functional, is often seen as a necessary evil rather than an optimal solution. It introduces a layer of indirection that can obscure the true state of your work and lead to confusion.
Introducing `git worktree`
Fortunately, Git has offered a more elegant solution for over a decade: a second working directory for the same repository. Introduced in Git version 2.5, the git worktree command allows you to check out multiple branches into separate directories, all sharing a single .git database. This means you get distinct working directories for each task, but they all point to the same commit history and object store. There's no duplication of repository data, no need to keep secondary clones in sync, and crucially, no more messy stashes.
Think of it less like juggling separate, unsaved documents and more like having multiple, clearly labeled notebooks on your desk, each dedicated to a different project. When an urgent request comes in, you simply close one notebook and open another. Your work in the first notebook remains exactly as you left it, untouched and ready for when you return.

How to Use `git worktree`
The process is remarkably straightforward. Suppose you are working on a new feature, `feature/new-api`, and have made uncommitted changes. Your repository is in this state:
/home/you/my-repo (feature/new-api *)$
$ git status
On branch feature/new-api
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: src/api.js
modified: src/utils.js
modified: tests/api.test.js
no changes added to commit (use "git add" and "git commit" to track)
An urgent bug fix is requested on the `main` branch. Instead of stashing, you create a new worktree:
/home/you/my-repo (feature/new-api *)$
$ git worktree add ../fix-bug main
Preparing C:\Users\you\my-repo\..\fix-bug\git\HEAD... done
... done
This command checks out the `main` branch into a new directory named `../fix-bug` (relative to your current working directory). This new directory is a fully functional Git working tree, independent of your original directory, but linked to the same repository database. You can now switch to this new directory and work on the bug fix.
/home/you/my-repo (feature/new-api *)$
$ cd ../fix-bug
/home/you/my-repo/../fix-bug (main *)$
$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
You can fix the bug, commit it to `main`, and then easily return to your original feature branch directory. The changes you made on `feature/new-api` are still there, exactly as you left them, ready for you to resume work.
Benefits Over `git stash`
The advantages of using git worktree over git stash are numerous:
- Clean Separation: Each worktree is a distinct directory with its own checkout of a branch. Your work is isolated and visible, not hidden in a stash.
- No Stash Conflicts: You avoid the common problem of
git stash popfailing or creating unexpected conflicts because the working directory is not being modified while the stash is applied. - Easier Context Switching: Simply `cd` into the appropriate directory. No need to remember to stash and pop.
- Reduced Mental Overhead: You don't have to keep track of what's in your stash or worry about losing it. The state of your work is always reflected in the files of the relevant directory.
- Resource Efficiency: While creating a new worktree does involve checking out files, it doesn't duplicate the entire repository's object database, making it much more efficient than cloning a repository multiple times.
When you are finished with a worktree, you can simply remove the directory and use git worktree prune to clean up any stale entries in the main repository's configuration.
Potential Downsides and Considerations
While git worktree is a powerful tool, it's not without its considerations. Each worktree requires disk space to store the checked-out files. For very large repositories or when dealing with many concurrent worktrees, this could become a factor. However, this is generally a more predictable and manageable use of disk space compared to the potential confusion and risk associated with extensive git stash usage.
Another point to consider is that while worktrees share the same .git database, they are separate working directories. Committing in one does not automatically update the other. This is by design, ensuring isolation. However, it means you must be mindful of which directory you are in when you run commands like git commit or git push.
What no documentation clearly articulates is the optimal strategy for managing *long-term* parallel development streams using worktrees. While excellent for short-term context switches, using worktrees for distinct, long-running feature branches alongside each other might require a disciplined approach to keep track of which worktree corresponds to which branch and development goal, especially if you deviate from a strict feature-branch-per-worktree model.
Conclusion
The git worktree command offers a robust, clean, and efficient alternative to the often-cumbersome git stash workflow for handling interruptions. By creating separate, independent working directories that share a single repository history, developers can switch contexts seamlessly without the risk of stash conflicts or lost work. If you find yourself frequently stashing and unstashing, it's time to explore the power of Git worktrees. It’s a feature that has been available for years, waiting to streamline your daily development workflow.
