Most people learn git worktree add and stop. That’s enough for one worktree. It isn’t enough when agents are creating and deleting them for you. This lesson is the reference shelf: the commands, the configuration that changes behavior across all of them, and the layouts worth choosing between. For the failure modes, see Worktrees in Practice.
Commands
The full git worktree command set is small:
add: Creates a worktree.list --porcelain -z: Lists worktrees in a stable, machine-readable format. Each field line, such asworktree,HEAD, orbranch, ends in a NUL byte. An empty field separates worktree records, producing a double NUL at each record boundary. Group fields until that empty field; a single NUL is not a complete-worktree delimiter. Use this framing in scripts instead of the human-readable output.lockandunlock: Protect a worktree from being pruned or removed.move: Relocates a worktree. Don’t move the folder yourself.remove: Deletes a worktree.prune: Cleans up records for worktrees whose folders no longer exist.repair: Fixes the links between a repository and its worktrees after something moved.
A few add flags earn their keep:
-bwith an explicit base: Creates a new branch from a starting point you name, instead of whateverHEADhappens to be.--detach: Checks out a commit without a branch.--no-checkout: Creates the worktree without populating files, so you can set up sparse checkout before anything lands.--orphan(Git 2.42+): Starts a branch with no history.--lock --reason: Locks the worktree at creation and records why.--no-track: Doesn’t set up upstream tracking for the new branch.
Configuration
- Shared configuration:
git config --localchanges every worktree, because the repository’s configuration file is shared. - Per-worktree configuration: First enable
extensions.worktreeConfigin the common configuration. Then move any existingcore.worktreeandcore.barevalues that belong to the main worktree into itsconfig.worktree, and remove them from the common file. Perform the move in the main worktree and verify both files before using linked worktrees. As the Git configuration reference explains,git config --worktreeacts like--localwhile the extension is disabled, so moving keys first just writes them back to the shared file. Older versions of Git refuse repositories that have this extension. - Relative paths (Git 2.48+): Let you move a repository and its worktrees together, and work inside containers. The cost is that older Git versions and some graphical clients can’t open the repository.
- Other keys worth knowing:
gc.worktreePruneExpire(how long Git waits before pruning stale worktree records; the default is three months),worktree.guessRemote(guess a matching remote branch when creating a worktree), andincludeIf "worktree:"(Git 2.56), which applies configuration only to worktrees whose path matches a pattern.
Layouts
- Siblings (
../app-feature): The simplest option. Each worktree is a folder next to the main checkout. - Nested and gitignored (
.worktrees/,.claude/worktrees/): Self-contained, but some IDEs and indexers trip over it. - A bare hub (
.bareplus one folder per branch): A bare repository holds the Git data, and every branch is a worktree. You have to fix the fetch refspec (the rule that says which remote branches to download), or you get noorigin/*branches. - Tool-managed: Let the tool clean them up, not
rm.
Advanced techniques
- Detached worktrees: For frozen reviews and side-by-side regression checks.
- Bisect in its own worktree: Bisect refs are private to each worktree, so the hunt doesn’t disturb your main checkout. In
bisect run, exit code127means “command not found,” but it counts as bad. Exit125tells bisect to skip. - Sparse worktrees: Use
--no-checkout, thensparse-checkout set, then an explicitcheckout HEAD. You get a worktree with only the folders you named. refs/worktree/*: For private checkpoints that don’t clutter the branch list.- A
post-checkouthook that bootstraps new worktrees: This is a Git hook, a script Git runs at set points, not a Claude Code hook. Whenworktree addcreates one, the hook’s old-HEADargument is all zeros, which is how you tell “new worktree” from “ordinary checkout.” - Conflict tooling:
git merge-tree --write-treepredicts conflicts before you merge.rererereuses conflict resolutions you’ve already made.range-diffshows what a rebase actually changed.
Pick a layout once, let the tool or one script create every worktree, and never move a folder by hand.