From 12bda8e84444437e7d5299b75ef7e02e573f09a9 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 9 Aug 2026 17:25:31 -0400 Subject: [PATCH] docs(#3268): next does require up-to-date; correct CONTRIBUTING and branching (#3269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONTRIBUTING.md said branch protection on `next` has the "up-to-date before merging" flag DISABLED and that "the rebase treadmill is gone for the 95% case". docs/branching.md repeated it three times. The live protection says the opposite: $ gh api repos/open-gsd/gsd-core/branches/next/protection \ --jq '.required_status_checks.strict' true This is not a cosmetic nit — it misstates the cost model of every PR in the repo. A contributor plans for no rebase, then finds their PR BEHIND at merge time. And because the push gate binds its pass marker to an exact sha, that rebase invalidates the marker and forces a full remote re-verification plus another CI cycle. Believing the treadmill is gone is how you pay for it unplanned, late, on a PR that looked finished — observed on PR #3261. Both files now state the real requirement, show the one-line command to verify it, and name the sha-invalidation consequence with the practical advice that follows from it: rebase LAST, immediately before pushing for review, rather than paying for a verification you are about to discard. What was true in the original text is kept: `next` moves far less often than `main` did, so the rebase frequency really is much lower. The claim that was wrong was that the requirement does not exist. Closes #3268 Co-authored-by: sim --- CONTRIBUTING.md | 21 +++++++++++++++------ docs/branching.md | 39 ++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 42f667d08..f1b100b54 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -147,12 +147,21 @@ If you target the wrong branch by accident, the `PR Target Validator` workflow will post a comment with the one-line fix (click "Edit" by the PR title and change the base branch — no need to recreate the PR). -**Why this matters:** Under the old single-branch model, every PR required -rebasing onto `main` because branch protection required "up-to-date before -merging" and `main` moved on every merge. With `next` as the integration -branch and that flag disabled on `next`, concurrent PRs can merge in any -order as long as they don't conflict on the same lines. The rebase -treadmill is gone for the 95% case. +**Why this matters:** Under the old single-branch model, every PR rebased onto +`main`, which moved on every merge. `next` moves far less often — only when +another PR to `next` lands — so in practice you rebase much less. + +**But `next` does still require "up-to-date before merging".** Branch +protection has `required_status_checks.strict = true`; check it yourself with +`gh api repos/open-gsd/gsd-core/branches/next/protection --jq '.required_status_checks.strict'`. +If another PR lands while yours is open, yours goes `BEHIND` and must be +rebased before it can merge. + +Budget for that, because the rebase is not free here: **it changes your HEAD +sha, which invalidates the sha-bound pass marker the push gate reads**, so a +rebase means re-running the full remote verification and another CI cycle +before the gate clears again. Rebase *last* — immediately before you push for +review — rather than paying for a verification you are about to discard. --- diff --git a/docs/branching.md b/docs/branching.md index 22398239f..9a4315b73 100644 --- a/docs/branching.md +++ b/docs/branching.md @@ -111,13 +111,17 @@ gh pr create --base next --repo open-gsd/gsd-core **Why this rarely needs a rebase:** - `next` moves slower than `main` did in the old single-branch model — only - changes when other PRs to `next` merge. -- Branch protection on `next` does **not** require "up-to-date before merge" - — only requires CI to be green. So another PR landing on `next` while yours - is open doesn't force you to rebase. + changes when other PRs to `next` merge. Fewer landings means fewer rebases. - Squash-merge means each PR becomes one commit on `next` — easy to revert, easy to read, no merge-noise. +**It does still need a rebase when `next` moves under you.** Branch protection +on `next` requires "up-to-date before merge" (`required_status_checks.strict = +true`), so a PR that goes `BEHIND` must be rebased before it can merge. And +because the push gate binds its pass marker to an exact sha, that rebase +invalidates the marker and costs a full re-verification plus another CI cycle +— so rebase *last*, right before you push for review. + ### Flow 2 — Hotfix (urgent patch release) When you need to ship a fix without waiting for the next minor. @@ -191,18 +195,27 @@ The old single-branch model: - 10 PRs in flight = 9 of them need to rebase every time one lands. The last one to merge has rebased N times. -The new model removes the pressure in three ways: +The new model reduces the pressure in two ways: 1. **`main` rarely moves.** Only release/hotfix merges land. Most days `main` doesn't change at all. -2. **`next` does NOT require "up-to-date before merge".** Branch protection - on `next` only requires CI green. Two PRs to `next` can merge in either - order without rebasing each other — git will handle the merge as long as - they don't touch the same lines. -3. **Squash-merge into `next`.** One commit per PR. No "merge main into my - branch" noise. If you ever do need to bring `next` into your branch - (because of a real conflict), it's one rebase per conflict, not per PR - that lands somewhere else. +2. **Squash-merge into `next`.** One commit per PR. No "merge main into my + branch" noise, and a clean revert. + +**It does not remove the up-to-date requirement.** `next` carries +`required_status_checks.strict = true`, exactly as `main` did — so a PR that +another merge pushes `BEHIND` still has to rebase. What changed is the +*frequency*: `next` moves only when a PR to `next` lands, not on every release, +so far fewer PRs go stale. + +Two consequences worth planning around: + +- The rebase changes your HEAD sha, which **invalidates the sha-bound pass + marker** the push gate reads. Re-verification and another CI cycle follow. + Rebase last, immediately before pushing for review. +- With several PRs in flight, the last to merge may still rebase more than + once. That is the treadmill, reduced but not gone — size the queue with that + in mind rather than assuming order-independence. You'll still occasionally rebase — when your branch genuinely conflicts with something that landed on `next`. But that's a real conflict you'd have to