Git Worktrees Intro
Worktrees let you check out multiple branches at the same time, each in its own directory, all sharing one underlying repository. No more git stash dances when you need to jump between contexts.
Recipe
Quick-reference recipe card -- copy-paste ready.
# Add a worktree on an existing branch
git worktree add ../feature-branch feature-branch
# Add a worktree and create a new branch in one step
git worktree add ../new-feature -b new-feature
# Add a worktree at a specific commit or tag (detached HEAD)
git worktree add ../hotfix abc1234
# List all worktrees attached to this repo
git worktree list
# Remove a worktree (after committing or stashing changes)
git worktree remove ../feature-branch
# Clean up stale entries after a folder was deleted manually
git worktree pruneWhen to reach for this: Any time you would otherwise stash work, clone the repo a second time, or context-switch between branches multiple times an hour.
Working Example
# 1. Start a feature in its own directory
git worktree add ../my-feature -b my-feature
# 2. Work and commit inside that worktree
cd ../my-feature
# ...edit files, run tests...
git commit -am "feat: scaffold new feature"
# 3. Walk back to the main worktree to merge
cd ../main-repo
git switch main
git merge my-feature
# 4. Clean up
git worktree remove ../my-feature
git branch -d my-featureWhat this demonstrates:
- One repo, two simultaneous working directories with independent files.
- The new feature commit is immediately visible from the main worktree -- they share history.
- The main worktree is where the merge happens; the feature worktree is just a place to write code.
- Worktrees are temporary by design: create, work, merge, remove.
Deep Dive
The mental model: one cabinet, many desks
Think of a Git repository as a writer's house. In the back room sits a steel filing cabinet -- this is the .git directory, holding every commit, every branch, every fragment of history. Out in the study is your writing desk, where one version of the manuscript is laid out so you can read and edit it.
For most of Git's history, you only had one desk. Switching branches meant gathering up the pages on the desk, filing them back, and laying out a different version. If you were halfway through a feature and needed to fix a production bug, you had to stash your half-finished work, clear the desk, fix the bug, then reverse the whole process.
Worktrees give you a second desk. And a third. And a fourth. Each desk holds a different branch, with its own files visible and editable, while the others continue holding whatever you had laid out before. All the desks share the same cabinet -- the same history, the same commits, the same remote configuration. But the files on top, the working trees, are independent.
That's what a worktree is: a second view onto the same repository.
What gets shared, what gets separated
When you add a worktree, Git does something elegant. In the new folder, it creates the working tree files for the branch you asked for, exactly as if you had cloned the project fresh. But it does not clone anything. The new folder contains a tiny .git file (not a directory) that points back to the original repository's .git folder. Every operation in the new worktree -- commit, push, pull, log -- reads from and writes to that single shared cabinet.
| Shared across all worktrees | Separate per worktree |
|---|---|
| Object database (commits, blobs, trees) | Working directory files |
| Branches and tags | Index (staging area) |
| Remote configuration | HEAD reference |
| Stashes | Uncommitted changes |
| Most config | Submodule checkouts (init per worktree) |
| Hooks | Build artifacts (node_modules, etc.) |
The wonderful consequence: there's no duplication of history. If your repo is gigabytes of objects, adding a worktree barely adds anything to disk -- you only pay for the checked-out files, not the history behind them.
The one-branch-per-worktree rule
Git enforces a single rule that catches everyone once: a given branch can only be checked out in one worktree at a time. Try to check out main in two worktrees, and Git refuses. The reason is simple -- if both desks held the same draft and you wrote different changes on each, which set of changes would the cabinet eventually accept? The constraint protects you from a question that has no good answer.
The workaround is what you'd expect: branch off. If you want a second worktree based on main, create a new branch from main (git worktree add ../scratch -b scratch main) and use that.
The administrative metadata
Inside your original .git folder, a worktrees/ subdirectory holds a small folder for every linked worktree. Each contains that worktree's own HEAD, index, logs, and a few other files. The original repo always knows where every worktree lives, what branch it has checked out, and whether the folder still exists on disk.
git worktree list prints all of them, including the main worktree -- which is just the first desk among equals.
The main worktree is structurally privileged
Linked worktrees feel like equals to the main one in day-to-day use, but the main worktree is where the actual .git directory lives. If you delete the main worktree's folder while linked worktrees still exist, all of them break -- the cabinet they depend on has vanished. Treat the main worktree as the foundation. Move it carefully (use git worktree repair after if needed).
When to reach for worktrees
The mental shift is from "branches are places I visit, one at a time" to "branches are places I can occupy simultaneously, each in its own room." Worktrees shine when:
- You are interrupted by a hotfix and don't want to disturb your in-progress feature.
- You want to review a teammate's PR by running their branch in a separate folder.
- You need to run a long test suite on one branch while continuing development on another.
- You are comparing two implementations side-by-side, both running, both editable.
- You maintain a "main" worktree as a clean reference and do all work in feature worktrees.
Worktrees are not a substitute for branches. They are not always a substitute for stashing -- a quick 30-second context switch is still faster with stash. They are almost always a substitute for cloning the repo twice, since you avoid the storage cost and the headache of keeping two clones in sync via the remote.
Gotchas
Things that will bite you. Each gotcha includes what goes wrong, why it happens, and the fix.
-
Trying to check out a branch already in another worktree -- Git refuses with
fatal: '<branch>' is already checked out at .... Fix: Either work in the existing worktree, create a new branch off that one (git worktree add ../scratch -b scratch <branch>), or remove the other worktree first. -
Deleting a worktree folder manually with
rm -rf-- Git's metadata still points to the missing folder, andgit worktree listkeeps showing it. Fix: Rungit worktree pruneto clean up dangling references. -
Removing the main worktree while linked worktrees exist -- The shared
.gitdirectory disappears and every linked worktree is broken. Fix: Never delete the main worktree's folder. If you need to relocate the repo, move the main worktree first, then rungit worktree repairfrom inside it to update the links. -
Submodules don't auto-initialize in a new worktree -- The submodule directories appear empty. Fix: Run
git submodule update --init --recursiveinside each new worktree that needs submodules. -
node_modulesand build artifacts duplicated per worktree -- Each worktree has its own working tree, sonpm installin three worktrees means threenode_modulesdirectories. Fix: Use a shared package cache (pnpm's content-addressable store handles this naturally) or accept the disk cost as the price of parallelism. -
Hooks fire in every worktree -- Hooks live in the shared
.git/hooksdirectory, so a pre-commit hook runs no matter which worktree you commit from. Fix: Usually what you want, but if a hook needs different behavior per worktree, branch ongit rev-parse --git-common-dirvs--git-dirinside the hook. -
IDEs open the wrong folder after switching worktrees -- Editor windows tied to the old path keep showing stale files. Fix: Open each worktree as its own project/window in your editor; treat them as separate workspaces.
-
Forgetting to commit before
git worktree remove-- Git refuses to remove a worktree with uncommitted changes (good!), but you may get stuck if the folder has untracked files you forgot about. Fix: Either commit, stash, or usegit worktree remove --forceif you are certain the changes are disposable.
Alternatives
Other ways to solve the same problem -- and when each is the better choice.
| Alternative | Use When | Don't Use When |
|---|---|---|
git stash | A 30-second context switch -- fix one line on another branch and come back | The interruption is long, or you need both branches running side-by-side |
| Cloning the repo twice | You need fully isolated .git directories (e.g., experimenting with destructive git filter-repo) | You want shared history, branches, and remotes -- worktrees are strictly better here |
| Branch switching in place | Single-branch flow with no in-progress work to preserve | You have uncommitted changes, or want to keep two contexts open |
git worktree | Two or more branches need to coexist -- review + feature, hotfix + WIP, A/B comparison | A simple stash-and-switch would do the same job in less time |
FAQs
What is the difference between a worktree and a clone?
- A clone duplicates the entire
.gitdirectory, history and all -- two independent repos. - A worktree shares the original
.gitdirectory, so commits and fetches in one are immediately visible in others. - Worktrees are dramatically cheaper on disk and avoid the "keep two clones in sync via the remote" headache.
Can I have two worktrees on the same branch?
- No. Git enforces one-branch-per-worktree to prevent conflicting commits to the same branch ref.
- The workaround is to branch off:
git worktree add ../scratch -b scratch maincreates a new branch starting frommainand checks it out in the new worktree.
Where should I put my worktree directories?
- Outside your main repo folder. Common patterns: a sibling folder (
../my-feature) or a dedicated worktrees parent (~/projects/myrepo-worktrees/feature-x). - Avoid nesting a worktree inside the main worktree -- Git will treat the inner files as untracked and the experience gets confusing.
Do worktrees share my stashes?
- Yes. Stashes live in the shared
.gitdirectory, sogit stash listshows the same entries from any worktree. - This means you can stash in one worktree and pop in another -- occasionally useful, often surprising.
What happens to my worktrees when I push or pull?
- A
git fetchin any worktree updates the shared remote refs, so all worktrees see the new commits immediately. - A
git pullonly updates the branch checked out in the worktree where you ran it -- the other worktrees stay on whatever commit they had.
How do I move a worktree to a new location?
git worktree move ../old-path ../new-path- Git updates the metadata so the worktree keeps working from its new location.
- If you moved the folder manually with
mv, rungit worktree repair ../new-pathfrom inside the main worktree.
Do hooks run in every worktree?
- Yes. Hooks live in
.git/hooksand that directory is shared, so apre-commithook fires in any worktree where you commit. - This is usually what you want -- consistent enforcement -- but be aware if a hook depends on absolute paths.
Can I use worktrees with submodules?
- Yes, but submodules are not automatically initialized in a new worktree. Run
git submodule update --init --recursiveafter creating it. - Recent Git versions handle this more gracefully, but the manual init is the safe default.
How do I list every worktree and the branch each is on?
git worktree list- Output shows the path, the commit SHA, and the branch (or
(detached HEAD)). - Use
--porcelainfor a stable, machine-readable format.
Is there a performance cost to having many worktrees?
- Disk: each worktree has its own checked-out files, so disk usage scales with the size of the working tree (not history).
node_modulesand build artifacts duplicate. - CPU/memory: negligible. Operations like
git statusonly scan the current worktree. - A handful of worktrees is fine. Hundreds would be unusual but technically supported.
Related
- Worktree Examples -- Full lifecycle examples for checkout, merge, rebase, and cleanup
- Essential Git Commands -- The foundational commands every worktree workflow builds on
- Merging & Rebasing -- How to integrate work between branches (and between worktrees)
- Merge Conflict Resolution Checklist -- Step-by-step playbook when a worktree merge conflicts