Skip to content

docs(runbooks): document the post-promotion branch reconcile#473

Merged
ss-o merged 3 commits into
mainfrom
docs/release-runbook-reconcile
Jul 22, 2026
Merged

docs(runbooks): document the post-promotion branch reconcile#473
ss-o merged 3 commits into
mainfrom
docs/release-runbook-reconcile

Conversation

@ss-o

@ss-o ss-o commented Jul 22, 2026

Copy link
Copy Markdown
Member

Adds a Post-promotion branch reconcile (class 1) section to runbooks/release.md.

Why

Class-1 repositories that promote a development branch to a deployed branch diverge after every promotion, by construction:

  • The deployed branch requires pull requests and linear history
  • Squash and rebase both mint new commits the development branch does not have
  • A merge commit — the one strategy that keeps the branches related — is exactly what linear history forbids

There is no branch-protection configuration that avoids this. Reconciling is a release step, not a sign something went wrong. It was being rediscovered each time instead.

Two traps this records

Both were hit while reconciling z-shell/wiki today.

Rulesets and classic branch protection are independent systems; the effective rule is their union. repos/z-shell/wiki/branches/main/protection reports required_linear_history: false, while ruleset 5612688 enforces it on the same branch. Reading only the classic API makes a merge commit look permissible when it is not.

An administrator's push is not refused by a ruleset. It prints Bypassed rule violations and succeeds. Two merge commits went onto wiki's next that way. The first went unnoticed because the push was run as git push -q | tail, which truncated the warning — so the runbook says explicitly to read push output and states which single bypass is expected and unavoidable here.

Honesty about the procedure

The documented reconcile cannot avoid a bypass: a direct push carries no prior status check, so the branch reports Required status check "Trunk Check" is expected. There is no pull-request route — a PR can only add commits, and realignment rewrites history. The section says so rather than presenting the procedure as clean.

Safety gate

The reset only runs when the two trees are identical, which is what makes it content-neutral. If they differ, the development branch has unmerged work and the runbook says to stop and promote that first.

Verification

Every command in the section was run against the live z-shell/wiki repo rather than written from memory — the safety gate, the reconciled check, and the gh api ... /rules/branches/ query all produce the documented output. The procedure itself was executed: wiki's next and main are now the same commit, and the two rule-bypassing merge commits are no longer reachable from next.

Class-1 repositories that promote a development branch to a deployed
branch diverge after every promotion. When the deployed branch requires
both pull requests and linear history, squash and rebase both mint new
commits the development branch lacks, and a merge commit — the one
strategy that would keep the branches related — is what linear history
forbids. There is no configuration that avoids it, so reconciling is a
release step rather than an incident.

Records the reset-and-force-push procedure, with a tree-equality safety
gate so it is only run when it is content-neutral.

Also records two traps found while doing this on wiki:

Rulesets and classic branch protection are independent, and the
effective rule is their union. Classic protection reported
required_linear_history false for a branch a ruleset separately enforced
it on, which made a merge commit look permissible when it was not.

An administrator's push is not refused by a ruleset; it reports
'Bypassed rule violations' and succeeds. Quieting push output hides that
warning, so the runbook says to read it and states which single bypass
is expected and unavoidable for this operation.
@ss-o
ss-o requested a review from a team as a code owner July 22, 2026 01:49
Copilot AI review requested due to automatic review settings July 22, 2026 01:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Documents a repeatable, content-neutral procedure for reconciling development and deployed branches in class-1 (continuously deployed) repositories after promotion, capturing common branch-protection/ruleset pitfalls encountered during real promotions.

Changes:

  • Add a new “Post-promotion branch reconcile (class 1)” section explaining why divergence is expected with linear-history + PR requirements.
  • Document a reconcile procedure and verification steps, including how to inspect branch rules and what bypass warnings to expect.

Comment thread runbooks/release.md
Comment thread runbooks/release.md
Comment thread runbooks/release.md Outdated
Review feedback on the post-promotion reconcile section.

The safety gate only echoed STOP while reset --hard and a force push
followed it, so anyone pasting the block would have run straight through
a failed check into a destructive operation. The procedure is now a
script with set -eu and an explicit exit 1 in the gate, and says to run
it as a script rather than paste it line by line, since a gate cannot
abort a run when each line is entered separately.

Branch names are now DEPLOY and DEV variables instead of hard-coded
main and next, so the section matches its stated scope of class-1
repositories generally.

'silently reports Bypassed rule violations' was self-contradictory. The
push does print the warning; it is simply not stopped.

Both gate paths were verified against a live clone: differing trees exit
1 before step 2, matching trees proceed.
Copilot AI review requested due to automatic review settings July 22, 2026 01:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread runbooks/release.md Outdated
Review feedback, plus a second fault found while verifying it.

git checkout "$DEV" lands in detached HEAD when a tag shares the branch
name, reproduced in a scratch repository. The reset in the next step
would then move a detached HEAD rather than the branch. Replaced with
git checkout -B against an explicit remote-tracking start point, which
also works in a fresh clone where no local branch exists yet.

Plain -B sets the branch to track the deployed branch, which would
misdirect later pulls, so --no-track is used and the upstream is set
explicitly to the development branch.

The push had the same ambiguity and failed outright with 'src refspec
matches more than one'. It now uses a fully-qualified refspec. This was
not in the review; it surfaced only when the corrected procedure was run
end to end, and it bit the test setup itself before it bit the script.

Verified in a repository carrying both a next branch and a next tag:
differing trees abort before any destructive step, matching trees run
through to a successful push leaving no detached HEAD and upstream set
to origin/next.
Copilot AI review requested due to automatic review settings July 22, 2026 02:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@ss-o
ss-o merged commit 5fcc4fa into main Jul 22, 2026
5 checks passed
@ss-o
ss-o deleted the docs/release-runbook-reconcile branch July 22, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants