Merge vs rebase for long-running branches Jump to heading
Most merge-versus-rebase advice assumes branches that live a day or two. Long-running branches — a framework migration, a large refactor, a feature that needs months behind a flag, an integration branch shared by a team — change the trade-offs. Rebasing a three-month branch means replaying hundreds of commits, resolving conflicts in each, and forcing everyone working on it to reset afterwards. Never integrating means a merge at the end that touches everything at once. The practical answer for most long branches is to merge main in regularly while the branch lives, and decide at the end how its history should land. This page sets out that routine and the exceptions, within merge vs rebase decision matrix.
When to use this approach Jump to heading
- A branch will live for weeks or months while main keeps moving.
- Several people commit to the branch, or other branches are based on it.
- Previous long branches ended with a painful “big bang” merge.
- You have confirmed the branch really must be long-lived; shorter alternatives are in limiting feature branch lifetime.
Step 1 — Compare the options over the branch’s whole life Jump to heading
The choice is not one operation but a pattern repeated for weeks. Compare the patterns, not single steps.
Step 2 — Merge main in on a regular rhythm Jump to heading
Pick a rhythm — weekly, or whenever main has a significant change in an area the branch touches — and merge main into the branch. Each merge resolves only the conflicts introduced since the last one.
git switch feature/framework-v5 && git pull --ff-only
git fetch origin
git merge --no-ff origin/main -m "Merge main into feature/framework-v5 ($(date +%F))"
make test
git push # How far behind is the branch right now?
git rev-list --count feature/framework-v5..origin/main rerere helps here too: if you try a merge, abort it, and redo it later, previous resolutions are reused. Combine with throwaway test merges between real ones, as in rerere for long-lived topic branches.
Step 3 — Keep the branch’s own work separable Jump to heading
With merges of main interleaved, the branch’s own changes can be hard to see. Two commands recover the view: the diff against the merge base, and the branch’s own commits excluding merges.
git diff origin/main...feature/framework-v5 --stat # what the branch changes, net
git log --oneline --no-merges origin/main..feature/framework-v5 # the branch's own commits Reviewers of a long branch should read the net diff rather than walking commit by commit through weeks of merges.
Step 4 — Know when rebasing is still right Jump to heading
Rebasing a long branch makes sense in two situations: the branch has only one author and nobody builds on it, or the branch is about to land and the team wants its commits linear on main. In the second case, rebase once at the end — and consider squashing groups of commits first to avoid replaying the same conflicts repeatedly.
# Final, one-time rebase of a single-author long branch, with history tidied first
base=$(git merge-base origin/main HEAD)
git rebase -i "$base" # squash noise; merges of main are dropped by default
git rebase origin/main The repetition problem is explained in repeated conflicts when rebasing vs merging.
Step 5 — Land the branch: merge, squash, or rebase Jump to heading
At the end, choose how the branch’s history lands on main, independently of how it was kept current.
For very large branches, a squash produces a commit too large to review or bisect usefully; a merge commit preserves the internal steps. That is often the deciding factor for migrations.
Step 6 — Shorten the next one Jump to heading
After the branch lands, look at why it had to live so long. Most long branches could have been split behind a flag or an abstraction, delivering the same change as a series of short branches.
# How long did it live, and how many merges of main did it need?
git log --merges --oneline --grep='Merge main into feature/framework-v5' | wc -l The techniques are in branch by abstraction for large changes.
Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Doesn’t merging main in make the branch’s history messy? Jump to heading
It adds merge commits to the branch. If main uses squash merging, they disappear when the branch lands. If main keeps merge commits, --first-parent on the branch shows its own story cleanly.
How often should main be merged in? Jump to heading
Often enough that each merge is small — weekly for most teams, more often when main is changing the same area heavily. A nightly throwaway merge can tell you when a real one is due.
Can other branches be based on the long branch? Jump to heading
Yes, and merging main in rather than rebasing is what makes that workable: dependent branches never see the long branch’s history rewritten.
Related Jump to heading
- Merge vs Rebase Decision Matrix — the parent topic.
- Keeping a Long-Lived Branch in Sync with Main — the practical sync routine.
- Keeping Merge Commits with --rebase-merges — rebasing a branch that contains merges.
- Measuring Branch Age Against Conflict Risk — the cost of long branches, measured.