I can’t emphasize how important git is in software development process, especially when you have a large team working in parallel.

As a result, resolving conflict and keeping your own feature branch up to date with the master branch has become essential part of daily job of every developers.

Git has two ways to merge commits from one branch to another branch:

  • git merge
  • git rebase

When you try to pull the upstream branch changes into your feature branch, git rebase is always better than merge as it doesn’t pollute your commit history with all those merge commits. Though it does require a bit learning curve to understand how it works.

I was always using git rebase master to re-sync changes but recently, I’ve come into a situation where the dev flow of my current job is squashing all the commits on merging into master branch. Sometimes, you can work on different features, and you might create a new feature branch from another feature that’s current in code review to re-use some code from it. But once that’s been merged into master branch, the original commit history is gone and when you try to rebase from master branch, you will have to resolve some conflicts that you may have resolved in the original feature branch, which doesn’t seem inefficient.

Before
master:      a -- b -- c -- d
                        \
feature1:                e -- f -- g
                                    \
feature2:                            h -- i -- j


After merging feature1:

master:      a -- b -- c -- d -- E (sqaushed commit)
                        \
feature2:                e -- f -- g -- h -- i -- j

As the parent branch: feature1 is gone, feature2 has to inherite its commit history implicitly, which makes the rebase hard because you have to resolve conflicts for commit: e, f and g again.

Git actually has already known this problem, and it provides a tool for developers to resolve this situation.

git rebase –onto X X X

Let’s look at the git rebase from another perspective: it doesn’t do anything fancy but only apply the commits you did on the branch one by one onto the new base branch. With that --onto argument, you can precisely control what commits to be applied.

In the same example above, let’s use this tool to avoid facing old conflicts from feature1 branch.

Firstly, we need to find out the parent commit from which your feature2 branch is created. If the feature1 branch is still in your local history, you can use git merge-base to find out.

git merge-base feature1 feature2

This command will tell you the commit g is the parent commit. The next step would be using this commit in the git rebase --onto.

git rebase --onto master g

This tells git to rebase the commits after g onto the master branch, and now you only need to resolve conflicts for feature2 branch only. Yay! 🎉

You can also specify a 3rd parameter at the end to choose the target branch if you are not checked out to it. It’s a pretty handy parameter if you want to rebase a branch, but you don’t want to switch to it.

I am always amazed on how powerful git is and its rich funcionalities to enable developers collaborate more efficiently.