You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Why this merge is different from every one that follows
This is the first v2/main → main milestone merge, and it is the only one that will look like this. Read the sequence below as a one-off, not as the template.
Three things make it exceptional, and all three are consequences of the 2.0.0 go-live rather than of anything in v2.1.0:
The branches only just acquired a shared history.main and v2/main had unrelated histories until the go-live merge (chore: replace main's tree with v2 #1830) established merge base 4d30d1cd by replacing main's tree with v2's. That makes this an ordinary merge — but it is the first time that has been true, which is why the "never use --allow-unrelated-histories" warning below needs saying at all.
The payload is repo infrastructure, not product work. The tree swap dropped files that lived only in the old tree, so most of this milestone restores them (SECURITY.md, the Claude workflow, dependabot.yml, the CoC) or adapts docs to the new contribution model. Exactly one PR (fix(core): mirror SEP-2243 x-mcp-header args to Mcp-Param-* on tools/call #1847) changes runtime behavior. A normal milestone will invert that ratio. See the milestone overview comment for the full grouped breakdown.
After this lands, the steady-state merge is just steps 1–3 with no conflict and no convergence PRs. Once v2/main's tip is an ancestor of main, and main continues to make no content changes of its own, every subsequent milestone merge is conflict-free — see "Then it's self-sustaining" at the bottom. The one-time cost is this merge.
Do not generalize the pre-flight below either. The branch-protection check and the PR-vs-direct-merge decision are first-time questions; once answered they stay answered.
Sequence
git fetch origin
# 1. Merge the milestone's work into the release branch.
git checkout -B main origin/main
git merge --no-ff origin/v2/main -m "chore: merge v2/main for <version> milestone release"# → PR #1880 is the convergence step. If it has merged, expect ZERO# conflicts. If it hasn't, expect exactly ONE conflict hunk in README.md# (the stale-vs-corrected `Mcp-Param-*` callout) — take v2/main's side.# Measured in a scratch worktree, not estimated.# 2. Gate before it becomes the release.
npm install && npm run ci
# 3. Publish the branch, then cut the release from it.
git push origin main
npm version <major|minor|patch># on main
git push --follow-tags
# → draft & publish the GitHub Release for that tag; the `publish` job runs# pack:verify and publishes the `latest` dist-tag# 4. Back-sync only what release adds (version bump), so package.json doesn't# diverge and conflict on every future merge.
Ordinary merge — the branches share merge base 4d30d1cd (established by the go-live merge #1830). Never use --allow-unrelated-histories; see the correction block in #1821's description.
Do not "fix" this with a back-merge of main into v2/main. That was built and rejected — see #1868 (closed). It would make this first merge conflict-free, but only by pulling 224 commits, 212 of them pre-swap v1-tree commits, permanently into the develop branch's ancestry. git log, bisect, and every GitHub compare on v2/main would carry the v1 lineage from then on. It is not worth avoiding a three-line conflict once, and after this merge the problem does not recur at all (see "Then it's self-sustaining" below).
Pre-flight
Branch protection on main permits a maintainer merge commit — the only thing that can block this. Everything else is verified.
Decide whether the merge goes through a PR (v2/main → main, reviewable, consistent with the no-direct-pushes posture) or a direct maintainer merge. Note closing keywords do work in such a PR, since main is the default branch.
Release notes call out the Node engine bump (>=22.7.5 → >=22.19.0).
Then it's self-sustaining
Once v2/main's tip is an ancestor of main, and main makes no content changes of its own, every subsequent milestone merge is conflict-free with no back-merge needed. This one-time conflict is the whole cost.
Why this merge is different from every one that follows
This is the first
v2/main→mainmilestone merge, and it is the only one that will look like this. Read the sequence below as a one-off, not as the template.Three things make it exceptional, and all three are consequences of the 2.0.0 go-live rather than of anything in v2.1.0:
mainandv2/mainhad unrelated histories until the go-live merge (chore: replace main's tree with v2 #1830) established merge base4d30d1cdby replacingmain's tree with v2's. That makes this an ordinary merge — but it is the first time that has been true, which is why the "never use--allow-unrelated-histories" warning below needs saying at all.mainaccumulated rc-series changes during the 2.0.0 run thatv2/mainnever saw, two PRs existed purely to make this merge tractable: docs: converge README Test servers section with main's restructure #1880 (READMETest serversconvergence — the PR that removes the one conflict hunk) and chore(deps): bring main's rc-series bumps to v2/main (@hono/node-server 2.x, vite 8.1.5) #1881 (main's dependency bumps brought ontov2/main). Nothing analogous will be needed again.SECURITY.md, the Claude workflow,dependabot.yml, the CoC) or adapts docs to the new contribution model. Exactly one PR (fix(core): mirror SEP-2243 x-mcp-header args to Mcp-Param-* on tools/call #1847) changes runtime behavior. A normal milestone will invert that ratio. See the milestone overview comment for the full grouped breakdown.After this lands, the steady-state merge is just steps 1–3 with no conflict and no convergence PRs. Once
v2/main's tip is an ancestor ofmain, andmaincontinues to make no content changes of its own, every subsequent milestone merge is conflict-free — see "Then it's self-sustaining" at the bottom. The one-time cost is this merge.Sequence
Ordinary merge — the branches share merge base
4d30d1cd(established by the go-live merge #1830). Never use--allow-unrelated-histories; see the correction block in #1821's description.Pre-flight
mainpermits a maintainer merge commit — the only thing that can block this. Everything else is verified.v2/main→main, reviewable, consistent with the no-direct-pushes posture) or a direct maintainer merge. Note closing keywords do work in such a PR, sincemainis the default branch.After it lands
@claudeshould work again — comment@claude reviewon any open PR (claude[bot]replied in ~19s on docs: refresh V2 board Status option IDs in AGENTS.md (#1823) #1825). Workflows forissue_commentevents run from the default branch, so ci: restore the Claude Code workflow and .mcp.json, lost in the v2 tree swap #1869 is inert until now.v2/main, and security updates should still appear (they're a repo setting, and ran whiledependabot.ymlwas missing entirely — build(deps): bump the npm_and_yarn group across 5 directories with 12 updates #1833, build(deps): bump the npm_and_yarn group across 5 directories with 2 updates #1840 — buttarget-branchis documented as affecting security-update behavior, so confirm).Then it's self-sustaining
Once
v2/main's tip is an ancestor ofmain, andmainmakes no content changes of its own, every subsequent milestone merge is conflict-free with no back-merge needed. This one-time conflict is the whole cost.