--- topic: worktrees source_keys: - git-scm-worktree-docs --- ## Shared vs. per-worktree state All worktrees share one object store, one config, and most refs under `refs/`. Each worktree keeps its own `HEAD`, index, and per-worktree metadata (`ORIG_HEAD`, `MERGE_HEAD`, `refs/bisect/`, `refs/worktree/`, `refs/rewritten/`) under `$GIT_DIR/worktrees//`. Exactly one **main worktree** exists per repo — the one `git init` or `git clone` produced — and it cannot be removed or moved. Every other worktree is a **linked worktree** created by `git worktree add`. ## `add` forms ```bash git worktree add # exists locally: check it out — non-destructive git worktree add -b # create a new branch; fails if it exists git worktree add # branch named after $(basename ): checked out # if it exists, else created from HEAD git worktree add -B # create the branch, or reset an existing one to HEAD, # discarding the commits it carried git worktree add --track -b / # new local branch tracking the remote — always works git worktree add # absent locally and in exactly one remote: # Git expands this to the --track -b form above git worktree add -d # detached HEAD, no branch ``` The same `git worktree add ` spelling appears twice above and does two different things: it checks out a local branch when one exists, and only otherwise falls through to the remote-tracking shortcut. Read the local branch list before relying on either. **Do not write `git worktree add /`.** A remote-tracking ref resolves as a commit-ish, so the tracking shortcut never fires and the worktree lands on a **detached HEAD with no local branch and no upstream** — commits there go unreachable once HEAD moves or the worktree is removed, and `git push` fails without an explicit refspec. That spelling is correct only as the final argument of the `--track -b` form. ## Full `add` flag table | Flag | Meaning | |---|---| | `-b ` | Create and check out a new branch; fails if it exists | | `-B ` | Like `-b` but resets the branch if it already exists | | `-d` / `--detach` | Detach HEAD; useful for throwaway experiments | | `--orphan` | Create empty unborn branch | | `--no-checkout` | Suppress initial checkout (for sparse-checkout setup) | | `--guess-remote` | Look for a matching remote-tracking branch by path basename | | `--lock [--reason ]` | Lock immediately on creation (atomic; avoids race vs. add-then-lock) | | `-f` / `--force` | Allow when branch is already checked out elsewhere | | `--relative-paths` | Link via relative paths (portable across moves) | Using `-` as `` is shorthand for `@{-1}` (the branch checked out before the current one), e.g. `git worktree add -`. ## New unborn branch ```bash git worktree add --orphan -b ``` Creates an empty branch with no commits. ## Sparse-checkout worktree Suppress the initial checkout to configure sparse-checkout first: ```bash git worktree add --no-checkout ../sparse main cd ../sparse git sparse-checkout init --cone git sparse-checkout set src/ git checkout main ``` ## Worktree on removable media ```bash git worktree add --lock --reason "external SSD" git worktree unlock # when reconnected ``` ## Remote-branch disambiguation ```bash git worktree add --track -b / # explicit: no guessing at all git worktree add # shortcut: needs one clear remote ``` The shortcut fires only when `` is not found locally, none of `-b`/`-B`/`--detach` were given, and a tracking branch of that name exists in exactly one remote. When several remotes carry the name, `checkout.defaultRemote` picks one for disambiguation purposes; with no such setting the shortcut has no single remote to resolve against and does not apply. `--guess-remote` covers the *other* spelling — `git worktree add ` with no `` at all. It bases the new branch on the remote-tracking branch matching `$(basename )` when exactly one remote has it, and marks that branch as upstream. Its default comes from the `worktree.guessRemote` config. ## Repair after a manual move ```bash git worktree repair # the MAIN worktree moved: run it there to reconnect every linked # worktree back to the main worktree git worktree repair # a LINKED worktree moved: run it inside that recently-moved worktree git worktree repair ... # reconnect a specific linked worktree — runnable from any worktree, # naming each moved tree's new path ``` Which form applies depends on what moved: | What moved | Remedy | |---|---| | The main worktree (or bare repo) | `git worktree repair` in the main worktree | | One linked worktree | `git worktree repair` inside that worktree | | Several linked worktrees | `git worktree repair ...` from any worktree, listing each new path | | Both main and linked worktrees | `git worktree repair ...` in the main worktree, naming each linked worktree's new path — this restores the connections in both directions | Only the no-argument form is tied to the current directory. The `...` form is not — it reestablishes the connection to every path you name, run from any worktree. ## Configuration | Key | Effect | |---|---| | `worktree.guessRemote` | Default for `--guess-remote` on `git worktree add` | | `worktree.useRelativePaths` | Default for `--relative-paths` on `git worktree add` (link via relative paths — portable across moves) | | `gc.worktreePruneExpire` | How long before stale worktree metadata is pruned by `git gc` | | `extensions.worktreeConfig` | Enable per-worktree config scope (`config.worktree` file) — see Gotchas in SKILL.md | | `checkout.defaultRemote` | Disambiguates which remote to use when a branch name matches multiple remotes during `worktree add` | ## Workflow patterns **Emergency fix without disrupting current work** — nothing is stashed, and the main worktree is untouched throughout: ```bash git worktree add -b emergency-fix ../temp main cd ../temp # fix, then commit git commit -a -m "fix: critical production bug" cd - git worktree remove ../temp ``` **Review a PR branch alongside your own work** — both branches stay checked out, so there is no context switch: ```bash git worktree add ../review-pr-123 origin/feature-xyz # detached HEAD — read-only review git worktree add --track -b feature-xyz ../review-pr-123 origin/feature-xyz # if you will commit # open ../review-pr-123 in a second editor window or terminal ``` Pick the second form the moment you intend to push anything back: the first leaves no branch to push and no upstream to push to.