Categories
git git-merge git-rebase version-control

When do you use Git rebase instead of Git merge?

2099

When is it recommended to use Git rebase vs. Git merge?

Do I still need to merge after a successful rebase?

8

  • 3

    See: stackoverflow.com/questions/457927/…

    – TStamper

    Apr 29, 2009 at 20:27

  • 36

    this is good: atlassian.com/git/tutorials/merging-vs-rebasing

    Aug 28, 2015 at 19:47

  • 14

    One problem with people who like to use rebase is that it deters them from pushing their code regularly. So wanting clean history prevents them from sharing their code, which I think is more important.

    Oct 6, 2015 at 8:38

  • 14

    @static_rtti: That’s just not true. You’re using a rebase-based flow wrong if it prevents you from pushing your changes regularly.

    – juzzlin

    Jan 9, 2016 at 21:14

  • 5

    My heuristic: “Try rebase, if it dissolves into conflict resolution hell give up and merge master into your branch and move on.” – more detail in my post timwise.co.uk/2019/10/14/merge-vs-rebase (in the context of commercial development)

    – Tim Abell

    Sep 2, 2020 at 14:55

536

It’s simple. With rebase you say to use another branch as the new base for your work.

If you have, for example, a branch master, you create a branch to implement a new feature, and say you name it cool-feature, of course, the master branch is the base for your new feature.

Now, at a certain point, you want to add the new feature you implemented in the master branch. You could just switch to master and merge the cool-feature branch:

$ git checkout master
$ git merge cool-feature

But this way a new dummy commit is added. If you want to avoid spaghetti-history you can rebase:

$ git checkout cool-feature
$ git rebase master

And then merge it in master:

$ git checkout master
$ git merge cool-feature

This time, since the topic branch has the same commits of master plus the commits with the new feature, the merge will be just a fast-forward.

13

  • 80

    but this way a new dummy commit is added, if you want to avoid spaghetti-history – how is it bad?

    – Incerteza

    May 19, 2014 at 14:07

  • 12

    Also, the –no-ff flag of merge is very very useful.

    May 22, 2014 at 12:39

  • 12

    @アレックス as user Sean Schofield puts it in a comment: “Rebase is also nice because once u do eventually merge ur stuff back into master (which is trivial as already described) you have it sitting at the “top” of ur commit history. On bigger projects where features may be written but merged several weeks later, you don’t want to just merge them into the master because they get “stuffed” into the master way back in the history. Personally I like being able to do git log and see that recent feature right at the “top.” Note the commit dates are preserved – rebase doesn’t change that information. “

    – Adrien Be

    Mar 1, 2016 at 4:37

  • 5

    I think it bears repeating here — remember that all these terms (merge, rebase, fast-forward, etc.) are referring to specific manipulations of a directed acyclic graph. They become easier to reason about with that mental model in mind.

    Jan 27, 2017 at 19:24


  • 38

    @Aldo There’s nothing “clean” or “tidy” about a rebased history. It’s generally filthy and IMHO awful because you have no idea what really went on. The “cleanest” Git history is the one that actually occurred. 🙂

    May 14, 2018 at 13:58

394

TL;DR

If you have any doubt, use merge.

Short Answer

The only differences between a rebase and a merge are:

  • The resulting tree structure of the history (generally only noticeable when looking at a commit graph) is different (one will have branches, the other won’t).
  • Merge will generally create an extra commit (e.g. node in the tree).
  • Merge and rebase will handle conflicts differently. Rebase will present conflicts one commit at a time where merge will present them all at once.

So the short answer is to pick rebase or merge based on what you want your history to look like.

Long Answer

There are a few factors you should consider when choosing which operation to use.

Is the branch you are getting changes from shared with other developers outside your team (e.g. open source, public)?

If so, don’t rebase. Rebase destroys the branch and those developers will have broken/inconsistent repositories unless they use git pull --rebase. This is a good way to upset other developers quickly.

How skilled is your development team?

Rebase is a destructive operation. That means, if you do not apply it correctly, you could lose committed work and/or break the consistency of other developer’s repositories.

I’ve worked on teams where the developers all came from a time when companies could afford dedicated staff to deal with branching and merging. Those developers don’t know much about Git and don’t want to know much. In these teams I wouldn’t risk recommending rebasing for any reason.

Does the branch itself represent useful information

Some teams use the branch-per-feature model where each branch represents a feature (or bugfix, or sub-feature, etc.) In this model the branch helps identify sets of related commits. For example, one can quickly revert a feature by reverting the merge of that branch (to be fair, this is a rare operation). Or diff a feature by comparing two branches (more common). Rebase would destroy the branch and this would not be straightforward.

I’ve also worked on teams that used the branch-per-developer model (we’ve all been there). In this case the branch itself doesn’t convey any additional information (the commit already has the author). There would be no harm in rebasing.

Might you want to revert the merge for any reason?

Reverting (as in undoing) a rebase is considerably difficult and/or impossible (if the rebase had conflicts) compared to reverting a merge. If you think there is a chance you will want to revert then use merge.

Do you work on a team? If so, are you willing to take an all or nothing approach on this branch?

Rebase operations need to be pulled with a corresponding git pull --rebase. If you are working by yourself you may be able to remember which you should use at the appropriate time. If you are working on a team this will be very difficult to coordinate. This is why most rebase workflows recommend using rebase for all merges (and git pull --rebase for all pulls).

Common Myths

Merge destroys history (squashes commits)

Assuming you have the following merge:

    B -- C
   /      \
  A--------D

Some people will state that the merge “destroys” the commit history because if you were to look at the log of only the master branch (A — D) you would miss the important commit messages contained in B and C.

If this were true we wouldn’t have questions like this. Basically, you will see B and C unless you explicitly ask not to see them (using –first-parent). This is very easy to try for yourself.

Rebase allows for safer/simpler merges

The two approaches merge differently, but it is not clear that one is always better than the other and it may depend on the developer workflow. For example, if a developer tends to commit regularly (e.g. maybe they commit twice a day as they transition from work to home) then there could be a lot of commits for a given branch. Many of those commits might not look anything like the final product (I tend to refactor my approach once or twice per feature). If someone else was working on a related area of code and they tried to rebase my changes it could be a fairly tedious operation.

Rebase is cooler / sexier / more professional

If you like to alias rm to rm -rf to “save time” then maybe rebase is for you.

My Two Cents

I always think that someday I will come across a scenario where Git rebase is the awesome tool that solves the problem. Much like I think I will come across a scenario where Git reflog is an awesome tool that solves my problem. I have worked with Git for over five years now. It hasn’t happened.

Messy histories have never really been a problem for me. I don’t ever just read my commit history like an exciting novel. A majority of the time I need a history I am going to use Git blame or Git bisect anyway. In that case, having the merge commit is actually useful to me, because if the merge introduced the issue, that is meaningful information to me.

Update (4/2017)

I feel obligated to mention that I have personally softened on using rebase although my general advice still stands. I have recently been interacting a lot with the Angular 2 Material project. They have used rebase to keep a very clean commit history. This has allowed me to very easily see what commit fixed a given defect and whether or not that commit was included in a release. It serves as a great example of using rebase correctly.

3

  • 21

    I mostly love this answer. But: Rebase doesn’t make a “clean” history. It makes a more linear history, but that’s not the same thing at all, since who knows now much “dirt” each commit is hiding? The cleanest, clearest Git history is the one that keeps branch and commit integrity.

    May 14, 2018 at 14:01

  • 4

    It’s worth mentioning that git has recently changed it’s git pull behavior to include the --rebase flag by default. That means that doing rebases on branches used by multiple developers is a little less dangerous. A person pulling your changes might be surprised that there are some conflicts to be resolved during such an operation, but there would be no disaster.

    – pkubik

    Jul 31, 2020 at 13:31

  • 1

    Another con for rebase, imo it’s harder in high-velocity git repos especially where the build time is > average time between merges. If branches are constantly being merged in, you need to keep rebasing until it’s your turn which can be tricky if you’re also coordinating with a build to pass. e.g. monorepos rebase merges to a shared branch might be difficult

    – nijave

    Aug 11, 2021 at 19:51