Remove redundant step-by-step subsections from workflow guide (the table already covers it), tighten ADR-011 alternatives, and remove version pins that go stale. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.9 KiB
2.9 KiB
ADR-011: Linearize Fallback for Reverse Sync
Status: Accepted Date: 2026-03
Context
Josh-proxy rejects reverse sync pushes when the subrepo history contains merge commits whose parents it cannot map through the filter. This happens when:
- A long-lived branch (e.g.,
stage) is merged intomainvia a merge commit - That branch contains auto-sync merge commits or criss-cross merges with
main - Josh encounters the merge commit, tries to map both parents through the filter, and fails with a 500 error
This is a legitimate subrepo workflow — teams merge staging branches into main regularly. The sync tool should handle it without requiring teams to change their Git workflow.
Alternatives considered
- Squash all commits into one: Simple but destroys all commit granularity.
- Rewrite subrepo history: Breaks josh's SHA mapping, forces all developers to re-clone.
- Linearize: cherry-pick regular commits, squash only merges: Preserves individual commit granularity; only merge commits lose their multi-parent structure.
Decision
When the direct push through josh-proxy fails, fall back to option 4: linearize the history by cherry-picking onto the josh-filtered base.
How it works
- Direct
git pushthrough josh-proxy is attempted first (existing behavior) - If it fails, create a temporary branch from
mono-filtered/<branch> - Walk human commits (oldest-first, bot commits excluded) from the ancestry path:
- Regular commits (≤1 parent):
git cherry-pick <sha>— preserves author, date, and message - Merge commits (>1 parent):
git cherry-pick -m 1 <sha>— applies the merge's diff relative to its first parent as a single commit
- Regular commits (≤1 parent):
- If cherry-pick conflicts (rare — usually due to ordering issues), fall back to
git diff | git applywith the original author metadata - Push the linearized branch through josh-proxy
- PR body includes a note explaining that merge commits were squashed
What is preserved
- Individual non-merge commits (author, date, message, diff)
- The net effect of each merge commit (as a squashed single commit)
- The original commit list in the PR body for reference
What is lost
- The multi-parent structure of merge commits (they become single-parent)
- The distinction between "changes introduced by the merge" vs "changes from each parent" — the merge is represented as its diff from first parent
Consequences
Positive:
- Reverse sync no longer gets stuck on merge commits — handles the common case automatically
- Non-merge commits retain full granularity (no unnecessary squashing)
- Subrepo history is untouched — no rewriting, no broken sync relationship
- The PR body documents when linearization was used, so reviewers know
Negative:
- Merge commit semantics are lost on the monorepo side (they appear as regular commits)
- Adds complexity to the reverse sync path (two code paths: direct push and linearize fallback)