You're deep in a feature branch. A bug report comes in. You need to check main, reproduce the bug, fix it, push — then get back to your feature.
Most developers do one of these:
-
git stash→ switch branch → work → switch back →git stash pop→ hope nothing broke - Clone the repo again into a second directory
- Commit half-finished work with a "WIP" message
All three are bad. There's a better way, and it's been in git since 2015.
What Are Git Worktrees?
A git worktree is a linked working directory that shares the same .git repository. Each worktree checks out a different branch, and they coexist on disk simultaneously.
my-project/ ← main branch (your primary worktree)
my-project-hotfix/ ← hotfix branch (linked worktree)
my-project-experiment/ ← experiment branch (linked worktree)
Three directories. Three branches. One repository. One .git history.
You can edit files in each directory independently, run tests in each, even have different editors open. No stashing. No switching. No WIP commits.
Getting Started
Create a worktree
# From your main checkout
cd my-project
# Create a worktree for an existing branch
git worktree add ../my-project-hotfix hotfix/login-bug
# Create a worktree with a new branch
git worktree add -b feature/new-api ../my-project-api
That's it. ../my-project-hotfix is now a fully functional checkout of hotfix/login-bug.
List worktrees
git worktree list
Output:
/home/dev/my-project abc1234 [main]
/home/dev/my-project-hotfix def5678 [hotfix/login-bug]
/home/dev/my-project-api 789abcd [feature/new-api]
Remove a worktree
When you're done with the branch:
# Delete the directory
rm -rf ../my-project-hotfix
# Clean up the worktree reference
git worktree prune
Or in one step (git 2.17+):
git worktree remove ../my-project-hotfix
Real-World Use Cases
1. Bug fixes without context switching
You're mid-feature. A P0 bug comes in.
# Create a worktree for the fix (30 seconds)
git worktree add -b hotfix/p0-crash ../hotfix main
# Fix the bug in the other directory
cd ../hotfix
# edit, test, commit, push
# Switch back — your feature branch is untouched
cd ../my-project
Your feature branch never moved. No stash. No WIP commit. No mental overhead of remembering where you were.
2. Running tests on one branch while working on another
Long test suite? Run it in the background on the worktree while you keep coding in the primary.
# In terminal 1 (worktree)
cd ../my-project-hotfix
cargo test
# In terminal 2 (primary)
cd ../my-project
# keep working on your feature
3. Comparing behavior across branches
Need to check how the app behaves on main vs. your branch?
git worktree add ../my-project-main main
# Terminal 1: run the app on main
cd ../my-project-main && cargo run
# Terminal 2: run your branch
cd ../my-project && cargo run
# Compare side by side
4. Code review with full context
Reviewing a PR? Check it out in a worktree instead of switching your primary branch:
git worktree add ../review-pr-42 origin/feature/pr-42
cd ../review-pr-42
# run tests, explore code, check behavior
# when done:
git worktree remove ../review-pr-42
5. Parallel CI-like workflows
Running linters, type checkers, and tests simultaneously across branches:
git worktree add ../wt-lint main
git worktree add ../wt-test feature/new-api
# Parallel execution
(cd ../wt-lint && npm run lint) &
(cd ../wt-test && npm test) &
wait
How It Works Under the Hood
When you clone a repo, git creates a .git directory that stores all objects, refs, and history. Your working directory is just one view into that data.
git worktree add creates another view — a new directory with its own HEAD, index, and working tree, but sharing the same .git/objects store.
.git/ ← shared object store
objects/ ← all commits, blobs, trees (shared)
refs/ ← all branches and tags (shared)
worktrees/
my-project-hotfix/ ← per-worktree HEAD and index
my-project-api/ ← per-worktree HEAD and index
This means:
- Disk usage is minimal. Worktrees share all git objects. Only the checked-out files are duplicated.
- Commits are immediately visible across worktrees. Push from one, pull from another.
- Branches are locked. You can't check out the same branch in two worktrees simultaneously. Git prevents this to avoid conflicting edits.
Common Pitfalls
Branch locking
git worktree add ../wt-main main
# Later, in primary:
git checkout main
# fatal: 'main' is already checked out at '../wt-main'
This is by design. Remove the worktree first, or work on a different branch.
Forgetting to prune
Deleted a worktree directory manually? Run git worktree prune to clean up stale references. Otherwise git still thinks the worktree exists and won't let you check out that branch elsewhere.
Submodules
Worktrees and submodules interact poorly in older git versions. If you use submodules, test with your git version first. Git 2.36+ handles this better.
Worktrees vs. Alternatives
| Approach | Disk cost | Speed | Risk |
|---|---|---|---|
git stash |
None | Fast | Stash conflicts, forgotten stashes |
| Second clone | Full repo | Slow | Divergent histories, double fetch |
| WIP commits | None | Fast | Polluted history, rebase headaches |
| Worktrees | Minimal | Fast | Branch lock (by design) |
Worktrees win on every dimension except one: they require you to know they exist.
Quick Reference
# Create worktree (existing branch)
git worktree add <path> <branch>
# Create worktree (new branch from current HEAD)
git worktree add -b <new-branch> <path>
# Create worktree (new branch from specific base)
git worktree add -b <new-branch> <path> <base>
# List all worktrees
git worktree list
# Remove a worktree
git worktree remove <path>
# Clean up stale worktree references
git worktree prune
Beyond Manual Use: Worktrees for Automation
Worktrees aren't just for humans. Any workflow that needs parallel access to multiple branches benefits: CI scripts, deployment pipelines, automated testing — or AI coding agents that need isolated working directories.
If you're running multiple AI agents on the same repo, worktrees give each agent its own checkout without the overhead of full clones. Each agent edits files independently, and conflicts only surface at merge time — which is when you want them.
Try it: cargo install batty-cli — GitHub | Demo
Git worktrees have been stable since git 2.5 (2015). If you're using any modern git version, they just work.
Top comments (0)