Consolidate git
An opinionated Claude operating system for PM-led engineering. Planning, enrichment, delegated execution, staged review, ship decisions, durable handoffs.
npx -y skills add dbc-oduffy/coordinator-claude --skill consolidate-gitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Cleans up branch sprawl. Triggers: consolidate branches, clean up branches, stale branches, merge all branches.
SKILL.md
14.4 KB, as published. Nobody here has run it
Consolidate Git — Branch + Worktree Cleanup
Overview
Reduce branch and worktree sprawl to a single clean workstream branch. Inventories all local and remote branches AND all worktrees, absorbs any unique commits into the current branch, deletes stale branches, and removes stale worktrees (including locked ones whose work has been absorbed).
This skill does NOT merge to main by default. Consolidation and shipping are separate decisions. The goal here is to leave the repo with one current branch holding all of my in-flight work, no leftover sibling branches, no stale worktrees. Whether that branch is ready to ship to main is a separate judgment for /merge-to-main, made after this skill reports. At the end, the EM MAY ask the PM whether to chain into /merge-to-main if the consolidated branch looks merge-ready — but the default exit is "consolidation complete, branch is yours."
Worktrees are not exempt. A worktree whose branch tip is already absorbed into main (or the current branch) is stale state, not active work — the branch lock is a stale signal, not a permanent reservation. The skill removes such worktrees by default. Worktrees with genuine unique commits proceed through the same absorb-or-skip evidence gate as any other branch.
Announce at start: "I'm using the coordinator:consolidate-git skill to consolidate branches and worktrees into the current branch. Merge to main is a separate step."
The Process
Step 1: Inventory Branches
List all local and remote branches, determine ownership, and categorize.
1a. Identify the current user:
MY_EMAIL=$(git config user.email)
1b. List all branches with tip author:
git branch -a
For each branch (excluding main and the current branch), check the author of the most recent commit on the tip:
# Local branch:
git log -1 --format='%ae' <branch>
# Remote-only branch:
git log -1 --format='%ae' origin/<branch>
1c. Categorize each branch:
| Category | Definition | Action |
|---|---|---|
| current | The checked-out branch | Absorb target — everything merges here |
| main | The trunk branch | Merge target — current branch merges here at the end |
| mine (stale) | Tip author matches $MY_EMAIL | Check for unique commits, absorb if any, then delete |
| other's | Tip author does NOT match $MY_EMAIL | Leave untouched |
1d. Present the inventory to the PM as a table:
| Branch | Local | Remote | Owner | Category |
|--------|-------|--------|-------|----------|
| main | yes | yes | — | trunk |
| work/machine-a/2026-03-20 | yes | yes | me | mine (stale) |
| feature/foo | no | yes | me | mine (stale) |
| feature/bar | no | yes | [email protected] | other's — skipped |
| work/machine-a/2026-03-23 | yes (current) | yes | me | current |
Only branches categorized as "mine (stale)" proceed to Steps 2–5. Other people's branches are reported but never touched.
Step 1.5: Inventory Worktrees
Enumerate all worktrees and join against the branch inventory. A worktree is just another checkout of a branch — its branch is subject to the same absorb-or-skip logic as any other branch. The only special handling: the worktree directory itself must be removed before the branch can be deleted.
git worktree list --porcelain
For each worktree (excluding the primary .git-owning checkout):
- Record the worktree path, branch, HEAD sha, and lock state (the
lockedline in porcelain output). - Treat the branch the same way as any local branch in Step 1c — owner check by tip-commit author, category by reachability:
- Branch tip reachable from
origin/mainOR from the current branch → stale (worktree absorbed) → candidate for removal. - Branch tip has unique commits → stale (worktree has unique work) → goes through Steps 2–4 like any other branch.
- Tip author is not me → other's worktree — skipped (report only).
- Branch tip reachable from
Add a Worktrees section to the inventory table:
### Worktrees
| Path | Branch | Locked | Owner | Category |
|------|--------|--------|-------|----------|
| .claude/worktrees/agent-a07… | worktree-agent-a07… | yes | me | stale (absorbed into main) |
| .claude/worktrees/agent-aec… | worktree-agent-aec… | yes | me | stale (absorbed into main) |
Locked is not a veto. A lock from a long-finished isolation run is exactly the state this skill exists to clean up. If the branch is absorbed, the worktree gets removed in Step 5 with --force after the lock is cleared (git worktree unlock <path>). If the worktree has uncommitted changes (git -C <path> status --porcelain non-empty), surface them to the PM before removing — that is genuine in-flight work and warrants pause.
Step 2: Check for Unique Commits
For each stale branch, check if it has commits not in the current branch:
# For local branches:
git log --oneline <current-branch>..<stale-branch>
# For remote-only branches:
git log --oneline <current-branch>..origin/<stale-branch>
Categorize the result:
- No unique commits — safe to delete immediately
- Has unique commits — proceeds to Step 3 (inspection), then Step 4 (verdict)
Do NOT label a branch "superseded," "stale-experiment," "already-applied," or any other verdict at this step. The only categories Step 2 emits are no unique commits and has unique commits — count N. Anything else is a Step 4 verdict and requires Step 3 evidence first.
Step 3: Inspect Unique Commits (Evidence Gate)
Hard gate: no verdict may be emitted before this step's output is on the page.
For each branch flagged "has unique commits" in Step 2, run BOTH:
git log --oneline <current-branch>..<stale-branch-or-origin/...>
git show --stat <each-commit-sha>
Then emit an inspection table to the PM before proposing any absorb/skip decision:
### Inspection: <branch-name> (<N> unique commits)
- <sha> <subject> — files: <path1>, <path2> (+X/-Y)
- <sha> <subject> — files: <path1> (+X/-Y)
For commits whose diff is non-trivial (>~20 lines or touches shared infra / plugin internals / configs), also run git show <sha> and quote the load-bearing hunks in 1–3 lines.
Self-check before moving to Step 4 — answer each in one sentence, in the message:
- Have I actually run
git show --stat(orgit show) on every listed sha? (If no: stop, run it.) - For each commit, what file(s) on the current branch supersede it, named by path? (If "current branch has a newer version" without a path, that's a guess, not evidence.)
- Are any of these commits touching files the current branch never touched? (If yes: not superseded — must absorb.)
A "superseded" verdict that names no superseding path on the current branch is a doctrine violation — go back and look.
Step 4: Absorb or Skip (Verdict)
Only after Step 3's inspection table and self-check are on the page, for each branch:
- Choose absorption strategy (inline override required on each git op that switches branches):
- Cherry-pick (default for 1-3 commits):
# Inline override required: cherry-pick involves switching from the active work branch; # COORDINATOR_OVERRIDE_BRANCH=1 is still required even after block-off-daily-branch.sh retirement. COORDINATOR_OVERRIDE_BRANCH=1 COORDINATOR_OVERRIDE_BRANCH_REASON="consolidate-git step 3 cherry-pick from <stale-branch>" \ git cherry-pick <commit> --no-edit - Merge (for branches with many commits):
COORDINATOR_OVERRIDE_BRANCH=1 COORDINATOR_OVERRIDE_BRANCH_REASON="consolidate-git step 3 merge <stale-branch>" \ git merge <stale-branch> --no-edit
- Cherry-pick (default for 1-3 commits):
- If conflicts arise:
- Inspect the conflicting files — determine if the current branch already supersedes the change
- If superseded: abort (
git cherry-pick --abortorgit merge --abort) and skip — note this in the report - If genuinely needed: resolve conflicts, then continue
- Do NOT force through conflicts blindly — each conflict is a signal that needs inspection
Report each absorption decision to the PM:
"Branch
work/machine-a/2026-03-20has 2 unique commits — both are experiment data snapshots already superseded by current branch. Skipping."
or:
"Branch
feature/auth-rewritehas 5 unique commits with real code changes. Cherry-picking into current branch."
Step 5: Delete Stale Branches and Worktrees
After all unique commits are absorbed (or explicitly skipped), remove stale worktrees first (a branch checked out in a worktree cannot be git branch -d'd), then delete the branches.
5a. Remove stale worktrees:
For each worktree categorized as stale in Step 1.5 (and not flagged as having uncommitted changes the PM elected to preserve):
# Clear the lock if present — the lock is leftover isolation-mode state, not a live reservation.
git worktree unlock <path> 2>/dev/null || true
# Remove the worktree. --force is needed because locked/checked-out worktrees
# refuse plain `git worktree remove`. Safe here: we already verified the branch
# tip is reachable from main / current and the working tree is clean (or PM-approved).
git worktree remove --force <path>
After removing all stale worktrees, prune any administrative remnants:
git worktree prune
5b. Delete branches:
# Local branches — use safe delete (-d), not force delete (-D)
git branch -d <branch>
# Remote branches — batch deletions into one push
git push origin --delete <branch1> <branch2> <branch3>
Use -d (safe delete), not -D. Safe delete will refuse if the branch has unmerged commits — this is a final safety net. If -d refuses, investigate before escalating to -D with PM approval.
After deletion, prune stale remote tracking refs:
git fetch --prune
Step 6: Post-Absorb Re-Verify Shared Infra (example-repo T1.7)
When conflicts were resolved during cherry-pick or merge in Step 4 — especially on shared files (plugin internals, shared scripts, configs) — re-verify that the absorbed changes actually survived.
Why this matters: Last-writer-wins silently reverts edits when both sides touched the same hunk and the conflict was resolved naively. An absorption that "succeeded" may have silently dropped changes from the source branch.
Verification steps:
- For each file with a known specific change:
git show HEAD:<file-path> | grep -F "<canonical phrase from your change>" - If a canonical phrase is missing, your change was overwritten. Re-apply it with a follow-up commit.
- This is especially important for
~/.claude/plugin files and project-wide config files touched by multiple branches in the consolidation.
Step 7: Report
## Branch Consolidation Complete
### Absorbed
- `work/machine-a/2026-03-20` — no unique commits (already merged)
- `feature/foo` — 3 commits cherry-picked into current branch
### Skipped (superseded)
- `work/machine-a/2026-03-19` — 1 commit (stale experiment data, current branch has newer version)
### Deleted
- Local: work/machine-a/2026-03-20, work/machine-a/2026-03-19
- Remote: origin/work/machine-a/2026-03-20, origin/work/machine-a/2026-03-19, origin/feature/foo
- Worktrees: .claude/worktrees/agent-a07… (branch absorbed into main), .claude/worktrees/agent-aec… (branch absorbed into main)
### Left Untouched (other owners)
- `feature/bar` ([email protected]) — not ours, skipped
### Current State
- On branch: `work/machine-a/2026-03-23` @ {sha}
- Ahead of `origin/main` by N commits — not merged (consolidation only)
- All of *my* sibling branches and worktrees absorbed or removed; only main + other owners' branches remain
Step 8: Optional Merge-to-Main Prompt (EM Judgment)
After reporting, the EM MAY ask the PM whether to chain into /merge-to-main — but only when the consolidated branch looks merge-ready. Default exit is to stop here.
Skip the prompt when:
- The current branch is already main (nothing to merge).
- Consolidation produced unresolved skips, dirty worktrees flagged for PM review, or conflicts that warranted pause.
- The branch is mid-workstream (recent commits suggest active development, not a ready checkpoint).
Offer the prompt when:
- Consolidated branch contains finished, reviewed work and would have been a
/merge-to-maincandidate before consolidation started. - The PM's framing for invoking consolidation suggested shipping intent.
Phrase as a recommendation, not a question to ratify default behavior:
"Consolidated branch looks merge-ready (N commits ahead of main, all absorbed work passes review). Want me to chain into
/merge-to-main?"
Otherwise: stop. Merge to main is a separate invocation.
Edge Cases
If on main with no other branches: Abort early — nothing to consolidate.
If the current branch is behind main: Merge main into the current branch first before absorbing other branches — ensures the final state includes everything.
If a stale branch has diverged significantly: Prefer merge over cherry-pick. If the merge has extensive conflicts, flag to the PM rather than resolving silently — the PM may want to inspect before committing.
If remote branches have no local counterpart: Fetch them first (git fetch origin <branch>) to inspect their commits, then delete the remote after inspection.
What This Does NOT Do
- Merge to main — consolidation lands everything on the current branch and stops. Shipping is
/merge-to-main, invoked separately by the PM (optionally suggested by the EM in Step 8 when the branch looks merge-ready). - Rebase — merges and cherry-picks only. Rebasing rewrites history and adds risk for no benefit in a cleanup operation.
- Touch other repos — scoped to the current repository only.
- Delete main — main is always preserved as the merge target.
- Force-delete branches — uses
-d(safe) by default.-Donly with explicit PM approval. - Touch other people's branches or worktrees — only branches/worktrees where the tip commit author matches the current user's
git config user.emailare candidates. Everyone else's are reported but never modified or deleted. - Remove worktrees with uncommitted changes silently — dirty worktrees are surfaced to the PM. The default for stale-but-clean (including locked) is removal; the default for dirty is pause.