Git – why to use rebase?
For most of my developer’s life, I was not aware of what git rebase is for. Oh, of course, for most of my life git was not existing. Also, I was using SVN for some time prior to git. This is why my git history starts in 2013. But still, for most of these years, I was not sure why I should use rebase.
The thing is that I was simply not aware of what rebase is. Not only what it is for, but what it is. And there is one more thing I will mention, regarding merge after rebase. Let’s start.
What is git rebase?
In short, rebase is the process in which the sequence of commits is moved to the new base commit.
In practice, we are working on branches. Each branch was created based on a particular commit in the repository history. This commit is the base commit for our branch.
On the image above you can see “my-branch” based on the initial commit of the repository. There are also some changes visible on the master branch.
After the rebase, your history will look like this:
The branch is still there, but the base commit is no longer the same. The base commit for “my-branch” is now “Second commit on master”.
OK, but what for?
You may now ask – why should I use rebase? Please take a look at these examples. The first one is the history of the repository when “my-branch” was merged into master without prior rebase:
The second one is history as it looks when we performed rebase first:
There is one more possibility, take a look at this one:
On the first one, you can see two separate timelines, each with its own commits. You can see that the base commit for “my-branch” was the initial commit and that there were adjustments to the master in the meantime. The problem is that for more complicated projects this can get messy. In one of the projects I’m in it looks like this:
On the second, history is simple – the branch was rebased to the last commit of master just before merge. This way the branch commits are straight in the line with others. No “fork” at the beginning and “join” afterward, no strange history jumps and hard to follow lines.
The third is my preferred way of rebasing and merging. You can see branch commits as the separate group on the branch line. How I achieved this? There are still two steps to perform: rebase and merge. The rebase step is performed on “my-branch”:
> git checkout my-branch > git rebase master
The thing is to use “no fast forward” when merging:
> git checkout master > git merge --no-ff my-branch
With the “–no-ff” switch, the merge is performed without “fast forward” strategy and the resulting history shows clearly that there are separate commits coming from the branch.
Important note regarding rebase
In git, the commit identifier is based (among other things) on the identifier of the previous commit. This means that during rebase, all identifiers of commits in your branch will be rewritten. They will be changed.
This means that you should not perform rebase on the branches you already pushed to any remote repository. There are exceptions, but you should know exactly what you are doing.