Need a quick command reference? Check the Git Cheat Sheet.
Picture this.
It’s 4:30pm on a Friday. You’ve been building a new dashboard feature for three days. You’re in flow. The code is half-done, your editor has 12 files open, and you finally understand the data model.
Then Slack pings.
“Hey, prod is down. The payment flow is broken. Can you take a look ASAP?”
Now what? You can’t commit half-baked code. You could stash — but stashes are a mess, you always forget what’s in them, and restoring one mid-panic is its own adventure. You could clone the repo again into a different folder… but that feels wrong.
There’s a better way. It’s been in Git since 2015. Most developers have never heard of it.
It’s called a worktree.
What a Worktree Actually Is
When you clone a repo, you get one working directory tied to one branch at a time. That’s the default. That’s always been the assumption.
A Git worktree breaks that assumption. It lets you check out a second branch into a second folder — connected to the same repository, sharing the same git history, objects, and commits. No second clone. No duplication of your entire node_modules.
Think of it like having two desks for the same project. Your main desk has the feature branch open. You spin up a second desk — minimal, clean — and work the hotfix there. When you’re done, you fold up the second desk. Your main desk is exactly how you left it.
The Five Commands You Need
# Add a new worktree on a new branch
git worktree add ../my-hotfix -b hotfix/payment-crash
# Add a worktree for an existing branch
git worktree add ../review-pr-42 origin/feature/auth-revamp
# See all your active worktrees
git worktree list
# Remove a worktree when you're done
git worktree remove ../my-hotfix
# Clean up any stale worktrees (if you deleted the folder manually)
git worktree prune
That’s the whole API. Five commands. The rest is just using your editor in a different folder.
The Friday Hotfix Scenario (Step by Step)
Let’s go back to that Slack message. Here’s exactly what you do:
# You're in your project folder, mid-feature
# Current branch: feature/new-dashboard
# Status: 8 modified files, not ready to commit
# Step 1: Create a worktree for the hotfix
git worktree add ../myapp-hotfix -b hotfix/payment-crash main
# This creates a NEW folder called myapp-hotfix
# It's based on main (clean, no your half-done code)
# Your current folder is completely untouched
Now open a new terminal tab, cd into the hotfix folder:
cd ../myapp-hotfix
# Fresh checkout of main. Install deps if needed.
npm install
# Find the bug, fix it
code .
Fix the bug. Commit it. Push it. Deploy.
git add src/payments/checkout.ts
git commit -m "fix: handle null customer ID in payment flow"
git push origin hotfix/payment-crash
Done. Go back to your feature branch:
cd ../myapp
# Everything is exactly where you left it.
# Your 8 modified files. Your flow state. Your 12 open tabs.
You just handled a prod incident without touching your feature branch once.
The PR Review Scenario
This one comes up all the time. A colleague asks you to review their code — but you want to actually run it, not just read the diff on GitHub.
Without worktrees, you’d have to stash your current changes, check out their branch, run the code, then switch back. Annoying.
With worktrees:
# Check out their branch in a separate folder
git worktree add ../review-sarah-auth origin/feature/new-auth-flow
cd ../review-sarah-auth
npm install
npm run dev # their code running on port 3000
Your feature branch is still running in the original folder — maybe on port 3001. You can switch between them in your browser. Compare behavior side by side.
When you’re done reviewing:
cd ~/projects/myapp
git worktree remove ../review-sarah-auth
Clean. No switching. No stashing. Sarah’s branch never touched your work.
The “I Need to Test the Old Version” Scenario
You shipped a feature last week. A user is reporting weird behavior that might be a regression. You want to run the old version alongside the new version to compare.
# Current code in ~/projects/myapp (new version)
# Check out last week's release tag in a separate folder
git worktree add ../myapp-old v2.1.4
cd ../myapp-old
npm install
PORT=4000 npm run dev # old version on port 4000
# Back to main terminal
cd ~/projects/myapp
PORT=3000 npm run dev # new version on port 3000
Now open both in your browser. Compare. Find the regression. No Docker, no VMs, no second clone.
One Rule: No Two Worktrees on the Same Branch
This is the one thing Git won’t let you do:
# This will fail if main is already checked out somewhere
git worktree add ../another-main main
# error: 'main' is already checked out at '/home/you/projects/myapp'
It makes sense — two worktrees can’t be on the same branch simultaneously because they’d conflict on what HEAD means. The workaround is to create a new branch:
git worktree add ../another-main -b temp/main-copy main
But honestly, if you need this, you probably have a different problem.
Where to Put Your Worktrees
Convention that works well: keep all worktrees as siblings of the main repo folder.
~/projects/
myapp/ ← main worktree (your feature branch)
myapp-hotfix/ ← temporary hotfix worktree
myapp-review-pr42/ ← PR review worktree
This way they’re easy to find, easy to delete, and git worktree list gives you a clean map:
/home/you/projects/myapp abc1234 [feature/new-dashboard]
/home/you/projects/myapp-hotfix def5678 [hotfix/payment-crash]
/home/you/projects/myapp-review-pr42 ghi9012 [feature/new-auth-flow]
What Gets Shared, What Doesn’t
This trips people up at first.
Shared across all worktrees (lives in .git/):
- Entire commit history
- All branches and tags
- Stashes (though you won’t need them anymore)
- Config, remotes, hooks
Separate per worktree (lives in the folder itself):
- Working directory files
node_modules/(each worktree has its own — or can share via symlink if you’re clever).envfiles (you’ll need to copy these)- Build output (
dist/,.next/, etc.)
The implication: if your repo is 2GB because of node_modules, each worktree will need its own install. That’s the main cost. For most projects it’s fine — you’re not keeping more than 2–3 worktrees active at any time.
Cleaning Up
Worktrees don’t clean themselves. A quick habit: when you merge or close a branch, remove the worktree.
# The clean way
git worktree remove ../myapp-hotfix
# If the folder is already gone (you deleted it manually)
git worktree prune
# Nuclear: list everything and decide
git worktree list
If you try to remove a worktree that has uncommitted changes, Git will stop you:
git worktree remove ../myapp-hotfix
# error: '../myapp-hotfix' contains modified or untracked files, use --force to delete it
Use --force only if you’re sure you don’t need those changes.
The Alias That Makes This Faster
Add this to your ~/.gitconfig:
[alias]
wt = worktree
wtl = worktree list
wta = worktree add
wtr = worktree remove
Now:
git wta ../myapp-hotfix -b hotfix/thing main
git wtl
git wtr ../myapp-hotfix
When to Use Worktrees vs. Stash
| Situation | Use |
|---|---|
| Quick 2-minute context switch | git stash |
| Hotfix while mid-feature | Worktree |
| Running a PR branch to test it | Worktree |
| Comparing old vs. new version | Worktree |
| Long-running parallel work streams | Worktree |
| You just need to check one file on another branch | git show branch:path/to/file |
Stash is for “I’ll be back in five minutes.” Worktrees are for “I need to actually work here for a while.”
The Real Unlock
The reason worktrees feel so good once you start using them: your main workspace is sacred again.
No more “did I stash the right things?” No more “wait, which branch was I on?” No more mid-hotfix panic where you realize you committed half your feature by mistake.
The feature branch stays untouched. The hotfix gets a clean room to live in. And when it’s done, you fold it up and it’s like it was never there.
It’s one of those Git features that, once you know it, you can’t imagine working without it.