prune deletes the remote twin on a proof computed only from local refs #566
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#563 Epic: the destructive surface has outgrown ADR 0029's classification table
sixfold-space/madtea
Reference
sixfold-space/madtea#566
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #563.
The second gap in the
prunemachine-proof carve-out. Separate from #564, same file.The defect
After a local branch deletes cleanly,
prunedeletes its remote twin and then drops the tracking ref:deleteLocalBranches(internal/service/prune/run.go:748-774) anddeleteSquashMerged(run.go:620-632) callbranchAPI.Delete, thendeleteTrackingRef(run.go:43-46). No step readsorigin/<name>.The local delete is not a proof about the remote ref.
git branch -daccepts a branch merged into HEAD or merged into its upstream, and merged-into-HEAD alone is enough. So a local branch can pass-dwhile its remote twin holds a commit that is in no other ref. Under--delete-branches --remotethat commit then loses its forge ref and its local tracking ref in the same run. Nothing recoverable remains.The orphan path in the same file is proven correctly:
findRemoteOrphanschecksgit branch -r --merged origin/<default>(run.go:407-413). Only the twin path skips the check.Fix
Check containment of the remote ref before the API delete, for example
git merge-base --is-ancestor origin/<name> <defaultBranch>, and route a non-contained twin to the skipped list the waydeleteSquashMergedalready routes a non-contained local branch.Acceptance criteria
prunenever deletes a remote branch whose tip is not contained in the default branch.Note on severity
Whether this is as urgent as #564 is a judgment call. #564 fires on an ordinary local workflow. This one needs the remote twin to be ahead, which is a narrower state, but the loss is the same and there is no reflog on the forge side.
Verification status, same caveat as #564.
The code path is confirmed by reading:
deleteLocalBranchesanddeleteSquashMergedcallbranchAPI.Deleteand then drop the tracking ref, and neither readsorigin/<name>first.The git behaviour the finding turns on, that
git branch -daccepts merged-into-HEAD alone and so passes while the remote twin is ahead, is not independently confirmed. Re-run it before writing the regression test, and correct this issue if it does not hold.