Merge when other people or systems build on your fork's branch, because it keeps history stable. Rebase when the fork is a private stack of patches on top of upstream and you want a clean, reviewable list. Never rebase a branch others depend on without telling them.
What each choice does to history
A merge adds one commit that joins upstream's changes to your branch. Your earlier commits stay exactly as they were. A rebase replays your commits one by one on top of the new upstream tip, creating new commits with new IDs.
That difference matters for security work. After a rebase, a commit hash you wrote down last month no longer exists on the branch. Audit notes, tickets and build records that cite old hashes stop pointing at anything.
What the Git documentation warns about
The rebase documentation is blunt: rebasing a branch that others have based work on is a bad idea, because anyone downstream is forced to fix their history by hand. It also says the real fix is to avoid rebasing in the first place. Treat that as the default for any shared fork branch.
A decision guide
| Situation | Better choice | Why |
|---|---|---|
| Release branch other teams pull from | Merge | History stays stable |
| Private patch stack, one maintainer | Rebase | Clean list of what you carry |
| You plan to send patches upstream | Rebase on a topic branch | Upstream wants tidy commits |
| Audit trail needed for each sync | Merge | One commit per sync, dated |
| Many conflicts every sync | Merge, with recorded resolutions | Fewer repeated fixes |
You can mix the two. Keep a stable main that you only merge into, and keep topic branches for individual patches that you rebase before sending upstream.
Steps for a merge update
- Fetch upstream and tag your current state so you can return to it.
- Merge the upstream branch into a temporary branch, not straight into main.
- Resolve conflicts, and for each one note why you kept your side or theirs.
- Run tests and a dependency scan on the temporary branch.
- Fast forward main to the result once checks pass.
Steps for a rebase update
- Create a backup branch at your current tip.
- Rebase your patch commits onto the new upstream tip.
- After each conflict, build and test before continuing.
- Compare the old and new patch series. Git has a command for this that shows the differences between two versions of a patch series, or more generally two commit ranges. Use it to confirm no patch changed by accident.
- Force push only to a branch you own, and tell downstream users first.
The comparison step is the one people skip, and it is the one that catches a silently dropped security patch.
Do not lose your own fixes
Whichever method you use, keep a short list of the security related patches you carry, such as backported fixes. After every sync, confirm each one is still present or has been replaced by the upstream version. See carrying a patch while waiting for an upstream merge for how to label them.
Where Safeguard fits
After either method, a fresh dependency scan confirms what the synced build now contains. Safeguard's SBOM and dependency scanning does this, and you can try a free scan at gold.safeguard.sh/scan.
Quick check
Is rebasing ever wrong for a fork?
Yes, when others build on the branch. Rewriting shared history forces them to repair their own copies.
How do I confirm a rebase kept all my patches?
Compare the old and new ranges with the range comparison command before you force push, and check that each patch appears in both.
Sources
Last reviewed: 19 October 2026.