Git : Merge Vs Rebase

Sumit Mishra
5 min readAug 15, 2021

This story deals with what is git merge and why rebase came into the picture?

What is merging?

Merging is the process of combining two separate pieces of code into one.

In how many ways can we achieve this?

For the sake of example, the branch we will be merging to is master. **This could be any branch in real life**

We can achieve merging in 2 ways :

  1. 3-way merge (happens when the master has diverged)
  2. fast-forwarding (happens when the master hasn’t diverged)

3-way merge

Let's understand this using a series of steps:

  1. Master has some code on 10th Aug with 10 commits on it.
  2. I took a copy of the master and created a branch out of it to develop my feature on 10th Aug eg: git checkout -b top-nav-bar origin/master
  3. I completed my feature by 12th Aug and have 4 new commits as part of it.
  4. I want it to get merged back into master for everyone to avail it.
  5. But by now the master has got 6 new commits added in 2 days. The total commit count is 16 on master.
  6. So master has diverged in two directions since I last took the copy of the master branch. It diverged with 4 new commits in the direction of my feature and 6 new ones added on itself. Git does not allow merging of branches that diverged and would urge to first resolve this divergence and try again.
  7. In order to resolve this, I need to do a 3–way merge to take my changes to master now.
  8. I will pull the master’s latest code in my feature branch. I will resolve conflicts. I will then add the new resolved files and create a new commit which is symbolic of a commit dedicated only to merging. This is called merge commit. Now I can push my changes on master. So instead of 4, I will be pushing 5 commits now where 1 extra commit is created solely for merging and has nothing to do with my feature development.
  9. finally, the master will have 21 commits. 16 older one with (4 + 1) commits added from my feature.

So what just happened? We messed up the master’s timeline in 2 ways:

  1. We ended up creating one extra commit which has nothing to do with my feature and this commit will be all around the master timeline in the future too if we follow this approach of merging code ie, feature-related commits followed by a merge commit. The master’s timeline will be sprinkled and muddied with this extra baggage of commits and will pollute the timeline.
  2. every time we merge code this way, the master’s timeline visually will look like a branch being cut off somewhere in the past and getting joined sometime in the future. So master’s timeline will look like a straight line with side railings all along. these side railings are nothing but the individual timelines of the feature branches which appear to run parallel with the master. An ideal timeline shape would be straight with no side rails and this is not possible to achieve with a 3-way merge.

What is fast-forwarding merge?

Let’s understand this too using a series of steps:

  1. Master has some code on 10th Aug with 10 commits on it.
  2. I took a copy of the master and created a branch out of it to develop my feature on 10th Aug eg: git checkout -b top-nav-bar origin/master
  3. I completed my feature by 12th Aug and have 4 new commits as part of it.
  4. I want it to get merged back into master for everyone to avail it.
  5. But by now there are no new commits on master. It still has those 10 commits which we saw on 10th aug. So master hasn't moved on since then. This is when we can say the master hasn't diverged.
  6. In order to merge my code in master, all that git has to do is to append my 4 feature commits to the master’s last commit (10th) to make it an overall series of 14 commits on master and move the tip of the master branch (which was earlier pointing at its 10th commit) to the last commit ie 14th commit. No actual merge happened here. Just appended and dragged the master branch tip to the end of all the commits.
  7. This is called fast-forwarding as we simply move the tip of the master branch to the end of new commits added. And we end up merging code to master!

So what just happened? So if there are no new commits added on master by the time we push our new feature’s commits, merging happens through fast forward. We maintain a linear timeline on master and do not introduce any extra commits which are nowhere related to the feature development. An ideal merge.

In the event that you require a merge commit during a fast forward merge for record keeping purposes you can execute git merge — no-ff <branch> option.

Why rebase then?

Because we strive to achieve an ideal timeline. An ideal timeline is defined by a linear commit history with no parallel siderails and no unwanted merge commits.

This can be achieved using fast-forwarding merge. But expecting ff merge always is hardly practical as people will add their commits before you merge your code every time and hence master will diverge more often than not.

So how to achieve my ideal timeline if ff merge is not always possible as it seemed to us the only way so far to achieve an ideal timeline? Rebase comes to the rescue. Rebase tries to keep your commit timeline straight and do not add any new commits just like ff merge. So we have got an alternate approach to achieve what we were trying to achieve through ff merge.

So what is rebase used for?

  1. alternative to merging
  2. cleanup tool/ cleaning history

feature br> git rebase master

when we rebase, we rewrite our feature branch timeline , and the commits hash change.

Before rebase and after rebase my feature commit ids change to mimic new commits so as to facilitate ff and a linear tree

after rebasing ur structure is linear. and ff can be performed and we know ff does not need to do any merge. So no merge is required after rebasing and one can simply push their changes

NEVER rebase commits that we shared with others

  1. Rebase commits that u have on ur machine and other don't; basically local commits
  2. So once a commit goes public say after pushing, then don't rebase them.
  3. Rebase only ur feature and not the one u r pushing ur code into
  4. don't rebase commits that are shared

Merge conflict doesnt go anywhere with rebase. It will still occur. We have to resolve them so that we keep pushing for that ff phase.

After rebase u may see commits applied on ur commits, this will generate conflicts sometime. Resolve it and do git rebase — continue.

it will aplly new commits again. until the line becomes clear.

finally simply push

--

--

Sumit Mishra
0 Followers

Sde 2 at Paypal. A Frontend developer with an experience of 4.5 years. A react developer.