Skip to content

docs(pull-request-workflow): merging divergent upstream history in forks#97

Merged
CybotTM merged 2 commits into
mainfrom
docs/merging-divergent-upstream-history
Jul 15, 2026
Merged

docs(pull-request-workflow): merging divergent upstream history in forks#97
CybotTM merged 2 commits into
mainfrom
docs/merging-divergent-upstream-history

Conversation

@CybotTM

@CybotTM CybotTM commented Jul 15, 2026

Copy link
Copy Markdown
Member

Catching a fork up with its upstream reads as a merge-strategy question. It's mostly a scope question — and four traps sit between the two. All four were hit in a single session on an archived-upstream fork (netresearch/terraform-provider-ad#14, closed in favour of #16).

What's added

1. "Merge" is a constraint on history rewriting — not an instruction to import everything

When a maintainer rejects a rebase because "rebasing would break our releases" and says "we need to merge", the load-bearing part is don't rewrite our release SHAs. Cherry-pick satisfies that too.

The fork was 22 ahead / 11 behind. The merge produced 548 conflicts and 11 DCO-breaking commits — and the entire net gain was a two-line typo fix. The other 10 upstream commits were vendor churn, upstream's own release CI, and dependency bumps the fork had already surpassed. The delta had been measured before the merge; the merge ran anyway. The maintainer's correction — "if the typo is the only change, pull in the typo, nothing more" — was the whole job.

Adds the delta-measurement commands to run before choosing the mechanism.

2. Resolve allowed merge methods before authoring a merge commit

A rebase-only repo cannot land a merge commit: --rebase flattens it and rewrites exactly the SHAs the merge existed to preserve. Today allow_merge_commit appears only in the merge step of the lifecycle checklist — too late to reshape the work.

3. Conflicts are not the whole merge — check clean ADDs under a deleted path

git merge only conflicts on paths both sides touched. Files the other side added that you never had merge silently.

The fork had run chore: unvendor; upstream still vendors. 545 paths conflicted DU (deleted by us / modified by them) — and 252 more merged cleanly as additions, because upstream's vendor upgrade had added files the fork never carried. Resolving only the conflicts would have re-vendored the project and reverted the unvendoring, with a green merge and no warning.

Includes the git rm -rfq detail — plain git rm refuses when the index has staged changes.

4. DCO and third-party history are structurally incompatible

Sign-off is an authorship declaration, so no fork can sign off upstream's commits. Any fork merging any third-party history fails DCO by construction — it's a property of the operation, not a mistake.

Flags that the DCO bot's own advice is wrong here: it suggests git rebase HEAD~N --signoff, which flattens the merge and forges sign-offs on other people's commits. Gives the port-and-re-author path instead (cherry-pick -x keeps the original author and still fails DCO; --amend --reset-author --signoff makes it honestly yours).

Placement

New section after the merge-strategy comparison in pull-request-workflow.md, plus a cross-link from Signing and DCO Failures — whose steps don't apply when the unsigned commits are someone else's.

Verification

markdownlint-cli2: 0 errors. Anchor target confirmed to resolve. Docs-only, no version bump — matching 05d53d1 and the surrounding docs(<reference>): history. Every command shown was run in the originating session.

Catching a fork up with an upstream reads as a merge-strategy question but is
mostly a scope question. Adds a section covering four traps, all hit in one
session on an archived-upstream fork:

- '"merge" is a constraint, not an import instruction'. A maintainer rejecting
  a rebase because it breaks releases is constraining SHA rewriting; cherry-pick
  satisfies that too. Measure the net delta before picking the mechanism. Real
  case: a full-history merge produced 548 conflicts and 11 DCO-breaking commits
  to deliver a two-line typo fix -- and the delta had been measured beforehand.

- Resolve allowed merge methods BEFORE authoring a merge commit. A rebase-only
  repo cannot land one: --rebase flattens the merge and rewrites exactly the
  SHAs it existed to preserve. Today allow_merge_commit only appears at the
  merge step, which is too late to reshape the work.

- Conflicts are not the whole merge. git merge only conflicts on paths both
  sides touched; files the other side ADDED that you never had merge silently.
  A fork that had unvendored resolved 545 vendor conflicts -- and 252 more files
  merged cleanly as additions, which would have re-vendored the project with a
  green merge.

- DCO and third-party history are structurally incompatible: sign-off is an
  authorship declaration, so no fork can sign off upstream's commits. Notes that
  the DCO bot's own suggested 'rebase --signoff' is actively wrong here (it
  flattens the merge and forges sign-offs), and gives the port-and-re-author
  path instead.

Cross-links the existing 'Signing and DCO Failures' section, whose steps do not
apply when the unsigned commits belong to someone else.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Copilot AI review requested due to automatic review settings July 15, 2026 08:30
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a comprehensive guide on 'Merging Divergent Upstream History (Forks)' to the git workflow documentation, detailing strategies for handling history constraints, allowed merge methods, silent additions under deleted paths, and DCO compatibility with third-party history. The review feedback suggests using git cherry instead of git log to identify unique commits more accurately, renaming the $UP variable to $UPSTREAM for clarity, and applying optional chaining and default values in jq commands to prevent fatal errors when parsing GitHub API responses.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread skills/git-workflow/references/pull-request-workflow.md
Comment thread skills/git-workflow/references/pull-request-workflow.md
- Define UPSTREAM/FORK. The snippet used an undefined $UP.
- Prefer 'git cherry' over 'git log' for 'what we add': it compares by patch-id,
  so a change upstream already carries under a different SHA is reported as
  already-there rather than counted as ours.

Verified on the originating fork: git log reported 27 commits, git cherry 26 --
the difference being the fork's re-authored port of an upstream fix, which
git cherry matched to the upstream original despite a different SHA, author and
commit message. Since the whole point of the section is measuring the delta
before choosing a mechanism, an overstated delta is the wrong input.

Declined the accompanying jq optional-chaining suggestion: jq field access on
null returns null and exits 0 (verified), so '.a.b' on a null '.a' is not the
fatal error the review described.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@sonarqubecloud

Copy link
Copy Markdown

@CybotTM
CybotTM merged commit 0797422 into main Jul 15, 2026
17 checks passed
@CybotTM
CybotTM deleted the docs/merging-divergent-upstream-history branch July 15, 2026 09:30
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