Skip to content
Back to skills

Using Git Worktrees

ASecurity

Use when work needs its own branch and checkout — a long feature, a risky refactor, or a parallel attempt.

  • 3 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
ai-agentsgoshellbashgit

Security analysis

A100/100

Scanned September 27, 2026

npx -y skills add felipemelendez/llm-orchestrator --skill using-git-worktrees --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Using Git Worktrees?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Using Git Worktrees
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/felipemelendez-using-git-worktrees/badge)](https://www.skillsdirectory.com/skills/felipemelendez-using-git-worktrees)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: using-git-worktrees
description: Use when work needs its own branch and checkout — a long feature, a risky refactor, or a parallel attempt.
---

# Using git worktrees

Use directory isolation for concurrent or risky work. Skip tiny edits when the
checkout is safe. Commit only within authorized scope.

## Proportional cadence

For enabled `workflow: proportional`, use the cadence resource helper only when
isolation is needed. Acquire a lease, create a copy/worktree, release after all
consumers stop, then explicitly finish after preserving deliverables. The helper
checks ownership, leases, locks, ignored/dirty files and retained commits before
non-forcing removal. Report retained paths. Never adopt old resources. No
automatic dependencies or broad baseline suites. Stop here; the steps below
are for projects without an enabled cadence.

## Delegation

Do not hand the checkout to the harness's per-agent worktree isolation (`isolation: worktree` on
dispatch) — it was evaluated and rejected, and the reasons apply to the interactive single-writer
case as much as to batch fan-out: the harness branches from the default branch, not your current
`HEAD`, so the subagent edits against the wrong base; the `worktree.baseRef: head` mitigation is a
user setting a plugin cannot ship; the harness never reports the worktree path, so the registry
claim, provenance marker, and green-baseline capture below have nowhere to land; and native
cleanup keeps changed worktrees in a location the reaper never scans. (The dated evaluation brief
lives under `docs/llm-orchestrator/research/`, a local working directory that is not distributed;
the operative reasons are all inline here.) Create the worktree yourself with the steps below —
for parallel writers, the materialize engine per `dispatching-parallel-agents` — and pass the path
into the dispatch envelope.

## Steps

1. **Check for existing isolation.** If `git rev-parse --git-dir` and `--git-common-dir` differ,
   you're already in a worktree — don't nest.

2. **Pick the directory.** `.worktrees/<slug>` — project-local, and the only path the tooling
   knows: `scripts/orch-worktree-materialize.sh` hardcodes `${PWD}/.worktrees/` and the reaper
   only scans there (a `~/.llm-orchestrator/worktrees/` fallback was documented once but never
   implemented). If the project-local path is unusable, stop and say so rather than inventing a
   location nothing else knows about.

3. **Add the worktree — on a unique path and a unique branch.** Never point two writers at the
   same directory or the same branch.
   ```
   git worktree add .worktrees/<slug> -b <branch-name>
   ```
   `git worktree add` itself refuses a path that already exists or a branch already checked out
   elsewhere — that refusal is your mechanical guard against two writers colliding on one tree.
   If it errors with "already exists" / "already checked out", stop: a sibling owns that
   worktree; pick a different slug, do not reuse it.

4. **Mark provenance.** Drop `.orch-worktree` in the new dir (cleanup only removes worktrees with
   this marker). `.orch-worktree-lock` records the owning session id for the registry's
   `--list`/`--release` — it is *informational provenance*, not the anti-clobber mechanism.

   The two **real mechanical guards** are: (a) at create time, `git worktree add`'s refusal of a
   duplicate path/branch plus the registry's atomic `mkdir` claim (see
   `orch-worktree-materialize.sh`); (b) at write time, the implementer's atomic
   `mkdir <worktree>/.orch-active` mutex — two writers handed the same path can never both
   proceed, because `mkdir` has exactly one winner. Both fail loudly; neither relies on a writer
   reading and obeying a text file.

   The mutex guard only means something when the thing at the path is what the protocol defines:
   a *directory* created by `mkdir`. A **regular file** at an `.orch-active` path is
   **protocol corruption**, not a held lock — a hold-marker something improvised outside the protocol (a
   controller once dropped one at the repo root and blocked every obedient writer). `mkdir` fails
   against it forever, no writer owns it, and the reaper refuses to remove what no successful
   mkdir claimed. Operator remedy: inspect and delete the file (`rm`, not `rmdir`). The
   implementer's BLOCKED message distinguishes "held by a writer (directory)" from "corrupted
   (file)" so nobody chases a phantom writer.

5. **Add to .gitignore if needed.**
   ```
   grep -q '^\.worktrees/' .gitignore || echo '.worktrees/' >> .gitignore
   ```

6. **Set up the project.** Install dependencies per the manifest (`package.json` → pnpm/npm/yarn
   from lockfile, `Cargo.toml` → `cargo build`, `pyproject.toml` → `uv sync`/`poetry install`,
   `go.mod` → `go mod download`).

7. **Run baseline tests and record.** Capture the green state before any edits and persist it so
   the regression guard can compare later.
   ```
   orch_lib() { local n="$1" p; for p in "${CLAUDE_PLUGIN_ROOT:-}/scripts/lib/$n" "$HOME/.claude/llm-orchestrator/scripts/lib/$n" "$(pwd)/.claude/scripts/lib/$n"; do [ -f "$p" ] && { printf '%s\n' "$p"; return; }; done; find "$HOME/.claude/plugins" -name "$n" -path '*llm-orchestrator*' 2>/dev/null | sort -V | tail -1; }
   L=$(orch_lib orch-detect.sh) && . "$L" && orch_regression_baseline <worktree-dir>
   ```
   This detects the test command, runs it, and writes
   `~/.llm-orchestrator/toolchain/<hash>/baseline.<tree-hash>.md` — the filename is keyed on the
   worktree's absolute path, so sibling worktrees of one repo each get their own baseline and
   cannot disarm each other's regression guard. If the suite is not green at this point, stop —
   do not proceed with edits until the baseline is clean.

## A submodule is not a worktree

`GIT_DIR != GIT_COMMON_DIR` is true inside a git submodule as well as inside a linked worktree,
so that comparison alone misidentifies one as the other. Check before acting:

```bash
git rev-parse --show-superproject-working-tree   # non-empty ⇒ you are in a submodule
```

Inside a submodule, worktree creation and cleanup are the wrong operations.

## Cleanup

Release the ownership claim **before** removing the worktree (so a concurrent prune can't race
the removal), then remove:

```
cd "$(git rev-parse --show-toplevel)"
MAT="${CLAUDE_PLUGIN_ROOT:-.}/scripts/orch-worktree-materialize.sh"; [[ -f "$MAT" ]] || MAT=".claude/scripts/orch-worktree-materialize.sh"
SID="$(bash "$MAT" --sid)"
bash "$MAT" --release "$SID" <slug>
git worktree remove .worktrees/<slug>
git worktree prune
```

Run removal from the repo root as its own command: deleting the shell's working
directory makes subsequent commands fail with "unable to read current working directory".

Refuse cleanup if `.orch-worktree` is missing — that worktree wasn't ours. If
`--release` reports "release denied" or "refusing to release in-progress claim",
retain the worktree and resolve ownership before removing it. A denied release
is not permission to delete another consumer's workspace.

## Output shape

```
Changed:
- created worktree .worktrees/<slug> on branch <branch-name>
- baseline tests: 142 passed
Verify:
- cd .worktrees/<slug> && pnpm test → 142 passed
Next:
- /llm-orchestrator:dispatch task 1 against this worktree
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.