# 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 ```sh # 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 ```sh git worktree list ``` Example output: ``` /home/you/projects/myapp abc1234 [main] /home/you/projects/myapp-feature def5678 [feature/auth] ``` ### Remove a worktree ```sh # 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: ```sh git worktree prune ``` ### Move a worktree ```sh 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: ```sh 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 ```sh 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 ```sh 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//` 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//`. 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 | Task | Command | |---|---| | Add a worktree for an existing branch | `git worktree add ` | | Add a worktree and create a new branch | `git worktree add -b ` | | List all worktrees | `git worktree list` | | Remove a worktree | `git worktree remove ` | | Clean up stale worktree records | `git worktree prune` | | Move a worktree | `git worktree move ` |