Skip to content

git branch -d can approve a deletion on the word of a stale remote-tracking ref, so it contributes no safety at all — and the documented cleanup order is what lets it pass #98

Description

@thelvick

Source: engagement-retro (eng-4b71)

Title: git branch -d can approve a deletion on the word of a stale remote-tracking ref, so it contributes no safety at all — and the documented cleanup order is what lets it pass

Measured. Cleaning up two squash-merged branches, the session predicted git branch -d would
refuse (after a squash the branch is not an ancestor of its base) and planned to fall back to
-D once content was verified. It did not refuse. It printed:

deleting branch '22-revendor-cadence' that has been merged to
refs/remotes/origin/22-revendor-cadence, but not yet merged to HEAD

and deleted — consulting a stale remote-tracking ref for a branch the forge had already
auto-deleted at merge. Not the remote, and not local main.

The ordering consequence is the sharp part. The documented cleanup order is sync → verify →
delete → prune. Pruning first would have removed the stale ref, made -d refuse, and forced
the explicit -D — so the documented order is precisely what lets the weak flag pass. What kept
this safe was that the content verification was done independently of the flag that was supposed to
enforce it: git diff --stat <branch> <merge-commit> returning empty. That comparison must be made
against the merge commit, not today's main, which is ahead and yields a non-empty diff that
reads like unmerged work — a fifth-hand instance of the same session's own pattern.

Proposed mechanism.

  • (a) State that the upstream -d consults may no longer exist, so -d succeeding is not
    evidence of anything. The existing guidance frames the risk as local main behind; that is the
    weaker half.
  • (b) The check that licenses a branch deletion is the content comparison against the commit
    that merged it
    , run independently of the deletion flag.
  • (c) Note that pruning before deleting changes -d's answer, so the cleanup order is
    load-bearing and should be stated as such rather than as tidiness.

Companion, worth stating beside it: a local cache of a remote's state answers a different
question than the remote does, and the two are indistinguishable on screen.
Two instances in this
window alone — git branch -r (stale remote-tracking refs) read as a listing of remote branches, and
a branch diff taken against today's main rather than the merge commit. git ls-remote --heads origin is the question that was meant.

Gate-2 recommendation: the companion clause may belong as a comment on #76 (four measured
shell traps the harness-trap list does not carry
) rather than in this issue's body. Recorded here,
not acted on.

Source: orchestrator/findings/2026-09-01-025-slice-22-revendor-cadence.md;
orchestrator/lessons.md 2026-09-01 (git branch -d consulted a stale tracking ref and deleted
anyway
).


Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    origin:agent-teamFiled by /file-feedback with a valid provenance markerprocessMethodology feedback class: processsource:engagement-retroField feedback bundled from an engagement retrostandard-feedbackRoutes to ai-assisted-dev-standardtriageAwaiting owner triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions