Blocked Branch Preserve-Tag Cleanup
Use when cleaning many repos and some stale local branches cannot be merged safely into the default branch.
Trigger conditions
git mergefails withrefusing to merge unrelated histories- branch has no matching remote branch
- branch has shared history but the diff is extremely large / artifact-heavy / conflict-heavy, making opportunistic cleanup riskier than preservation
- repo hygiene is the goal, not historical branch recovery work
Safe disposition workflow
- Inspect the blocked branch:
- confirm default branch
- check whether a matching remote branch exists
- check whether histories are unrelated via failed merge or missing merge-base
- estimate branch size with
git diff --shortstat <default>...<branch>when histories are related
- Classify the branch:
mergeableif small and cleanpreserve-onlyif unrelated history, no remote, or very large/conflict-heavyactive/worktree-backedif the branch is attached to a live worktree; do not delete yet
- For
preserve-onlybranches, create a local recovery tag before deletion:git tag preserve/<branch>-$(date +%Y%m%d) <branch>
- Delete the local branch after tagging:
git branch -D <branch>
- Do not push the preservation tag by default. Keep it local unless the user explicitly wants remote archival.
Why this works
This gives you a reversible cleanup path: branch clutter is removed, but the exact tip commit remains recoverable through the tag.
Practical heuristics
- Unrelated-history branches with no remote are usually stale/orphan branches; do not force
--allow-unrelated-historiesunless the user explicitly wants content salvage. - If a branch diff is huge (for example thousands of files, generated assets, or vendored environments), prefer preserve-only cleanup over ad hoc conflict resolution.
- If a conflict is in legacy control-plane files (
.agent-os, old instructions, generated environments), that is usually a sign the branch is not worth opportunistic merging during hygiene work. - Worktree-backed branches must be handled after their worktrees are removed or confirmed inactive.
Verification
After cleanup, verify:
git branch -vvno longer lists the stale branchgit tag --list 'preserve/*'contains the recovery tag- default branch remains checked out and clean/up to date