--- name: git-worktrees description: > Use when working on several branches at once without stashing — manages the full lifecycle of a git worktree. Not ordinary branch switching or checkout -> `git-branches`. Not interactive multi-step git guidance -> `git-workflow`. metadata: category: git source_keys: - git-scm-worktree-docs --- ## Gotchas - **A branch can be checked out in only one worktree at a time.** `git worktree add` on an already-checked-out branch fails; `--force` is the only override, so use it only deliberately. - **Never `rm -rf` a worktree directory.** That strands metadata in `$GIT_DIR/worktrees/`. Use `git worktree remove`, or `git worktree prune` afterwards. - **Submodules break worktree support.** A worktree containing submodules cannot be moved at all, and needs `--force` to remove. - **`extensions.worktreeConfig = true` is a one-way door.** It costs compatibility with older Git and forces `core.bare`/`core.worktree` into `config.worktree`. Leave it off unless per-worktree config is needed. ## Step 1 — Dispatch | Operation | Run | |---|---| | Create on a branch that already exists locally | `git worktree add ` | | Create on a new branch | `git worktree add -b ` | | Create on the branch named after the path basename | `git worktree add ` — checks that branch out if it exists, else creates it from HEAD | | Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B ` | | Create a local branch tracking a remote one | `git worktree add --track -b /` — always correct. `git worktree add ` expands to exactly this, but **only** under the conditions in `references/worktrees.md` | | Throwaway experiment, no branch | `git worktree add -d ` — detached HEAD | | **Never** `git worktree add /` | That ref resolves, so the shortcut never fires and you get **a detached HEAD, no branch, no upstream**. Commits there go unreachable once HEAD moves, and `git push` needs an explicit refspec. Use the tracking row above | | List | `git worktree list -v`, or `--porcelain -z` to parse | | Lock or unlock | `git worktree lock [--reason ] ` / `git worktree unlock ` | | Move | `git worktree move ` | | Remove | `git worktree remove ` | | Prune stale metadata | `git worktree prune --dry-run`, then without the flag | | Repair after a manual move | `git worktree repair` — in the main worktree if *it* moved, or inside a linked worktree that moved. `git worktree repair ...` — from any worktree, naming each moved linked worktree's new path | If the operation needs anything the table does not carry — the full `add` flag table, orphan branches, sparse-checkout, locking for removable media, remote disambiguation across several remotes, how to name a worktree unambiguously, worktree config keys, or the worked emergency-fix and PR-review patterns — read `references/worktrees.md`. Gates: - **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates. - **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state. - **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected. ## Step 2 — Report ```yaml worktrees: - path: branch: commit: locked: lock_reason: ``` Derive those fields from `git worktree list --porcelain -z`. For a single operation, report its outcome instead — `created: true`, `moved: true`, `removed: true`.