Skip to content

fix: sync-upstream should merge, not rebase, so future sync PRs stay mergeable - #4

Merged
SmailG merged 1 commit into
mainfrom
claude/fork-sync-workflow-lag-o108mo
Jul 18, 2026
Merged

fix: sync-upstream should merge, not rebase, so future sync PRs stay mergeable#4
SmailG merged 1 commit into
mainfrom
claude/fork-sync-workflow-lag-o108mo

Conversation

@SmailG

@SmailG SmailG commented Jul 18, 2026

Copy link
Copy Markdown
Owner

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 upstream 3fe2823), and this PR fixes the workflow so future sync PRs don't hit the same wall.

Root cause

Create sync branch and rebase took whatever commits were unique to main (relative to upstream/main) and rebased them onto the new upstream tip, producing a branch with entirely rewritten commit SHAs. That's fine in isolation, but the moment main gains a commit that didn't come from a previous sync merge (here: the #1 and #2 workflow fixes), the rebased branch and main no 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/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 can't lose ancestry with main the way a rebase does — the next sync only ever needs to merge the delta since the last one.
  • Same conflict policy as before ("upstream wins", README rebuilt from the fork's template), just with --ours/--theirs flipped to match merge semantics (they're inverted relative to rebase).
  • .claude-plugin/.upstream-base no 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.
  • Final gh pr merge --auto switches from --rebase to --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 main into the sync branch, keep the newer .upstream-base value, 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 since 3fe2823 yet, so I haven't been able to trigger a fully live end-to-end run of the new code path — happy to trigger workflow_dispatch once 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

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).
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • sync

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: fba1b407-8a83-4e40-9e0a-dcaa467750e9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

.coderabbit.yml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key: "version"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@SmailG
SmailG marked this pull request as ready for review July 18, 2026 10:52
@SmailG
SmailG merged commit b52c10f into main Jul 18, 2026
1 check passed
@SmailG
SmailG deleted the claude/fork-sync-workflow-lag-o108mo branch July 18, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants