Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Git Worktrees

What Are They?

A git worktree is a checked-out copy of a branch that lives in a separate directory on your filesystem, but shares the same underlying git repository (.git database) as your main clone.

Normally, a single git clone has one working directory — the files you see and edit. A worktree lets you have multiple working directories at once, each on a different branch, all tied to the same repository. You don’t clone the repo a second time; you project a second (or third, or fourth) working directory from the one clone.

~/.git/           ← shared: all objects, refs, config
~/projects/myapp/          ← main worktree (branch: main)
~/projects/myapp-feature/  ← linked worktree (branch: feature/auth)
~/projects/myapp-hotfix/   ← linked worktree (branch: hotfix/crash)

All three directories above read and write to the same .git object store. Commits made in any worktree are immediately visible to all others.


Core Commands

Add a worktree

# Check out an existing branch into a new directory
git worktree add ../myapp-feature feature/auth

# Create a new branch and check it out in one step
git worktree add -b feature/new-thing ../myapp-new-thing main

The first argument is the path for the new directory. The second is the branch name (or starting commit).

List worktrees

git worktree list

Example output:

/home/you/projects/myapp          abc1234 [main]
/home/you/projects/myapp-feature  def5678 [feature/auth]

Remove a worktree

# Remove the directory and deregister the worktree
git worktree remove ../myapp-feature

# Force-remove even if there are untracked or modified files
git worktree remove --force ../myapp-feature

After deleting a linked worktree directory manually (e.g. with rm -rf), git still knows about it. Clean up the stale reference with:

git worktree prune

Move a worktree

git worktree move ../myapp-feature ../myapp-auth-feature

Typical Workflows

Work on two branches simultaneously

You’re deep in a feature branch when a urgent bug report comes in. Instead of stashing your work or committing a WIP, you add a worktree:

git worktree add ../myapp-hotfix main
cd ../myapp-hotfix
# fix the bug, commit, push — then come back to your feature

Your feature working directory is untouched.

Run tests against a different branch without switching

git worktree add /tmp/myapp-test origin/release/2.0
cd /tmp/myapp-test
cargo test

You keep your editor open on main while tests run elsewhere.

Review a colleague’s PR locally

git fetch origin
git worktree add ../review-pr-123 origin/pr/123
cd ../review-pr-123
# read, run, evaluate — then remove when done
git worktree remove ../review-pr-123

How It Works Internally

When you run git worktree add, git:

  1. Creates a subdirectory inside .git/worktrees/<name>/ to store the worktree’s private state (its HEAD, index, and a back-reference to the working directory path).
  2. Writes a .git file (not a directory) into the new working directory that points back to .git/worktrees/<name>/.
  3. Checks out the requested branch into the new directory.

The object database (all commits, trees, blobs) is shared. Only the index and HEAD are per-worktree.


Limitations and When to Avoid Them

Each branch can only be checked out once

The most important constraint: a single branch cannot be checked out in two worktrees at the same time. Git enforces this to prevent the two trees from diverging their indexes silently. If you try, you’ll get an error:

fatal: 'feature/auth' is already checked out at '/home/you/projects/myapp'

Workaround: check out the second worktree at a specific commit (detached HEAD), or create a local tracking branch.

Tools that look for .git as a directory can break

Some tools assume .git is a directory, not a file. A linked worktree has a .git file instead, which confuses:

  • Older git GUIs that scan for .git/ directories
  • Some shell prompts and plugins that detect git repos naively
  • Scripts that do test -d .git

Build systems that use the working directory path

If your build system or language tooling caches absolute paths (e.g. Cargo’s target/ directory is placed relative to the workspace root), separate worktrees work fine — each has its own target/ directory. But if a tool bakes the source path into cached artifacts, switching between worktrees may cause spurious rebuilds or cache invalidation.

Hooks run in the worktree context, not the main repo

Git hooks in .git/hooks/ apply to all worktrees. But the working directory ($GIT_WORK_TREE) will be the linked worktree path, not the main repo path. Hook scripts that assume a fixed working directory can behave unexpectedly.

Not a substitute for branches in CI

Worktrees are a local developer convenience. Don’t model CI pipelines around them — use proper branch checkouts in ephemeral CI environments instead.

Submodules require extra care

Submodules are not automatically initialized in a new worktree. You need to run git submodule update --init inside each linked worktree where you need them.

Avoid for long-lived parallel development

If you find yourself maintaining two worktrees of the same repo for weeks at a time, that’s a signal you might want two separate clones or a proper branch strategy — not worktrees. Worktrees shine for short-lived parallel work (hotfixes, reviews, quick tests), not as a permanent parallel development setup.


Quick Reference

TaskCommand
Add a worktree for an existing branchgit worktree add <path> <branch>
Add a worktree and create a new branchgit worktree add -b <branch> <path> <start-point>
List all worktreesgit worktree list
Remove a worktreegit worktree remove <path>
Clean up stale worktree recordsgit worktree prune
Move a worktreegit worktree move <old-path> <new-path>