Sitemap

Git Worktree: Stop Stashing, Start Working

5 min readMar 31, 2026

--

Press enter or click to view image in full size

You’re deep in a feature branch. Tests are passing, the logic is flowing, and you’re finally in the zone when a Slack message drops:

“🔥 Production is down. Login is broken.”

The old you would git stash, switch branches, fix the bug, pop the stash, resolve whatever conflicts crept in, and then try and fail to remember where your train of thought was.

There’s a better way, and it’s been hiding in plain sight.

What is Git Worktree?

Introduced in Git 2.5 (2015), git worktree lets you check out multiple branches of the same repository into separate directories — simultaneously, without cloning — all sharing a single .git folder.

Get Aditya Padekar’s stories in your inbox

Join Medium for free to get updates from this writer.

Think of it as tabs for your terminal. Each worktree is an independent working directory with its own branch checked out, its own uncommitted changes, and its own build artifacts. They all live in the same repo, share the same history, and stay in perfect sync.

~/repos/my-app/               ← main worktree (your usual clone)
│ .git/ ← single git store, shared by all
│ src/
│ package.json
│
~/worktrees/my-app-hotfix/ ← linked worktree (branch: hotfix/login)
│ src/
│ package.json
│
~/worktrees/my-app-review/ ← linked worktree (branch: feat/payments)
src/
package.json

💡 Quick distinction: A worktree is not a clone. Clones duplicate the entire .git object store. Worktrees share it — they're lightweight pointers to a branch, not copies of a repo.

Why You Need It

The everyday pain of context switching in Git is real. Every developer has faced some version of this scenario:

😩 Without Worktrees

  • Stash half-done work
  • Switch branch, fix bug
  • Run tests, wait…
  • Switch back, pop stash
  • Resolve merge conflicts
  • Lose your mental context
  • Repeat. Regret. Repeat.

✅ With Worktrees

  • Open a second terminal
  • git worktree add
  • Fix bug in isolation
  • Run tests independently
  • Keep your feature branch untouched
  • Review PRs without switching
  • Parallel builds, no conflicts

“The best feature branches are the ones you never have to leave.”

Anatomy of a Worktree

When you run git worktree add, Git creates a new directory (wherever you point it) containing a gitfile — a tiny file that reads like a symlink back to the shared .git/ store. Inside that store, Git tracks linked worktrees in .git/worktrees/.

# These files exist for each linked worktree:
gitdir ← path back to the linked worktree's .git file
HEAD ← which branch/commit this worktree is on
index ← its own staging area
lock ← prevents accidental pruning (optional)

Each worktree has its own HEAD, index (staging area), and working tree — but shares the object database, refs, and remotes. This means git fetch in any worktree updates all of them instantly.

Essential Commands

Add a Worktree

# Add worktree for an existing branch
git worktree add ../my-app-hotfix hotfix/login-bug

# Create a new branch + worktree in one command
git worktree add -b feat/payments ../my-app-payments main

# Check out a detached HEAD (useful for bisect / review)
git worktree add ../my-app-review abc1234

List Worktrees

git worktree list

/home/vinay/repos/my-app a1b2c3d [main]
/home/vinay/worktrees/my-app-hotfix d4e5f6a [hotfix/login-bug]
/home/vinay/worktrees/my-app-review 7g8h9i0 [feat/payments]

Remove a Worktree

# Clean removal (worktree must have no uncommitted changes)
git worktree remove ../my-app-hotfix

# Force removal even if there are untracked changes
git worktree remove --force ../my-app-hotfix

# If you deleted the directory manually, clean up git's refs
git worktree prune

Real-World Workflows

🔥 The Emergency Hotfix: A bug’s burning in production. You’re knee-deep in a feature. Don’t stash. Don’t panic. Open a worktree.

# While on feat/my-big-feature — DON'T stash, just:
git worktree add -b hotfix/payment-null ../app-hotfix main

cd ../app-hotfix

# Fix the bug, test, commit, push — feature untouched
git push origin hotfix/payment-null

# Merge, then clean up
git worktree remove ../app-hotfix
git branch -d hotfix/payment-null

👀 Code Review Without Switching: Reviewing a colleague’s PR doesn’t have to interrupt your work. Check it out in a fresh worktree, run the app, and review — your branch stays pristine.

git fetch origin
git worktree add ../app-pr-142 origin/feat/dashboard-redesign

cd ../app-pr-142
# Install deps, run the dev server, review in browser
npm install && npm run dev

# Done reviewing — tear it down
git worktree remove ../app-pr-142

🧪 Parallel Benchmarking: Want to benchmark your optimization against the original? Spin up two worktrees and run them side by side.

# Terminal 1 — baseline
git worktree add ../app-baseline main
cd ../app-baseline && npm run bench

# Terminal 2 — your optimization branch
cd ../app && npm run bench

# Compare output side by side — no switching needed

🔍 git bisect Across Worktrees: Running git bisect in a worktree means you can hunt a regression without abandoning your current work.

git worktree add ../app-bisect main
cd ../app-bisect

git bisect start
git bisect bad # current commit is broken
git bisect good v1.2.0 # this one was fine
# git handles the rest — test, mark good/bad, repeat

Gotchas & Limitations

  • You can’t check out the same branch twice. Git will refuse to create a worktree for a branch that’s already checked out elsewhere. Use a new branch or a detached HEAD for review tasks instead.
  • node_modules are not shared. Each worktree has its own independent working directory, which means separate node_modules. You'll need to install dependencies in each one. It's isolated by design, but be mindful of disk usage.
  • .env files don't copy over. If your .env is gitignored (as it should be), you'll need to manually copy or symlink it into new worktrees.
  • Rebasing shared branches is risky. If you rebase a branch that’s currently checked out in another worktree, things can get messy. Prefer merging when multiple worktrees are sharing history.

Pro Tips

Organize with a sibling folder

Keep your worktrees tidy by putting them all in a sibling directory to your main clone. This avoids polluting your project directory and keeps paths predictable.

~/dev/
my-app/ ← main worktree
my-app-worktrees/
hotfix/ ← linked worktree
review-pr-99/ ← linked worktree

Add a shell alias

# Quick worktree creation: `gwt payments origin/main`
gwt() {
git worktree add ../"$(basename $(git rev-parse --show-toplevel))-$1" ${2:-HEAD}
}

Use with your editor

VS Code, Neovim, and most editors treat each worktree directory as a completely independent project. Open them in separate windows — you get full editor isolation, separate terminal sessions, separate extension states, and no interference.

Lock a worktree on a remote machine

If you’re using worktrees over a network mount or on a remote that might prune stale refs, lock the worktree to protect it:

git worktree lock ../app-hotfix --reason "active on CI server"

# Unlock when done
git worktree unlock ../app-hotfix

Summary

Git worktree is one of those features that, once you start using it, you’ll wonder how you ever lived without it. It’s particularly powerful for:

  • Hotfix isolation — fix in a separate tree, merge, delete
  • PR code reviews — check out any branch without abandoning yours
  • Parallel development — multiple branches, multiple terminals
  • Side-by-side benchmarking — run both versions simultaneously
  • Long-running git bisect — never abandon your WIP

It’s not a replacement for good branching strategy, and it doesn’t eliminate merge conflicts — but it radically reduces the cognitive overhead of context switching. The next time a bug erupts mid-feature, don’t stash. Spin up a worktree.

--

--