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 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.
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
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.
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
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.
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
git merge: It is safe and we often do not worry about losing code
git rebase: could be dangerous if being used carelessly.
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 :).
PS: I read several other articles when writing this post, so please refer to them for more details.