What's the difference between 'git merge' and 'git rebase'? What's the difference between 'git merge' and 'git rebase'? git git

What's the difference between 'git merge' and 'git rebase'?


Suppose originally there were 3 commits, A,B,C:

A-B-C

Then developer Dan created commit D, and developer Ed created commit E:

A-B-C-D-E

Obviously, this conflict should be resolved somehow. For this, there are 2 ways:

MERGE:

A-B-C-D-E-M

Both commits D and E are still here, but we create merge commit M that inherits changes from both D and E. However, this creates diamond shape, which many people find very confusing.

REBASE:

A-B-C-D-E-R

We create commit R, which actual file content is identical to that of merge commit M above. But, we get rid of commit E, like it never existed (denoted by dots - vanishing line). Because of this obliteration, E should be local to developer Ed and should have never been pushed to any other repository. Advantage of rebase is that diamond shape is avoided, and history stays nice straight line - most developers love that!


Personally I don't find the standard diagramming technique very helpful - the arrows always seem to point the wrong way for me. (They generally point towards the "parent" of each commit, which ends up being backwards in time, which is weird).

To explain it in words:

  • When you rebase your branch onto their branch, you tell Git to make it look as though you checked out their branch cleanly, then did all your work starting from there. That makes a clean, conceptually simple package of changes that someone can review. You can repeat this process again when there are new changes on their branch, and you will always end up with a clean set of changes "on the tip" of their branch.
  • When you merge their branch into your branch, you tie the two branch histories together at this point. If you do this again later with more changes, you begin to create an interleaved thread of histories: some of their changes, some of my changes, some of their changes. Some people find this messy or undesirable.

For reasons I don't understand, GUI tools for Git have never made much of an effort to present merge histories more cleanly, abstracting out the individual merges. So if you want a "clean history", you need to use rebase.

I seem to recall having read blog posts from programmers who only use rebase and others that never use rebase.

Example

I'll try explaining this with a just-words example. Let's say other people on your project are working on the user interface, and you're writing documentation. Without rebase, your history might look something like:

Write tutorialMerge remote-tracking branch 'origin/master' into fixdocsBigger buttonsDrop down listExtend READMEMerge remote-tracking branch 'origin/master' into fixdocsMake window largerFix a mistake in howto.md

That is, merges and UI commits in the middle of your documentation commits.

If you rebased your code onto master instead of merging it, it would look like this:

Write tutorialExtend READMEFix a mistake in howto.mdBigger buttonsDrop down listMake window larger

All of your commits are at the top (newest), followed by the rest of the master branch.

(Disclaimer: I'm the author of the "10 things I hate about Git" post referred to in another answer)


While the accepted and most upvoted answer is great, I additionally find it useful trying to explain the difference only by words:

merge

  • “okay, we got two differently developed states of our repository. Let's merge them together. Two parents, one resulting child.”

rebase

  • “Give the changes of the main branch (whatever its name) to my feature branch. Do so by pretending my feature work started later, in fact on the current state of the main branch.”
  • “Rewrite the history of my changes to reflect that.” (need to force-push them, because normally versioning is all about not tampering with given history)
  • “Likely —if the changes I raked in have little to do with my work— history actually won't change much, if I look at my commits diff by diff (you may also think of ‘patches’).“

summary: When possible, rebase is almost always better. Making re-integration into the main branch easier.

Because? ➝ your feature work can be presented as one big ‘patch file’ (aka diff) in respect to the main branch, not having to ‘explain’ multiple parents: At least two, coming from one merge, but likely many more, if there were several merges. Unlike merges, multiple rebases do not add up. (another big plus)