Rebase tutorial
Table of contents
Notions to operate with
masterbranch: the branch where the stable code lies. Usually nobody should be able to directly push to master.featurebranch: the branch with the code of the functionality that should be added to the stable code.
Problem description
Imagine a master branch with already existing commits:
A B C (master)
*-->*-->*
And the developer decides to create a new feature branch:
(master)$ git checkout -b feature1
Result:
A B C (remote:master, local:feature1)
*-->*-->*
Now the developer adds a commit into feature1:
A B C (remote:master)
*-->*-->*
\ D (local:feature1)
\----->*
What happens when someone merges his branch into master before you?
A B C E (remote:master)
*-->*-->*-->*
\ D (local:feature1)
\--->*
Your branch becomes outdated so if you will merge your branch now you will get:
A B C E M_1(remote:master)
*-->*-->*-->*--->*
\ /
\-->*/ D (local:feature1)
where M_1 is a merge commit. Up until now nothing scary and it looks pretty nice, but imagine having several commits merged in the meantime that start from different commits and everything looks entangled that you cannot see what code does your feature1 branch wants to merge without seeing the diff from the merge request.
F G (local:feature2)
*-->*\
/ \
A B C E / M_1 \ M_2 (remote:master)
*-->*-->*-->*--->*----->*
\ /
\-->*/ D (local:feature1)
In order to avoid this, before merging the merge request, rebase your feature1 branch on top of master:
(feature1)$ git checkout master
(master)$ git pull origin master
(master)$ git checkout feature1
(feature1)$ git rebase master
(feature1)$ git push -f origin feature1
What do the above commands do:
- Switch from branch
frature1tomasteron your local repository - Update your local
masterbranch by pulling all the new commits from origin master - Switch back to branch
feature1 - The most important part: rebase
feature1branch on top ofmasterbranch - Update your remote branch by force pushing to
origin:feature1
Before:
A B C E (remote:master)
*-->*-->*-->*
\ D (remote:feature1)
\--->*
After step 4:
A B C E (remote:master)
*-->*-->*-->*
\ \ D' (local:feature1)
\ \--->*
\ D (remote:feature1)
\--->*
Note that the hash of the commit has changed after rebasing at step 4, so on your remote feature1 branch it is still the commit with hash D, while on your local branch, the hash of the commit changed to D' - the changes are the same if no conflicts arose during rebasing. That’s why we should force push feature1 to our remote repository.
After step 5:
A B C E (remote:master)
*-->*-->*-->*
\ D' (remote:feature1)
\--->*
Those 5 steps from above can be substituted with a nicer suite of commands:
(feature1)$ git pull -r origin master
(feature1)$ git push -f origin feature1
Note the git pull -r origin master command - it is an alias for the first 4 commands.
In case that during rebasing you have conflicts:
(feature1)$ git pull -r origin master
(rebasing-in-progress)$ ... some conflicts detected, please solve them ...
Solve your conflicts and after that do:
(rebasing-in-progress)$ git add .
(rebasing-in-progress)$ git rebase --continue
(feature1)$ git push -f origin feature1
Summary
Remember the following commands:
git pull -r origin mastergit add .- in case you had conflicts and you resolved them allgit rebase --continue- in case of conflicts and after the step abovegit push -f origin <your_feature_branch_name>- force update your remote feature branch
More information about rebasing you can find here.