Landing a change through the forge moves its base branch without running the
Git hooks. A push to that branch would move the head: of every open request
that follows it; a landing does not, so those requests keep reviewing the
pre-merge tip.
Why
- A change request follows the branch it was opened from.
post-receivecallsmetadata.SyncBranchHeadafter a push so the request names the tip a reviewer will see. landing.Landmoves the base ref withupdate-ref, so no hook runs. The open requests that follow the moved branch are left on their old head.- The symptoms are misleading: the request page says “branch moved”, its Runs
tab lists runs for the old commit (the new run exists, but under the base
branch), and
head:is no longer the reviewed code. - Approvals are bound to a commit, so a follower with approvals would be holding ones that name code the branch no longer has.
- This is exactly the stacked workflow: land the upper request into the lower’s branch, and the lower request must move with the branch.
CI itself is not missing: the ref reconciler queues the new tip within 30s. Only the follower sync is skipped.
Scope
-
MarkMergedmoves the open requests following the request’s base branch onto the landed commit, in the same metadata commit that marks the request merged (so the landing and its followers cannot disagree). - Share the follower-update body with
SyncBranchHeadinstead of keeping two copies of the rule. - Cover it with a landing test: a lower request following a branch, an upper request landing into that branch, and the lower request’s head moving.
Acceptance criteria
- Landing a request moves
head:of every open request whosehead_refis the base branch that just moved. - The mark, the linked-issue closures and the follower moves are one commit; a failure writes none of them.
- A follower’s approvals are not carried: they still name the commit they were given for.
go test -tags sqlite_fts5 ./metadata ./forge/landingpasses.