worktree-guard
Skill1 starsChanged 8 months agoMITView on GitHub
Safe worktree merge — diffs each changed file against dev HEAD before copying, flags conflicts. Use BEFORE copying worktree files to the main tree. Triggers: 'merge worktree', 'copy from worktree', after any worktree agent completes with changes.
- Commits and pushes
In this repository51 other files it gives its agents.
- algorithmic-artSkill
- audit-componentsSkill
- canvas-designSkill
- cascade-orchestrationSkill
- consultSkill
- data-reconciliationSkill
- debug-collaborateSkill
- deep-root-causeSkill
- deploy-allSkill
- design-reverse-engineerSkill
- design-showcaseSkill
- docxSkill
- env-auditSkill
- evolveSkill
- frontend-designSkill
- full-stack-buildSkill
- full-stack-traceSkill
- gh-repo-reconSkill
- grill-meSkill
- handoffSkill
- html-slidesSkill
- insightSkill
- internal-commsSkill
- isolation-testSkill
- mcp-builderSkill
- model-selectionSkill
- pdfSkill
- persistent-issueSkill
- pre-merge-reviewSkill
- premise-auditSkill
- propagate-featureSkill
- regression-bisectSkill
- research-gateSkill
- review-implSkill
- schema-checkSkill
- session-notesSkill
- skill-auditSkill
- skill-creatorSkill
- slack-gif-creatorSkill
- start-daySkill
- temporal-forensicsSkill
- theme-factorySkill
- throwaway-scriptSkill
- triage-ideasSkill
- verify-completeSkill
- webapp-testingSkill
- web-artifacts-builderSkill
- wisdomSkill
- worker-buildSkill
- write-planSkill
- xlsxSkill
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 6 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 37
If a file appears in BOTH lists, it's a conflict.
- Distinctive: line 60
After all files merged:
- Distinctive: line 65
If build fails, the merge introduced an error — investigate before committing.
- Very specific: line 78
When a worktree agent commits its changes to a branch, use this sequence to integrate back into dev (this is the canonical pattern):
- Very specific: line 84
Test: Run project tests + npm run build in each affected project before pushing.
- Very specific: line 87
Empty diff = silent commit failure: If git log main..origin/<agent-branch> returns nothing, the agent ran but never committed.
- Distinctive: line 187
Run the real install: when a genuine build is needed.
- Very specific: line 202
NEVER cp a worktree file over a main tree file without checking for conflicts first
- Distinctive: line 203
NEVER assume worktree has the latest version — it branched from an earlier commit
- Distinctive: line 204
NEVER merge worktrees in sequence without rebuilding between each (cascading conflicts)
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Worktree Guard — Safe Merge
Prevents worktree agents from silently overwriting changes made earlier in the session or by other worktrees.
When to Use
MANDATORY before copying any files from .claude/worktrees/agent-* to the main working tree. This skill should be invoked automatically when:
- A worktree agent completes with file changes
- Multiple worktree agents ran in parallel and need merging
- Any
cpcommand targets files from a worktree path
Steps
1. Identify Changed Files
For each worktree that needs merging:
cd <worktree-path> && git diff --name-only2. Check for Conflicts
For each changed file in the worktree, check if the same file was modified in the main tree since the worktree branched:
# Get the worktree's base commit
BASE=$(cd <worktree-path> && git merge-base HEAD origin/dev)
# Check if file changed in dev since base
git diff --name-only $BASE..HEAD -- <file-path>If a file appears in BOTH lists, it's a conflict.
3. Handle Conflicts
For each conflicting file:
- Show a side-by-side summary: what the worktree changed vs what dev changed
- DO NOT silently overwrite — present options:
- Merge manually: Apply worktree additions without removing dev changes (append CSS, merge JSX carefully)
- Keep dev: Skip the worktree's version of this file
- Keep worktree: Overwrite (only if user explicitly confirms)
- For CSS files (most common conflict): append worktree additions to the end of the dev version
- For JSX/JS files: use Edit tool to surgically add worktree's new code blocks into the dev version
- Refined rule for a shared/common hub directory: if the conflicting file lives in a shared library layer imported by many consumers (utils, hooks, shared components), prefer Keep worktree (
git checkout --theirs <file>) — the agent's edits ARE the intended change, and a shared hub is rarely touched by unrelated work in the same window. Fall back to a manual merge only when step 2 shows the main branch and the worktree independently touched the same file.
4. Safe Copy
For non-conflicting files, copy directly:
cp <worktree-path>/<file> <main-tree>/<file>5. Verify
After all files merged:
cd <project> && npm run buildIf build fails, the merge introduced an error — investigate before committing.
Common Conflict Patterns
| File Type | Strategy |
App.css | Append new CSS blocks from worktree to end of dev file |
App.jsx | Surgical Edit — add new imports, state, JSX where needed |
| API handler files | Add new endpoint cases to existing if/else chain |
package.json | Merge dependencies (usually additive) |
Worktree Agent Cherry-Pick Lifecycle (6 Steps)
When a worktree agent commits its changes to a branch, use this sequence to integrate back into dev (this is the canonical pattern):
- Fetch:
git fetch origin <agent-branch>after agent reports completion - Diff:
git log main..origin/<agent-branch> --onelineto confirm commits exist. If empty, the agent failed to commit — redo the work in the main tree. - Cherry-pick:
git cherry-pick origin/<agent-branch>(single commit) orgit cherry-pick <first>^..<last>for multi-commit branches. For a clean integration,git merge --no-ff origin/<agent-branch>also works. - Conflict handling: For conflicts in shared files, prefer
git checkout --theirs <file>— the agent's edits are the intended changes; main usually has unrelated drift. Manual merge only when both sides independently touched the same region. - Test: Run project tests +
npm run buildin each affected project before pushing. - Cleanup:
git worktree remove <path>andgit branch -D <agent-branch>once merged. Remote branch:git push origin --delete <agent-branch>.
Empty diff = silent commit failure: If git log main..origin/<agent-branch> returns nothing, the agent ran but never committed. Do not proceed — redo the task.
Post-Merge Teardown
Generalizes the merge flow above to ANY merged worktree — a cherry-picked agent branch OR a merged PR worktree. Tear down immediately after merge confirmation (or after git merge-base --is-ancestor <wt-HEAD> origin/<main-branch> confirms the commits landed) — don't defer to session end. Stale worktrees accumulate (one audit had to bulk-remove 21) and cause "already checked out" errors when a branch name is reused:
git worktree remove -f <path-to-worktree> # -f needed when a lockfile is dirty from an install
git worktree prune # clear stale refs — especially after a multi-worktree session
git branch -d <branch-name> # if a branch was created for itPeriodic hygiene: git worktree list | wc -l — if it climbs past a handful, audit each worktree's HEAD with git merge-base --is-ancestor <wt-HEAD> origin/<main-branch> and bulk-remove only those already merged. If you find yourself hand-rolling this create/list/teardown/prune cycle often, wrap it in a small helper script (create/list/finish/prune subcommands) rather than reproducing the recipe by hand each time — cheap to write, and it removes the "did I remember every step" risk.
Bulk Cleanup — When Worktrees Have Already Piled Up
The single-worktree teardown commands above silently fail at scale, which is exactly how a list balloons into the hundreds despite following this skill. Three mechanics defeat a naive bulk-removal loop, in this order:
1. A locked worktree blocks BOTH remove and prune. Session-created worktrees are often
created locked, so git worktree remove --force fails on them and git worktree prune skips
them too — a bulk loop reports mass failures with no obvious cause. The lock lives at
.git/worktrees/<id>/locked. Check the real spread before looping:
ls .git/worktrees | wc -l # registrations (may exceed live dirs)
ls .git/worktrees/*/locked 2>/dev/null | wc -l # how many are locked2. git worktree prune honors a grace period by default (gc.worktreePruneExpire,
typically 3 months) — a registration whose directory is already gone is NOT reaped, and prune
prints nothing, which reads as "nothing to do." Always pass --expire=now for an active
cleanup.
3. Removing worktrees one at a time is slow (each deletes a full directory tree). Deleting the directories directly and reaping every stale registration in ONE prune is far faster. Safe ordering — delete the directory, clear the lock only for registrations whose directory is already gone, then prune:
# per target: delete the worktree directory (fs remove, recursive)
# then, for every .git/worktrees/<id> whose gitdir path no longer exists: rm .git/worktrees/<id>/locked
git worktree prune --expire=nowScoping the unlock to missing directories is the safety invariant — a worktree still on disk is never touched, so an active session can't be unlocked out from under it.
Before deleting: what "dirty" actually means here
Don't trust git status dirtiness alone as evidence of real work. A worktree whose index
has been wiped shows as heavily modified (mass staged deletions) while git diff is empty and
the actual content is intact but untracked — the entry that looks most dangerous to delete can
hold nothing at all.
The checks that actually decide, cheapest first:
git cherry origin/<default-branch> <branch>— empty means every commit on the branch is already upstream. Patch-id aware, so it survives the squash-merge of a ONE-commit branch; ancestry alone does not. The match is per commit, so a branch of 2+ commits squashed into one shows+for every commit even though it merged. For those, compare the whole range as one patch:git diff origin/<default-branch>...<branch> | git patch-id --stableagainstgit show <squash-sha> | git patch-id --stable.- Untracked files that are genuinely novel — diff the untracked set against
git ls-tree -r origin/<default-branch> --name-only. Most "novel"-looking untracked files turn out to be untracked copies of already-tracked files. - Novel source files against history —
git log --all --diff-filter=D -- <path>for anything still novel after step 2. Most turn out to be deliberate, recoverable deletions from a real commit; a file with genuinely no history anywhere is the rare one worth archiving before you delete the worktree.
Archive that genuinely-novel set before deleting (cheap insurance, and it makes the delete reviewable), and exclude your own current session's worktree — it's registered like any other and is trivially the newest by modified time.
git worktree remove never deletes the branch — a worktree removed by mistake loses only
the working directory; its commits survive on the branch. Clean up branches separately with
git branch -d (not -D) against --merged origin/<default-branch>, so git's own merge
check is a second gate — it also refuses to delete a branch currently checked out anywhere.
Finish with git fsck --connectivity-only: a registration whose HEAD resolves to nothing is
a corrupt empty shell, safe to clear the same way as a missing-directory registration.
Sibling Worktrees (per-concurrent-session isolation)
Distinct from the merge flow above: when several sessions run at once, each concurrent task should get its own sibling worktree — a peer directory next to the main checkout (e.g. ../<repo>-<topic>) — so one session's branch switch or cleanup can't clobber another's uncommitted work. Use this instead of sharing a single checkout across sessions. For a throwaway, non-cd'd scratch tree, a lighter alternative is a leading path variable pointing into a scratch/temp directory.
Create (off your default integration branch for most tracks, off the release branch for a follow-up to something already shipped):
git worktree add -b <you>/<topic> "../<repo>-<topic>" origin/<default-branch> # new branch
git worktree add "../<repo>-<topic>" <you>/<existing-branch> # existing branchcd into it and treat it as a full standalone checkout (edit / grep / build / test / commit from inside).
Bootstrap deps so tests/builds work in the fresh tree:
- Junction/symlink the main repo's dependency directory (fast — for a test-only run): on Windows,
cmd.exe /c 'mklink /J "<worktree>\node_modules" "<main-repo>\node_modules"'— note/J(junction), NOT/D(symlink; needs admin, fails without it). On macOS/Linux, a plain symlink works. - Run the real install when a genuine build is needed. If it churns the lockfile, restore the original from your default branch afterward to keep the churn out of the feature diff.
- Copy in any gitignored local secrets/keys the sibling needs for deploy-adjacent operations.
Teardown (immediately after the branch lands — don't defer to session end):
rmdir <worktree>/node_modules # un-junction/un-link FIRST if you linked it
git worktree remove "../<repo>-<topic>" --force # --force if the lockfile is dirty
git branch -D <you>/<topic>A junctioned/symlinked dependency directory must be removed before worktree remove, or removal trips on it.
Anti-Patterns
- NEVER
cpa worktree file over a main tree file without checking for conflicts first - NEVER assume worktree has the latest version — it branched from an earlier commit
- NEVER merge worktrees in sequence without rebuilding between each (cascading conflicts)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

