From 9cb8a4480bb70b8dd10435652e9291bc2382f1a2 Mon Sep 17 00:00:00 2001 From: OffgridwithJD Date: Fri, 18 Sep 2026 16:13:29 +0000 Subject: [PATCH] docs: say why rebasing works where merging does not (#1116) CONTEXT.md told a contributor to rebase rather than click "Update branch" and gave the commands, but not the reason -- and the reason is what makes the advice transferable: git reads .gitattributes from the tree it is merging INTO, so a branch opened before the driver landed cannot use it. Measured on #1107, whose head predates #1108: merge main INTO the branch conflicts: CHANGELOG.md rebase the branch ONTO main conflicts: grep -c 'CHANGELOG.md.*merge=union' gives 0 on that head and 1 on main. Merging brings main's commits into a tree whose attributes have no driver; rebasing replays the branch onto main, where the driver is already in force. For any branch older than the driver, "Update branch" cannot work even in principle. THE ARM WAS RED ON THE UNMUTATED TREE FIRST. Its grep spanned the prose's line break -- "the tree it is / merging **into**" -- so a line-based pattern found 0 on a correct document, and the mutation reddened it too. That looks like a working removal proof and is two failures agreeing. Re-anchored on a phrase that fits one line: control green, mutation red. docs_style 47 checks rc=0. It holds no ledger rows, so no rows move. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012RSw4qMHS7ByE7PY8Ns4cs --- CHANGELOG.md | 24 ++++++++++++++++++++++++ CONTEXT.md | 16 ++++++++++++++++ test/docs_style.sh | 7 +++++++ 3 files changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7add6858..4ffba985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,30 @@ true until the next version shipped. ### Fixed +- The union-merge page did not say why rebasing works where merging does not + (#1116 follow-up). + + `CONTEXT.md` told a contributor to rebase rather than click *Update branch*, and + gave the commands, but not the reason. The reason is the part that makes the advice + transferable: **git reads `.gitattributes` from the tree it is merging INTO**, so a + branch opened before the driver landed cannot use it. + + Measured on #1107, whose head predates #1108: + + merge main INTO the branch conflicts: CHANGELOG.md + rebase the branch ONTO main conflicts: + + `grep -c 'CHANGELOG.md.*merge=union'` gives 0 on that head and 1 on main. Merging + brings main's commits into a tree whose attributes have no driver; rebasing replays + the branch onto main, where the driver is already in force. So for any branch older + than the driver, *Update branch* cannot work even in principle. + + THE ARM FOR THIS WAS RED ON THE UNMUTATED TREE FIRST. Its grep spanned the prose's + line break -- "the tree it is / merging **into**" -- so a line-based pattern found + 0 on a correct document. The mutation then reddened it as well, which looks like a + working removal proof and is two failures agreeing. Re-anchored on a phrase that + fits one line; the control is green and the mutation still reddens. + - A `CONFLICTING` badge on a changelog entry is GitHub, not git (#1116). #996 gave `CHANGELOG.md` a union merge driver, and it does what it was argued to diff --git a/CONTEXT.md b/CONTEXT.md index 205fe1a9..d9390ec7 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -500,6 +500,22 @@ Measured, on four branches rebased onto the driver after it landed: zero CHANGEL conflicts, one `## [Unreleased]`, every entry present, `docs_style.sh` green. The same merges showed `CONFLICTING` on GitHub throughout. +### And why rebasing works where merging does not + +The advice above is not a preference. Git reads `.gitattributes` from the tree it is +merging **into**, so a branch that predates the driver cannot use it: + + merge main INTO the branch conflicts: CHANGELOG.md + rebase the branch ONTO main conflicts: + +Measured on #1107, whose head predates #1108 (`grep -c 'CHANGELOG.md.*merge=union'` +gives 0 on that head and 1 on main). Merging brings main's commits into a tree whose +attributes have no driver; rebasing replays the branch onto main, where the driver is +already in force. + +So for any branch opened before the driver landed, *Update branch* cannot work even +in principle — and that is most branches that have been open more than a day. + ### What the driver does not excuse A **release cut** edits `## [Unreleased]` into `## [1.0-alphaN] - date`, which is the diff --git a/test/docs_style.sh b/test/docs_style.sh index 0908172a..9df6abdf 100755 --- a/test/docs_style.sh +++ b/test/docs_style.sh @@ -590,6 +590,13 @@ check "and names the command rather than only the problem" \ "$(grep -c 'git rebase origin/main' "$SRCDIR/CONTEXT.md")" "1" check "and warns against the button that reintroduces the conflict" \ "$(grep -ci 'do not click' "$SRCDIR/CONTEXT.md")" "1" +# ANCHORED ON ONE LINE. The first spelling of this arm spanned the prose's line +# break -- "the tree it is / merging into" -- so a line-based grep found 0 on the +# unmutated tree and the arm was red for the sentence it was asserting. The mutation +# then reddened it too, which looked like a working proof and was two failures +# agreeing. Same class as a drift-guard that does not join line continuations. +check "and says WHY rebasing works where merging does not" \ + "$(grep -c 'merging \*\*into\*\*' "$SRCDIR/CONTEXT.md")" "1" echo "checks run: $checks"