fix: sync-upstream should merge, not rebase, so future sync PRs stay mergeable - #4
Conversation
PR #3 (the first real sync PR) came out with a genuine merge conflict against main: "Create sync branch and rebase" took main's fork-only commits and rebased them onto the new upstream tip, producing a branch with entirely rewritten commit SHAs. Once main itself gained commits outside the sync flow (the #1/#2 workflow fixes), that rewritten history no longer shared recognizable ancestry with main, so git saw independent adds of the same fork-only files (e.g. .claude-plugin/.upstream-base) with no common version to 3-way-merge from — an add/add conflict GitHub can't auto-resolve on any merge strategy. Resolved PR #3 by hand (merge main into the branch, keep the branch's newer .upstream-base value, everything else merged cleanly) and merged it — main is now caught up to upstream 3fe2823. To keep this from recurring, switch the branch-construction step from `git rebase upstream/main` to `git merge upstream/main`: - The sync branch is now a genuine descendant of main's actual tip (upstream/main merged in as a second parent), so it never loses ancestry with main the way a rebase does. - Conflict resolution keeps the same "upstream wins, README rebuilt from template" policy, with --ours/--theirs flipped to match merge semantics (opposite of rebase). - `.claude-plugin/.upstream-base` no longer conflicts at all in this flow, since upstream doesn't have that file — it's written as a deliberate post-merge step rather than needing 3-way resolution. - Final `gh pr merge` switches from --rebase to --merge, since GitHub's rebase-merge rejects branches containing merge commits (which this branch now always has).
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note
|
Summary
Follow-up to #1 and #2. Once those landed, the workflow produced a real sync PR (#3) — but it opened with a merge conflict against
main. I resolved #3 by hand and merged it (main is now caught up to upstream3fe2823), and this PR fixes the workflow so future sync PRs don't hit the same wall.Root cause
Create sync branch and rebasetook whatever commits were unique tomain(relative toupstream/main) and rebased them onto the new upstream tip, producing a branch with entirely rewritten commit SHAs. That's fine in isolation, but the momentmaingains a commit that didn't come from a previous sync merge (here: the #1 and #2 workflow fixes), the rebased branch andmainno longer share recognizable ancestry — git sees independent "adds" of the same fork-only files (.claude-plugin/.upstream-base, in this case) with no common version to 3-way-merge from. That's an add/add conflict, and it blocks every GitHub merge strategy (merge, squash, and rebase), not just the one the workflow was using.This means the rebase approach was only ever going to produce a cleanly-mergeable PR the very first time. Any future manual commit to
main(a workflow tweak, a hotfix, anything) would reintroduce the same conflict on the next sync.Fix
Switch branch construction from
git rebase upstream/maintogit merge upstream/main:main's actual tip (upstream/mainmerged in as a second parent), so it can't lose ancestry withmainthe way a rebase does — the next sync only ever needs to merge the delta since the last one.--ours/--theirsflipped to match merge semantics (they're inverted relative to rebase)..claude-plugin/.upstream-baseno longer conflicts at all going forward — upstream doesn't have that path, so it never participates in the 3-way merge; it's written as a deliberate step after the merge instead.gh pr merge --autoswitches from--rebaseto--merge, since GitHub's rebase-merge rejects any branch containing a merge commit — which this branch now always has by design.Validation
I hand-resolved #3 using this exact merge direction (merge
maininto the sync branch, keep the newer.upstream-basevalue, everything else merged with zero conflicts) before writing this fix, so the conflict-resolution mechanics are proven against real data. Upstream hasn't produced new commits since3fe2823yet, so I haven't been able to trigger a fully live end-to-end run of the new code path — happy to triggerworkflow_dispatchonce this merges and there's new upstream content to sync, to confirm the automated run produces a cleanly-mergeable PR with no manual intervention.Test plan
Generated by Claude Code