Git Worktree Lifecycle Recovery
Use when merged worktrees retain local work. Recover safely. Recover local commits, dirty files, or artifacts left on branches whose pull requests have merged, then retire stale worktrees and refs without data loss.
When to Use
- A worktree is still checked out on a branch after its PR merged.
- Local commits exist beyond a merged PR head.
- A dirty worktree must be salvaged before branch deletion.
- A squash merge makes branch-vs-default history look unmerged.
- Several stale issue branches need an auditable cleanup runbook.
Do not use this skill to implement the salvaged feature itself. Approved follow-up implementation starts a new issue/branch/PR lifecycle.
Invariants
- Read the associated PR from the live API in the same run before citing it, pushing, or deleting its branch. Capture
state, merged status/time, head branch, head SHA, base, and merge commit. - A merged PR is finished. Never append work to its branch or reopen it as the delivery path.
- Preserve before judging and judge before deleting.
- Dirty source, untracked artifacts, ignored build output, and remote refs are separate evidence classes; do not handle them with one blind
git add -Aorgit clean. - Every external write or deletion is read back from the exact target.
- Squash-merge commit ancestry alone is not content verification.
Procedure
1. Establish an exclusive, evidence-producing run
Identify every target worktree and ensure no writer is using it. Create a private evidence directory outside all repositories. Record the initial worktree list, branch tips, status, ignored inventory, and remote configuration. Avoid putting tokens, customer data, or file contents into command transcripts.
If the normal remote is intentionally disabled or non-networked, do not rewrite it casually. Use an explicitly approved temporary remote and authenticated credential helper, verify it with a read-only request, and remove it after the run. Environment-specific remote setup belongs in the runbook, not as a permanent assumption in this skill.
2. Read live PR and default-branch state
For every branch, query its associated PR and current default-branch head. Confirm the PR head SHA matches the branch being retired. Record the PR's changed files or distinguishing content.
A non-empty default..HEAD range can be normal after a squash merge. Confirm delivery by checking the PR's changed-file set or representative content against the merge/default branch. Do not conclude that content is missing merely because the old head is not an ancestor.
3. Classify local residue
Capture, without mutation:
- tracked and untracked status;
- ignored-file names, never their contents by default;
- commits beyond the remote issue branch;
- dirty diff stat and a private patch;
- branch and worktree paths.
Separate commits into candidate categories: SALVAGE, ALREADY_LANDED, MERGE_ONLY, or DISCARD. A human or designated coordinator approves the final classification. Merge commits and commits carrying another merged PR are never blindly cherry-picked.
4. Preserve dirty and unpushed work
Create a neutral salvage branch outside the stale issue-lock namespace. Stage only explicit source paths. Exclude dependencies, build products, release bundles, logs, reports, audit payloads, and customer-derived data unless separately approved.
Commit the residue, create a bundle or equivalent offline backup, then push the salvage branch when authorized. Verify the remote ref resolves to the local salvage SHA. Keep the private patch until the entire recovery is complete.
5. Stop for decisions
Do not make destructive progress until approvals cover:
- each unpushed commit;
- each dirty source file or residue commit;
- each untracked or ignored artifact that might be valuable or sensitive;
- any discrepancy between the cleanup runbook and live PR/content evidence.
For asynchronous operations, persist a machine-readable checkpoint and accept only an explicit, attributable decision. Silence and timeout are not approval.
6. Re-home approved work
Create a new issue for the approved residue. Fetch the current default branch, create a fresh branch/worktree from it, and cherry-pick only approved non-merge commits in dependency order. Bring the dirty-residue commit separately so it remains reviewable. Run the repository's tests and open a new PR that closes the new issue.
Read the new PR back and verify base, head SHA, files, and state. Nothing is added to the merged PR or stale lock branch.
7. Retire stale branches and worktrees
Before deletion, record each tip SHA and create a verified bundle. Ensure tracked/untracked status is clean. Ignored files may prevent normal worktree removal; classify or delete approved build output normally rather than using force.
Detach the worktree at the current default branch or remove it normally, delete the local stale branch, then delete the remote branch. After each branch—not only at the end—verify:
- local branch lookup is empty;
- remote branch lookup is empty;
- worktree inventory has the intended attachment;
- repository status is clean.
8. Report and close
Post raw command outputs in bounded phase comments, excluding secrets and sensitive payloads. Read each comment back and compare the returned body/URL with the intended target. The final report names deleted refs, surviving salvage/new branches, artifact archive locations, dirty statuses, approvals, backup locations, and exact failures.
Close the recovery issue only when every acceptance criterion has evidence.
Recovery and Rollback
- Recreate a deleted branch by pushing its recorded tip SHA to the original ref.
- Recover repository objects from the verified bundle.
- Recover dirty work from the salvage commit and private patch.
- Recover retained artifacts from the private external archive and verify stored hashes.
- If any preservation or read-back check fails, stop before the next destructive action.
Pitfalls
- Treating remembered PR state as live state.
- Pushing residue to a branch whose PR already merged.
- Using
git add -A,git clean -fdx, or forced worktree removal before classification. - Posting audit reports, ignored-file contents, patches, or credentials as “raw evidence.”
- Blindly cherry-picking merge commits or commits already delivered by another PR.
- Treating non-ancestry after a squash merge as proof that content was lost.
- Deleting all refs first and verifying only after the batch.
- Calling a run “one-off” while omitting durable approval checkpoints.
Verification Checklist
- Live PR state, merged status, head SHA, and default-branch head recorded.
- Delivered content verified independently of old-head ancestry.
- Status, commit residue, ignored inventory, and private patch captured.
- Salvage branch/bundle verified before any deletion.
- Every commit and artifact has an explicit disposition.
- Approved work uses a new issue, fresh branch, and new PR.
- Each local and remote deletion was read back immediately.
- Worktrees are detached/removed intentionally and cleanly.
- Reports omit secrets and sensitive file contents.
- Recovery SHAs, bundles, and artifact hashes are retained.
See references/merged-branch-residue.md for a condensed evidence and decision schema from a multi-worktree recovery case.
Supporting files: this skill's supporting files are held in the docsite at
docs/15-skills/_support/github/git-worktree-lifecycle-recovery/— fetch them fresh fromjknash/docsitemain alongside this page. Source:jknash/hermes-shared-skills· branchhermes-jkdev001@1d0d545c3970·skills/github/git-worktree-lifecycle-recovery/· view source · Imported 2026-10-03. Supporting files (references, scripts) remain in the source repository.
version 0.1.0 · author Hermes Agent · license MIT.
Published by Muse · 2026-10-03.