Git rebase is a command that may scare some people. They think that rebase is not necessary.
Thus they rarely do rebasing and use only merging. However, I think rebasing is a good practise
as it helps you confirm that your branch is working on the latest changes done by others.
What is rebase
Given you are working on a
master branch, then there is one feature, say a sign-in, needed to be implemented.
What we do here according a normal git workflow is to create a branch named like
We say that
master branch (at commit 94c09e9) is a parent branch of
After some commits done on
feature/sign-in, suppose you decide to update a base css and make another
As you may see, the recent update(0d03724) is not yet applied to
feature/sign-in branch is built based on the old
master branch at commit 94e09e9.
In order to get a new base (a new commit 0d03724) for
feature/sign-in, we need to rebase
feature/sign-in on top of
Thus, rebase, in a simple way, means to change the parent commit of your working branch. Or you can say
to rebuild your target branch on top of the base branch.
Rebase can be done by:
- Check out your feature branch,
git checkout feature/sign-in
- Issue rebase command by supplying a new base branch as parameter,
git rebase master
After doing so, you will see that the parent commit of
feature/sign-in is changed from 94c09e9 to 0d03724.
How does rebase work
Roughly, we see what rebase does is just to move the parent commit of
feature/sign-in to the latest commit
master. But what exactly goes on behind the scene?
rebase command is triggered, these following things happen.
- The commits in
feature/sign-in are temporarily kept.
- The head pointer of
feature/sign-in branch is (hard) reset to 0d03724.
- The commits in (1) are reapplied consequently. The reapplying results in a new commit which has the same
content as the original commit, but with different commit id. For instance, in this scenario, fee8b31 is
re-applied and results in fbcaae2. Then, 48efde8 is replied, and results in 781c6c6. If there was
any conflict between commit in
master, the rebase is paused and the developer
has to resolve the conflict before using
git add <target file> and
git rebase --continue.
What to do after rebase
Issueing rebase command, as you may see, causes the commit’s structure of
feature/sign-in to change.
feature/sign-in contains a whole new commits 0d03724, fbcaae2 and 781c6c6 compared
to the old branch which contains fee8b31 and 48efde8 (noted that fbcaae2 and 781c6c6 are the same as these commits
but they got new SHAs).
By getting a new commit structure, you are prevented from pushing to the remote
feature/sign-in. The only way
to get your updated right there is to use a force push with
git push -f origin feature/sign-in. So, you have to
make sure that your working branch is updated before doing rebase, or you may end up losing some commits.
When rebase is needed
Rebase is a part of the safe procedure to get your working branch merged into the main branch.
Let’s say we are working on a master branch, there are 2 branches in progress:
The latter feature is finished before
feature/sign-in and is merged to master branch.
Soon, you also finished working on
feature/sign-in and you want to merge this to
How will you do?
The easiest way
The easiest way is to merge the code right away by checking out
master and run
git merge feature/sign-in.
If you were lucky enough, your code would get merged. If not, you have to resolve the conflicts. When merging is finished,
you got a new merge commit e9e2b8a which may contain the conflict-resolved content.
The good things for this approach are it is easy to understand and the conflict resolving is done only once.
However, there are many disadvantages:
- Conflict resolving is done only once… yet there may be numerous conflict on numerous files to be resolved.
- If there were so many commits on
master and merging is done very late, resolving conflicts is a nightmare.
You have to call some people who did updates on
master and have them help you resolve the conflicts which
they may forget what they have done already.
- After merging is success, there is no gaurantee that the code will work as normal or the code will pass all the
tests available. In a worst case, you need to commit some fix-commits on
master to resolve the problem.
This is not pleasing.
The rebase-first way
Instead of issuing merge command right away, you should rebase
feature/sign-in on top of
feature/sign-in to be finished, you should oftenly rebase it with
master multiple times (the best is
to rebase everytime there is a new commit on
Two commits (fee8b31 and 48efde8 ) are re-applied and result in efab4e8 and f16eb33 respectively.
During the re-apply, if there are conflicts, the rebase is paused and you have to resolve them. In worst case,
the rebase is paused for 2 times if both commits introduced the conflicts. After you have the rebase done,
you can then merge your code with a no fast forward option using
git merge --no-ff feature/sign-in.
This merge is no-conflict guarantee.
The key is, as stated above, rebase often, everytime there is a new commit on main branch. This approach helps solving
the problem we face on the merge-right-away approach.
- The conflict may happen multiples time, but we compare it in a small amount of change. Resolving
it is a lot easier because we do it in a bite-size. Also, the changes are still fresh. People can help you
solve it easily because they can still remember what they just did.
- After rebase, you can test if your code worked normally on your branch without getting
master dirty. All fix-commits
happen on your branch.
master will be clean and easier to maintain.
Do not forget: rebase often, everytime there is a new commit on main branch. This is very important, or this
approach will not benefit you much.
Rebase lets you move your working branch on top of the recent version of parent branch. This process helps you
update your code and make it perfect for merging. The key is, always rebase everytime there is a new commit on a parent branch.
Also do not forget that, rebase cause your commit tree structure to change. Make sure that you got your branch synced before