Worktrees vs multiple clones Jump to heading
Both approaches end with two directories you can build in, which is why the choice is usually made by habit. They differ in exactly one structural way β worktrees share an object database and a set of refs, clones do not β and every practical difference follows from it. Sharing makes worktrees fast to create and immediately consistent; it also means an operation in one is visible in the other, which is occasionally the last thing you want. This page maps the trade honestly, within Git worktrees and parallel development.
When to use this approach Jump to heading
- You are deciding how to get a second working copy and want the trade-offs first.
- Someone has proposed standardising on one or the other across a team.
- A tool has misbehaved in a worktree and you are wondering whether to give up on them.
- You are about to rewrite history and need to know what a second copy would see.
- If you just need to look at another branch for thirty seconds, neither: use
git showorgit diff.
Step 1 β Compare what each one costs to create Jump to heading
# A worktree: refs and objects already present, files checked out
time git worktree add --detach ../app-wt HEAD
du -sh ../app-wt # A clone: objects transferred again, unless referenced locally
time git clone . ../app-clone
du -sh ../app-clone/.git ../app-clone # A local clone that borrows objects β the middle ground
time git clone --reference . --dissociate "$(git remote get-url origin)" ../app-ref Step 2 β Decide how much isolation the task needs Jump to heading
This is the real question, and it has a clear answer per task rather than in general.
# Shared refs: a commit in one worktree is instantly visible in the other
git -C ../app-wt commit --allow-empty -m "probe"
git log --oneline -1 "$(git -C ../app-wt rev-parse HEAD)" # visible here immediately
# Separate refs: a clone must fetch before it sees anything
git -C ../app-clone log --oneline -1 origin/main # Verification: which objects does each copy own?
git -C ../app-wt rev-parse --git-common-dir # points back at the original
git -C ../app-clone rev-parse --git-common-dir # its own Step 3 β Check your tooling before committing to worktrees Jump to heading
Most tools work correctly. The ones that do not fail in recognisable ways, and finding out early is cheap.
# Does the build write to a path derived from the directory, or a fixed one?
grep -rn 'cacheDir\|outDir\|target-dir' --include='*.json' --include='*.toml' . | head
# Does the editor or language server key state on the repository or the directory?
ls -d .vscode .idea 2>/dev/null # The decisive test: build in both, then rebuild in the first
(cd ../app-wt && npm run build >/dev/null) && (cd . && npm run build 2>&1 | grep -ci 'cache\|rebuild') If the second build rebuilds everything, the tool is sharing a cache keyed on something other than the path, and either configuration or a clone is the answer.
Step 4 β Know what a history rewrite does to each Jump to heading
This is the sharpest difference and the one that catches people out.
# In a worktree setup, a rewrite changes refs both copies read
git rebase -i HEAD~5 # in one worktree
git -C ../app-wt status # the other may now report a diverged branch # A clone is unaffected until it fetches, and can serve as a recovery source
git -C ../app-clone log --oneline -5 origin/main SAFETY WARNING β before rewriting history, check whether another worktree has the affected branch checked out. The rewrite updates the shared ref while the other worktreeβs index and working files still reflect the old commits, and continuing to work there can produce a commit that resurrects the history you just rewrote. Either remove the worktree first or move it to a detached HEAD. The wider risks are covered in safe git rebase -i for shared branches.
Step 5 β Pick per situation, using a short rule Jump to heading
# Worktree: parallel work on the same project, same tooling, no rewriting
git worktree add -b fix/urgent ../app-urgent origin/main
# Clone: risky experiments, a different tool version, or a recovery copy
git clone --reference . --dissociate "$(git remote get-url origin)" ../app-experiment Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Can I get the best of both with a referenced clone? Jump to heading
Largely, yes: --reference plus --dissociate gives independent refs with a fast creation path, so it is the right choice when you want isolation without the transfer. Without --dissociate it is faster still but fragile, because the clone depends on the original repositoryβs objects continuing to exist.
Do worktrees work with submodules? Jump to heading
They do, with the caveat that submodule working directories are per worktree and need initialising in each one. For repositories that use submodules heavily, the setup cost of a worktree rises enough that a clone becomes competitive again β see pinning and updating Git submodules safely.
Is one of them better for very large repositories? Jump to heading
Worktrees, clearly, because the object transfer is the dominant cost and they avoid it entirely. Combined with sparse checkout, a worktree over a very large repository can be created in seconds and hold only the directories you need.
Related Jump to heading
- Git Worktrees & Parallel Development β the parent topic and the sharing model.
- Cleaning Up Stale Worktrees Safely β the maintenance cost of choosing worktrees.
- Sparse-Checkout for Large Monorepos β making each working copy smaller as well as cheaper.