Merge vs. Rebase
Since I was still an intern at STOIC, I was told to use git pull --rebase
as much as possible to avoid unexpected merge conflict. Yes, it was right at that time, because we were all working in the same branch master. However, if you are a big fan of Git Flow, you should probably pay attention, overused rebase may cause panic in a team work. Let’s see why.
Tl;dr? Jump to the summary at the end.
Some Background
Both git rebase
and git merge
are designed to integrate changes from one branch into another one, but the do it in two different ways.
Let’s say you are working on a new feature branch, someone pushed / merged news commits to master. You have two options to incorporate the new commits into your feature, merging or rebasing.
The Merging Way
The easiest way to do so is to merge master into feature.
1 | git checkout feature |
As we can see, git merge
creates a new commit ahead of feature that ties together the histories of both branches.
Merge is the easiest way and it’s a non-destructive operation by creating a new commit. However, on the other hand, it feels kind of uncomfortable if master is under active development, you have to merge master to feature frequently so as to keep up with latest code base. This will generates large amount of merging commits, which can pollute your feature branch.
The Rebasing Way
An alternative to git merge
, you can rebase the feature branch onto master.
1 | git checkout feature |
As you can see this moves the entire feature branch right after the latest commit of master, it gives you the feeling that the base of feature just moved from white commit to the latest blue commit.
The major benefit is you get a cleaner branch and this won’t cause any pollution to feature, no extra merge commits. But there are also a trade-off for this pristine commit history. If you don’t pay attention during rebasing, you might create a potential catastrophic for you teammates.
Golden Rule of Rebasing
As everyone said, unless you totally understand what you are doing, don’t abuse it. The golden rule here is to never use it on PUBLIC branches.
Let’s say if you happen to rebase your feature to master like this.
When you complete your work on feature, you want to push them back to master. Can we rebase them to master? NO, absolutely no. After you rebasing master after your latest feature commit, you local master has already diverged from everybody else’s master, because you share a difference master history. The only solution here is to merge them together, needless to say this will create an extra merge commit that contains duplicated commits that contain the same changes.
Always ask youself, is there anyone else working at this branch? If yes, don’t mess up the history with rebasing.
Some one asks, why can’t we just push local rebased master to remote and overwrite it? The answer is no and yes. You can’t directly push local master to remote because Git prevent this from happening to avoid conflicts. Of course, you can do force push in this situation to sync you local master to remote, instead of merging them.
1 | ## BE CAREFUL with this! |
This overwrites the remote master branch to match the rebased one from your local repository and makes things very CONFUSING for your teammates. What are they going to do with their local master?
Other Magic of git rebase
Local Cleanup
One of the greatest feature of rebasing is that it allows you to squash several commits into one commit in an interactive mode. More detailed instructions can be found here: squashing commits with rebase.
Commits Reorder
As I explained in another post, Reorder Git Commits with Rebase, this gives you full flexibility to reordering local commits. I find this really helpful, especially when you mixed your code review commits and some other features implementation commits. But keep this in mind, only use this for local un-published commits.
Summary
And that’s all you really need to know to start rebasing your branches. If you would prefer a clean, linear history free of unnecessary merge commits, you should reach for git rebase instead of git merge when integrating changes from another branch.
On the other hand, if you want to preserve the complete history of your project and avoid the risk of re-writing public commits, you can stick with git merge. Either option is perfectly valid, but at least now you have the option of leveraging the benefits of git rebase.