| name | git-worktrees |
| description | This skill should be used when the user asks about "git worktree", "parallel checkout", "worktree cleanup", "create worktree", "remove worktree", "worktree path", or when a workflow involves git worktrees, parallel development, multiple checkouts, or edits that must happen in the intended worktree path. Reusable workflow for safely creating, entering, and working within git worktrees (plus clean removal).
|
For humans: Every workflow isolates work in git worktrees — separate checkout directories sharing the same repo history. This is the mechanical reference your agent follows. Set $WORKTREES_ROOT to your preferred location. See the glossary or Git docs.
Git Worktrees Workflow (Safe Ops)
This skill is the reusable, canonical workflow for git worktree operations in multi-worktree development.
Agent Identifier (Required)
Every worktree MUST include an agent identifier prefix. This is mandatory for all worktree operations.
Input: <agent-id> — a short identifier for the agent (e.g., A, B, C, agent1, alice)
Purpose:
- Makes it immediately clear which agent created which worktree
- Prevents naming collisions when multiple agents work in parallel
- Enables easy cleanup of a specific agent's worktrees
Worktree Naming Convention
All worktree names follow this format:
agent-<agent-id>-<rest-of-name>
Where <rest-of-name> follows existing conventions:
| Context | Format | Example |
|---|
| With milestone + issue | agent-<id>-<M#>-<issue-id>-<title-slug> | agent-A-M8-PROJ-42-fix-settings-bug |
| With issue only | agent-<id>-<issue-id>-<title-slug> | agent-B-PROJ-42-story-pipeline |
| Review branch | agent-<id>-<issue-id>-review-<title-slug> | agent-A-PROJ-42-review-pipeline |
| Fix branch | agent-<id>-<issue-id>-fix-<title-slug> | agent-B-PROJ-42-fix-pipeline |
| No milestone/issue | agent-<id>-<purpose>-<title-slug> | agent-C-fix-login-timeout |
Worktrees Root (Required)
All worktrees live under a single flat directory:
WORKTREES_ROOT="$WORKTREES_ROOT"
Worktree directory: Always $WORKTREES_ROOT/wt-agent-<agent-id>-... (mirrors the branch name).
Prompt components (copy/paste blocks)
For command authorship, use the reusable worktree lifecycle blocks:
references/worktree-lifecycle-blocks.md
- Disposable: pick up / put down (recommended default)
- Persistent: keep alive until explicit end
Graphite-first note (when applicable)
- If the repo/workflow uses Graphite stacks, prefer
gt for sync/restack and branch/stack operations.
- Use
git freely for inspection/non-mutating commands (e.g. git status, git diff, git log, git show, git grep, git rev-parse, git branch --show-current).
- Use mutating
git primarily for worktree mechanics (add/remove) or explicit admin needs.
Core invariants
- A git branch is not owned by a worktree. A worktree is just another checkout directory of the same repo.
- A branch can be checked out in only one worktree at a time. If you need the same code in two places, create a second branch.
- Removing a worktree removes the directory, not the branch. Branches (and any Graphite metadata) remain.
- Agent prefix is required: Every worktree name MUST start with
agent-<agent-id>-.
Default conventions
- Prefer creating worktrees under
$WORKTREES_ROOT (flat; no extra nesting): $WORKTREES_ROOT/wt-agent-<agent-id>-<rest>.
- Prefer one worktree per agent/task/issue to avoid branch checkout collisions.
- The same agent should use the same
<agent-id> throughout a session.
When to create new branch vs. checkout existing
| Scenario | Action | Why |
|---|
| Starting new work that builds on another branch | Create new branch (-b) | Don't lock the parent; others may still need it. |
| Fix-review / addressing review feedback | Create new fix branch (-b) | Keep original implementation atomic; fix becomes separate changeset. |
| Someone else might be working on the branch | Create new branch | Avoid contention; let them keep the original. |
| Need changes from a branch but don't want to block it | Create new branch on top | Build on its changes without locking. |
Worktree patch-path guard (must do before any edits/patches)
<worktree_patch_path_guard>
Use absolute paths with all Write/Edit/Patch tools. This is the only way to guarantee consistent writes to the correct worktree.
-
Get the worktree root and use it for all file operations:
WORKTREE_ROOT="$(pwd -P)"
git rev-parse --show-toplevel
git branch --show-current
-
For every Write/Edit/Patch tool call, use absolute paths:
- Construct paths from
$WORKTREE_ROOT (e.g., $WORKTREE_ROOT/src/foo.ts)
- Never use relative paths that could resolve to a different checkout
- Never write to a different checkout path "because it exists"
</worktree_patch_path_guard>
- List worktrees:
git worktree list
- If the intended worktree already exists, switch by
cd into it; do not create a second one.
Use this when starting NEW work that builds on another branch. Creates a new branch and checks it out in a new worktree.
Context required:
<agent-id>: REQUIRED — agent identifier (e.g., A, B, C)
<branch-name>: your new branch name following the naming convention: agent-<agent-id>-<M#>-<issue-id>-<title-slug> (or without milestone: agent-<agent-id>-<issue-id>-<title-slug>)
<parent-branch>: the branch you're branching from
Inference for <parent-branch> (if not explicitly known):
- Run
gt ls to see current stack.
- Default to the stack tip when work is related to the current stack.
- Default to
main when work is independent or starting fresh.
Convention: <worktree-dir> defaults to $WORKTREES_ROOT/wt-<branch-name> (includes agent prefix).
Branch name construction:
- With milestone:
agent-<agent-id>-<M#>-<issue-id>-<title-slug> (e.g., agent-A-M8-PROJ-42-story-pipeline)
- Without milestone:
agent-<agent-id>-<issue-id>-<title-slug> (e.g., agent-B-PROJ-42-story-pipeline)
- Create and enter:
WORKTREES_ROOT="$WORKTREES_ROOT"
git fetch --all --prune
git worktree add -b <branch-name> "$WORKTREES_ROOT/wt-<branch-name>" <parent-branch>
cd "$WORKTREES_ROOT/wt-<branch-name>"
- Sanity-check:
git branch --show-current
git status
- Install dependencies (skip only for truly read-only workflows):
- Use the repo's package manager (check
package.json, lockfiles, or repo docs):
pnpm install
- If install unexpectedly changes lockfiles and the workflow didn't call for it, stop and ask before committing those changes.
Use this for fix-review workflows. Creates a new fix branch inserted into the stack (not as a sibling) and checks it out in a new worktree. This keeps the original implementation atomic while ensuring correct stack ordering.
Context required:
<agent-id>: REQUIRED — agent identifier (e.g., A, B, C)
<work-branch>: the original implementation branch you're fixing
<fix-branch>: your new fix branch name: agent-<agent-id>-<issue-id>-fix-<title-slug>
Inference for <work-branch> (if not explicitly known):
- Run
gt ls and identify the branch matching the issue being fixed.
- If multiple candidates exist, ask the user to confirm.
Convention: <worktree-dir> defaults to $WORKTREES_ROOT/wt-<fix-branch> (includes agent prefix).
Fix branch naming: agent-<agent-id>-<issue-id>-fix-<title-slug> (e.g., agent-A-PROJ-42-fix-pipeline)
Key insight: Avoid touching the primary worktree when possible. Check where <work-branch> is checked out, then pick the appropriate path.
Step 0: Check where work-branch is checked out
git worktree list
- Case A: work-branch is FREE (not checked out anywhere) → Use Path A below.
- Case B: work-branch is checked out in primary → Use Path B below.
- Case C: work-branch is checked out in another worktree → Ask user; that worktree should have been cleaned up.
Path A: Insert from a new worktree (preferred — never touches primary)
-
Create worktree checking out work-branch directly (worktree named after fix-branch for clarity):
WORKTREES_ROOT="$WORKTREES_ROOT"
git worktree add "$WORKTREES_ROOT/wt-<fix-branch>" <work-branch>
cd "$WORKTREES_ROOT/wt-<fix-branch>"
-
Now on work-branch in the worktree — create + insert fix branch:
echo "# Fix branch for <work-branch>" > .fix-init && git add .fix-init
gt create --insert -am "fix(<scope>): initialize fix branch" <fix-branch>
git rm .fix-init
gt modify --commit -am "fix(<scope>): remove placeholder"
-
Worktree is now on <fix-branch> (e.g., agent-A-PROJ-42-fix-pipeline), properly inserted. Skip to verification below.
Path B: Insert from primary (already on work-branch), then create worktree
Primary is already on work-branch. Do the insertion there, restore primary to its original state, then create the worktree.
-
Record original branch and do insertion:
ORIGINAL_BRANCH=$(git branch --show-current)
echo "# Fix branch for <work-branch>" > .fix-init && git add .fix-init
gt create --insert -am "fix(<scope>): initialize fix branch" <fix-branch>
git rm .fix-init
gt modify --commit -am "fix(<scope>): remove placeholder"
-
Restore primary to original branch (leave it as you found it):
git checkout "$ORIGINAL_BRANCH"
-
Create worktree for fix-branch (no -b flag, branch exists):
WORKTREES_ROOT="$WORKTREES_ROOT"
git worktree add "$WORKTREES_ROOT/wt-<fix-branch>" <fix-branch>
cd "$WORKTREES_ROOT/wt-<fix-branch>"
Verification (all paths)
-
Verify stack position:
gt ls
- Expected:
... → <work-branch> → <fix-branch> → ... (child, not sibling)
- If wrong:
gt move --onto <work-branch>
-
Sanity-check:
git branch --show-current
git status
Legacy approach (use create-fix-branch-in-worktree above instead). This older pattern creates the branch as a sibling rather than inserting it into the stack, which can cause ordering issues.
Context required:
<agent-id>: REQUIRED — agent identifier (e.g., A, B, C)
<work-branch>: the original implementation branch you're fixing
<fix-branch>: your new fix branch name: agent-<agent-id>-<issue-id>-fix-<title-slug>
Inference for <work-branch> (if not explicitly known):
- Run
gt ls and identify the branch matching the issue being fixed.
- If multiple candidates exist, ask the user to confirm.
Convention: <worktree-dir> defaults to $WORKTREES_ROOT/wt-<fix-branch> (includes agent prefix).
-
Fetch and create fix branch:
git fetch --all --prune
WORKTREES_ROOT="$WORKTREES_ROOT"
git worktree add -b <fix-branch> "$WORKTREES_ROOT/wt-<fix-branch>" <work-branch>
cd "$WORKTREES_ROOT/wt-<fix-branch>"
-
Register with Graphite (sets parent but does NOT insert if upstack branches exist):
gt track --parent <work-branch>
gt ls
-
Sanity-check:
git branch --show-current
git status
Use this when resuming work on a branch you created and own. Checks out an existing branch in a new worktree.
Context required:
<agent-id>: REQUIRED — agent identifier (should match the original agent who created the branch)
<existing-branch>: the branch you want to check out (should already include the agent prefix)
Inference for <existing-branch> (if not explicitly known):
- Derive from agent ID + issue ID using naming convention:
agent-<agent-id>-<issue-id>-<title-slug>.
- Run
gt ls to find branches matching the pattern.
- If multiple candidates exist, ask the user to confirm.
Convention: <worktree-dir> defaults to $WORKTREES_ROOT/wt-<existing-branch> (includes agent prefix).
-
Fetch and verify branch exists:
git fetch --all --prune
git show-ref --verify --quiet "refs/heads/<existing-branch>"
-
Check if already checked out somewhere:
git worktree list
- If checked out in the primary worktree, switch primary to a different branch first:
git switch main
- If checked out in another worktree, ask the user if it's safe to remove that worktree before proceeding.
-
Create worktree and enter (note: no -b flag — checking out existing branch):
WORKTREES_ROOT="$WORKTREES_ROOT"
git worktree add "$WORKTREES_ROOT/wt-<existing-branch>" <existing-branch>
cd "$WORKTREES_ROOT/wt-<existing-branch>"
-
Sanity-check:
git branch --show-current
git status
-
Install dependencies (skip only for truly read-only workflows):
pnpm install
- Apply the patch-path guard above before edits.
- Avoid checking out any branch that is already checked out in another worktree (Git will error; don’t try to “force it”).
- If you see unexpected working tree changes:
- First run
git branch --show-current and confirm whether you're even on the branch you intend to operate on.
- If you are on the intended branch: stop and tell the user that unexpected changes exist on your working checkout. Do not stash/restore/reset, and do not try to work around it.
- If you are not on the intended branch: leave this checkout alone and go to the intended branch/worktree before continuing (do not try to “carry” changes across branches).
- Avoid destructive cleanup of unrelated changes unless explicitly instructed.
- If using Graphite stacks, prefer the workflow’s safe sync/restack guidance rather than ad-hoc rebases:
gt sync --no-restack
gt restack --upstack
- If you are not using Graphite stacks, use a plain git update:
git fetch --all --prune
git rebase <parent-branch>
Only remove worktrees you created (or were explicitly told to remove).
- Detach and remove the worktree directory:
WORKTREE_DIR="$(pwd -P)"
git status
git switch --detach
cd <primary-worktree-path>
git worktree remove "$WORKTREE_DIR"
- Optional cleanup:
git worktree prune