Git rebase or Git pull?

A few days ago, one member in my lab and I were about to finish a project together. We also used git server for sharing code and collaborate. However, when I used combination of git fetch, git stash, git rebase and git stash apply to fetch new code, he said it is not recommended to use git rebase and I should use git pull instead. Just for your information, I have been using that 4 commands very often in most of my projects and it almost becomes part of my habit when fetching the code. Although I already have a pretty basic understanding of their differences, I believe this is a good chance for me to study it further and I would like to share with you.

Difference

git pull is shorthand for git fetch followed by git merge, and it is easier to say git pull is a very short command to update your local code with changes from origin repos. So the first difference is very obvious, it is shorter. Now I am asking myself why I need to type 4 consecutive commands just to get a new code?

However, the main difference is actually in the way Git handles the changes. In case of git pull, because it uses git merge to update local code, it will usually create a new commit in case new commits from remote cannot be fast-forwarded. Let's imagine you are developing things on master branch (bad thing :D) and your friend has pushed new commits, if you use git pull, you are likely to see a commit like this

Merge remote-tracking branch of 'origin/master'

That's the default message git created when merging the code. In this case, the origin/master has some commits which cannot be fast-forwarded, so a new commit is created. And in many cases, you will not be able to see the complete commit history. Here is an illustration to help you understand this better.

In the picture above, we are working on Feature branch and we need to merge master branch into the current branch. After running git merge, we will have

If we stay in the feature branch, we will have no idea what commits were made in the master branch because all commits in master have just become a single commit in feature branch.

On the other hand, git rebase will do thing differently. Take the above example again, if we run git rebase master instead of git merge master, we will have the following

In this case, git will first rollback all new commits made on the feature branch, and then move all commits on master branch to feature branch, finally it will apply each new commit again (which has just been rolled back previously). Therefore, this is also called rewriting the history as the hash of each commit on feature branch is now completely different from the value before rebasing.

Because of this history rewriting mechanism, if you already pushed your commits to the remote repository, you would have to push with --force after rebasing because the commit hash is completely changed. And in case someone else already fetch your code before you merge, they will have a big trouble when fetching the code again because the history on their local copy is totally different from the one you have just pushed with --force, they can not merge the changes automatically.

Quick comparison

So, as we have a pretty good understanding of how git pull (or more specifically, git merge) and git rebase work, let's have a quick comparison

  1. Ease
  • git merge: Easy to use, we can avoid many conflicts when merging
  • git rebase: need more advanced knowledge of how git works, can have many conflicts when merging.
  1. History
  • git merge: Ugly git history, it is hard to trace the individual commit
  • git rebase: Clean and tidy git history, you can trace back an individual commit if needed
  1. Issue
  • git merge: It is safe and we often do not worry about losing code
  • git rebase: could be dangerous if being used carelessly.

Conclusion

If you are a git beginner and you want things to be safe, I recommend using git pull and git merge all the time for merging code. Of course, it would create trouble if you want to debug based on git history, but it is still the safest way. In case you want to maintain a clean and tidy git history, git rebase is for you. Just remember, git rebase should be used with care, or you are going to pay a price for that :).

Happy coding!

PS: I read several other articles when writing this post, so please refer to them for more details.

  1. Merging vs. Rebasing
  2. Git team workflows: merge or rebase?
  3. Merging Branches: Without a Conflict – Git Merge
  4. pull with rebase
  5. Getting solid at Git rebase vs. merge