git:20260602.bfcd1a9 to git:20260602.01d2ec8

49 added, 68 removed. Audit B to A.

---
- description:
+ description: >-
Creates isolated git worktrees for parallel development. Use when starting
- feature work needing isolation or working on multiple branches simultaneously. Not
- for simple branch switching or basic git operations.
+ feature work needing isolation or working on multiple branches simultaneously.
+ NOT for simple branch switching, bulk branch cleanup (use cleanup-git), or git
+ hook/config setup (use configuring-git-hygiene).
name: using-git-worktrees
---
# Git Worktrees
- ## Core Principle
+ Use one sibling worktree root per project: `<project>.worktrees/<branch-slug>`. Keep the main worktree clean on the integration branch by default. Trivial solo one-liners may stay in the main worktree when a worktree would add pointless ceremony.
- Main repo stays on main/master — never edit directly. Every branch gets its own worktree. All worktrees for a project live under one per-project root directory, `<project>.worktrees/`, a sibling of the main repo. Delete the worktree and its branch after the PR merges.
+ Treat a worktree as a disposable branch folder. Remove it and its branch after the PR merges.
- Think of a worktree as a **disposable branch folder**, not a long-lived parallel environment.
+ ## Scope
- **Exception:** Trivial one-liner commits on a solo project can go directly on main to avoid ceremony overhead.
+ Use this skill when:
- ## Workflow
+ - starting a feature, fix, or experiment that should not disturb current work
+ - working on multiple branches at once
+ - trying competing approaches
+ - the current worktree has uncommitted changes and the user wants to start something else
- Check repo state before creating a worktree. Any worktree workflow description must name this dirty-state check before `git worktree add`:
+ Do not use this skill for:
+ - simple branch switching with no parallel work
+ - bulk branch or stale worktree cleanup — use `cleanup-git`
+ - git hook, Gitleaks, `.gitignore`, or config setup — use `configuring-git-hygiene`
+
+ ## Create Workflow
+
+ Check state before any `git worktree add`:
+
```bash
git status --short
git branch --show-current
git worktree list
```
- If the current worktree is dirty, ask whether to commit, stash, or create the new worktree anyway before proceeding. Confirm before running cleanup commands that remove worktrees or delete branches.
+ If the current worktree is dirty, ask whether to commit, stash, or proceed anyway. Do not stash silently.
- The per-project root is derived from the main worktree, so create and clean up correctly even when invoked from inside another worktree:
+ Use the helper when available:
```bash
- # main worktree is always the first entry of `git worktree list --porcelain`
- main_wt=$(git worktree list --porcelain | awk '/^worktree /{print $2; exit}')
- project=$(basename "$main_wt")
- root="$(dirname "$main_wt")/$project.worktrees"
+ scripts/setup-worktree.sh <branch> [--base <ref>]
```
- ```bash
- # 1. Create worktree for new work (slug = branch with / → -)
- mkdir -p "$root"
- git worktree add "$root/fix-cron" -b fix-cron
+ The helper creates `<project>.worktrees/<branch-slug>` from the main worktree root, handles existing local/remote branches, refuses path conflicts, and refuses dirty state unless `--allow-dirty` is passed after user approval.
- # 2. Work there (open your editor or coding agent in that folder)
- cd "$root/fix-cron"
+ Manual fallback lives in [workflow.md](references/workflow.md).
- # 3. After PR merges — confirm, then clean up from the main worktree
- scripts/cleanup-worktree.sh fix-cron
- ```
+ ## Naming
- Both steps are scripted: `scripts/setup-worktree.sh <branch> [base]` and `scripts/cleanup-worktree.sh [branch]`.
+ - Root: sibling `<project>.worktrees/` directory.
+ - Directory: branch slug only; replace `/` with `-`.
+ - Examples: `fix-cron`, `feature-auth`, `bugfix-issue-123`.
- ## Directory Layout
+ ## Cleanup Workflow
- All worktrees for a project live under one root, `<project>.worktrees/`, a sibling of the main repo (never nested inside it):
+ For one named worktree after PR merge:
- ```
- ~/projects/
- ├── myproject/ # main worktree — always on main, always clean
- └── myproject.worktrees/ # per-project worktree root
- ├── fix-cron/ # worktree for fix-cron branch
- ├── feature-auth/ # worktree for feature/auth branch
- └── bugfix-123/ # worktree for bugfix/issue-123 branch
+ ```bash
+ scripts/cleanup-worktree.sh [branch]
```
- Why a sibling root: one tidy place per project, no .gitignore pollution, clean git status, independent build artifacts. The root is removed automatically once its last worktree is cleaned up.
-
- ## Naming Convention
-
- Worktree dir is the branch slug only — slashes become dashes. No project prefix; the `<project>.worktrees/` root already scopes it.
-
- - `fix-cron` — `myproject.worktrees/fix-cron`
- - `feature/auth` — `myproject.worktrees/feature-auth`
- - `bugfix/issue-123` — `myproject.worktrees/bugfix-issue-123`
-
- ## When to Suggest Worktrees
-
- - User wants to start a new feature, fix, or experiment
- - User is about to edit code on main/master
- - User wants to try multiple approaches to the same problem
- - User has uncommitted changes and wants to start something else
-
- ## Cleanup on PR Merge
-
- When a PR merges, remove the worktree and delete its branch. State clearly what is being removed and why before running anything destructive.
+ The helper refuses unless `gh` confirms the PR is `MERGED`. Pass `--force` only after the user confirms the merge without `gh` or confirms the branch should be abandoned.
- Squash and rebase merges rewrite the commit, so `git branch -d` reports the branch as "not fully merged" even though the PR is merged. The source of truth is the PR state, not local ancestry — do not conflate them.
+ For bulk cleanup, stale worktrees, gone upstreams, or merged local branches, use `cleanup-git`.
- Use `scripts/cleanup-worktree.sh [branch]`. It is strict by default: unless `gh` confirms the PR is MERGED it changes nothing and exits with a single clear message. Pass `--force` to proceed anyway — when `gh` is not installed (you confirm the merge) or to abandon an unmerged branch on purpose; `--force` also force-removes a dirty worktree and force-deletes the branch. It defaults to the current worktree's branch, refuses to remove the main worktree, `cd`s out of the worktree before removing it, falls back to `git branch -D` for the squash/rebase case, runs `git fetch --prune`, and prunes the empty root. It does not run `git pull` — pull main yourself afterward only once you have confirmed main is checked out and clean. WORKFLOW.md has the manual command sequence for when the script is unavailable.
+ Do not run `git pull` as part of cleanup. Pull the integration branch only after confirming the main worktree is checked out and clean.
- ## Failure handling
+ ## Failure Handling
- - Worktree path already exists: pick a different branch/slug; never force-overwrite.
- - Branch already exists remotely: use `git worktree add "$root/<slug>" <branch>` (no `-b`) to check it out.
- - Dirty main repo when user wants a new worktree: ask to commit, stash, or proceed anyway — do not silently stash.
- - `git worktree remove` fails with "is dirty": confirm with user before running `git worktree remove --force`.
- - `git branch -d` says "not fully merged" after a squash/rebase PR merge: confirm the PR is MERGED, then use `git branch -D` — this is expected, not data loss.
- - Invoked from inside the worktree being removed: `cd` to the main worktree first, or the shell ends up in a deleted directory.
+ - Worktree path exists: pick a different branch/slug; never overwrite.
+ - Branch already exists remotely: check it out without `-b` or use the helper.
+ - Dirty current worktree: ask to commit, stash, or continue with explicit approval.
+ - `git worktree remove` fails because the worktree is dirty: confirm before `--force`.
+ - `git branch -d` fails after squash/rebase PR merge: confirm the PR is `MERGED`, then use `-D`.
+ - Invoked from inside the worktree being removed: change to the main worktree before removing it.
## Output
```text
WORKTREE READY
==============
Action: CREATE | CLEANUP
Branch: <branch>
Path: <project>.worktrees/<slug>
Status: DONE | BLOCKED
Next:
- - cd into the worktree path and open the editor there, or
- - pull main yourself after a confirmed cleanup
+ - cd <path> and open the editor there, or
+ - pull the integration branch yourself after confirmed cleanup
```
- For cleanup, only report DONE when the PR is confirmed MERGED (or `--force` was used deliberately); otherwise status is BLOCKED with the single reason the script reported.
+ For cleanup, report `DONE` only when the PR is confirmed `MERGED` or `--force` was used deliberately. Otherwise report `BLOCKED` with the script's reason.
## References
- - [WORKFLOW.md](references/WORKFLOW.md) - Detailed steps, project setup, cleanup, common mistakes
- - [scripts/](scripts/) - setup-worktree.sh and cleanup-worktree.sh
+ - [workflow.md](references/workflow.md) — manual fallback and edge cases
+ - [scripts/](scripts/) — `setup-worktree.sh` and `cleanup-worktree.sh`