About Git’s merge and rebase

The example isn’t very good, because it only consider one commit (merged or rebased), giving you the impression that the resulting commits are similar. In general, a rebase will add multiple commits, while a merge will add at most one (fast-forward merges add none).

Moreover, as long as there is no conflict to solve, or if you solve said conflicts the same way each time, the final content of C3′ and C5 will be the same but they remain different commits (since C3′ and C5 have different parents, they’ll also have different hashes, a fact that is more obvious in the illustrations below). Correspondingly, the recorded history for each is different. Note for the rebase, the history is linear, while for the merge it’s a lattice.

Consider the same question when merging/rebasing several commits, as illustrated in “A Visual Git Reference” from Mark Lodato. You will see that the end result is quite different.

git checkout master
git merge other # update master with tip of branch 'other' changes

git merge other

You take only:

  • the current commit (ed489 below since you are on master),
  • the latest commit of branch other (which is a snapshot representing the full content of the repo when branched in ‘other‘, not a delta)
  • their common ancestor (b325c), and performs a three-way merge.

For the meaning of the working directory and stage in this diagram, note the arrows going to the three-way merge, then to the working directory and stage. The working directory represents all the files that you see (on your hard drive), some of which are changed as a result of the three-way merge. The stage holds the files changed by the three-way merge, which is then used to create the new commit (f8bc5).

This is very different from a rebase which strives to reapply each and every commit of a branch on top of the destination branch:

git checkout topic # this time we are on topic
git rebase master  # means: recreate every topic commits on top of master
                           at the end, we are still on (new) 'topic' branch

git rebase master

The above command takes all the commits that exist in ‘topic‘ but not in master (namely 169a6 and 2c33a), replays them onto master, and then moves the branch head to the new tip. Note that the old commits will be [eventually] garbage collected if they are no longer referenced.

Rebasing uses the working directory and the staging area as it replays the commits (apply changes to working directory, add changes to staging area, commit the staged changes, repeat). Once all this is done, the head of the rebased branch is set to the last of the new commits (f7e63).


2 additional differences:

Leave a Comment