Worktrees Over Branches
The standard git workflow is: stash your changes, switch branches, do the other thing, switch back, pop your stash, hope nothing conflicted. It works. It’s also terrible.
The Branch Lie
Branches are marketed as cheap context switches. “Just git checkout feature-x and you’re there!” But your working directory is a single physical location. When you switch branches, every file changes on disk. Your editor reloads. Your build cache is invalid. Your test state is gone.
That’s not a context switch. That’s a context demolition.
And if you have uncommitted work — which you always do, because real development isn’t a clean sequence of atomic commits — you need to stash it. Stashes are a stack with no labels (yes, you can add messages, but nobody does). Multiple stashes become a game of “which one was this?” And git stash pop on the wrong branch is a special kind of pain.
The Worktree Fix
Git worktrees give you what branches promise: actual parallel workspaces. Each worktree is a separate directory with its own working tree, checked out to its own branch. Your main checkout stays untouched.
# Create a worktree for a feature branch
git worktree add ../trees/feature-x
# Or from a specific parent
git worktree add ../trees/bugfix-y main
# List active worktrees
git worktree list
# Clean up when done
git worktree remove ../trees/feature-x
Now you have two (or five, or ten) checkouts. Each one has its own build state, its own editor session, its own uncommitted experiments. Switching context means changing directories, not changing the universe.
When It Matters
Worktrees shine in three scenarios:
Interrupt-driven work. You’re deep in a feature when a bug report comes in. Without worktrees, you stash, switch, fix, commit, switch back, pop, re-orient. With worktrees, you cd to the bugfix worktree, fix it, commit, cd back. Your feature branch didn’t move.
Long-running builds. If your project takes minutes to compile, a branch switch means waiting for a full rebuild. Worktrees maintain separate build directories. The feature branch is already compiled and waiting.
Code review. You want to test someone’s PR without disturbing your current work. Check it out in a worktree, run the tests, delete the worktree. Zero impact on your main checkout.
The Naming Convention
A convention that works well: put all worktrees under a trees/ directory adjacent to your main checkout, named by ticket ID and a short description.
project/
.git/
src/
Makefile
trees/
PROJ-00045-expansion-step/
PROJ-00046-cover-generation/
hotfix-null-check/
The ticket ID prefix makes it easy to cross-reference with your task tracker. The short description tells you what’s in there without opening it. When the ticket is done, git worktree remove and optionally delete the branch.
The Catch
Worktrees have one real limitation: you can’t have two worktrees on the same branch. This is by design — allowing it would create conflicting working states for the same ref. But it means your main branch is always “claimed” by your primary checkout. If you want to test against main, you do it there.
The other catch is tooling awareness. Some editors and IDE plugins assume one repository means one working directory. They might get confused by worktrees. Terminal-based workflows handle this naturally — it’s just directories.
The Point
The best tools are the ones that match how you actually work rather than how the tool’s documentation says you should work. Nobody works on one thing at a time. Nobody has a perfectly clean git state before they need to do something else. Worktrees acknowledge that reality instead of fighting it.
git stash is a bandage. git worktree is the fix.