When rebasing is better than merging
My simple rules for when to rebase or mergeContinuing the thread of the last few days, today the times I prefer rebasing to merging:
- When I need to update my feature branch with the
main
branch, I rebase.
Yep. That’s my list. It boils down to two simple rules:
- Merge into main.
- Otherwise rebase.
And since that covers virtually all the times that the merge vs. rebsae debate covers, I’ll spend the rest of my time today talking about why I prefer rebasing a feature branch (and tomorrow I’ll round out this discussion with a few excepions I’ve found to my 2 rules).
So I’ll spend the rest of my time today talking about why I prefer rebase. Of course, this is assuming either is appropriate—the best answer to this question is actually neither.
So the main argument for merging rather than rebasing is that merging is easier. And there is some truth to this.
If your branch has diverged significantly from main, such that there are several conflicts, especially multiple conflicts in the same code, then by merging, you get to resolve those conflicts only once. With rebase, you resolve each conflict as it occurs. Each conflict is typically smaller, but there are more of them. And sometimes you resolve the same conflict more than once. This is absolutely annoying.
However, this is optimizing for the current workflow at the expense of future legibility. And while there’s a judgement call to be made, my strong preference is to optimize for future legibility.
Let me enumerate some of the problems I see with the merge approach:
- The merge “scars” left by frequently merging main into your feature branch are noise, that make finding useful information in git history harder.
- The single “merge commit” that comes from resolving conflicts in a merge are very hard to read. If you ever have to look at git history to understand the evolution of a function/class/file, these merge commits will drive you nutty. Best to avoid them.
- I’ve seen countless merges “gone bad”, that end up showing the wrong history in GitHub (I don’t know exactly what causes this, becuase I don’t do merges like this, but I see it fequently from other teammates who are in the habit of merging into feature branches).
- It makes git bisect a bit more confusing. This isn’t something I usually optimize for, becuse it’s rarely used, but when it is used, it’s nice to have a clean history. I consider this more a bonus win, rather than a primary reason.