Today we are going to look at how Git merge and rebase commands behave while trying to keep feature branch up to date.
In a large codebase where a lot of people are working we have constant updates to the master
branch. We want to work on top of this branch and always have to latest changes. We can achieve this by either using merge
or rebase
to get the latest changes made in master
branch into our feature branch.
merge
So what is merge doing:
Join two or more development histories together
Let's now look at an example using merge
to keep our branch up to date. This is pretty simple example with a few commits in each branch:
* c5d39ef (HEAD -> feature) update 1 feature.txt
* 0c4d97c add feature.txt
| * 4d55c54 (master) update 1 master.txt
|/
* 2358179 add master.txt
// Different representation of the situation
A---B master
\
C---D feature
We started our feature
branch from master
where at first there was only one commit A
. We made a commit 'C' in our feature branch. In the mean time someone made a commit B
in master
branch and after that we made another commit D
in our feature branch. We now have to get the latest changes from master
into our feature branch and we are going to use merge
.
After executing git merge master
from our feature branch we got:
* ec3f6dc (HEAD -> feature) Merge branch 'master' into feature
|\
| * 4d55c54 (master) update 1 master.txt
* | c5d39ef update 1 feature.txt
* | 0c4d97c add feature.txt
|/
* 2358179 add master.txt
// Different representation of the situation
A---B master
\
C-B-D-E feature
It has it's benefits, of course, as every other thing in software development but the drawbacks in large codebase are huge.
- It is hard to go back and change/clean our feature branch commits.
- It is making hard to follow and find out when/why something was done.
In this simple example maybe it is understandable what happened. But in real life where we got hundreds of commits and we will make a lot of merge commits which are redundant. You can imagine that this is going to become almost impossible to follow when we are working for a long time on a feature because we will end up with a lot of merge commits.
rebase
to the rescue
So what is rebase doing:
Reapply commits on top of another base tip
We will review the same scenario but using rebase
instead.
A---B master
\
C---D feature
After executing git rebase master
from our feature branch we got:
* 7d4b7c0 (HEAD -> feature) update from-rebase.txt
* 5b61ccd add from-rebase.txt
* d694446 (master) update rebase.txt
* 8f8b0e3 add rebase.txt
// Different representation of the situation
A---B master
\
C'-D' feature
We got our changes reapplied over the latest commit from master
branch. Note: the commits have the same set of changes but from Git point of view they are completely different objects and have different hashes.
Conclusion
By using rebase
we benefit from:
- making the history in our
master
branch much easier to follow because it is linear - long tramlines from long-lived feature branches
- ability to easily change our feature branch history
There are a couple of things to keep in mind though:
- it can be confusing for less experienced Git users
- we are loosing the chronological order - IMO this is not a problem at all because we achieve series of intentional changes that are made to
master
branch - it can result in fixing the same conflict for every commit in the feature branch - for this one I find really useful the git rerere configuration which is saving the resolved conflicts and then reusing them. With it we don't have to resolve the same conflict all over again.
I don't recommend to blindly use rebase
to keep your feature branches up to date but for larger projects my preference is to use rebase
instead of merge
.
When I started using Git I find those concepts very confusing, so I hope someone will enjoy this and will find it useful. If this is the case, please follow me on Twitter where I will share another tips and upcoming articles from my experience.
Top comments (5)
It is true that things can get really messy with
rebase
when people don't understand what is happening. We had this problem for a while, sometimes fixing the problem requires an hour or two... However, I couldn't say that we didn't have problems withmerge
as well. So, I think if people don't spend enough time playing around with Git and learning how it is working and the concepts behind it, we will always end up in messed up situation.From my experience,
merge
is working well enough when the team is small - let's say up to 6-8 people. There aren't so many changes that we would need to get frommaster
branch and keeping the feature branch up to date is not so critical. However, with multiple teams working on the same codebase the situation is pretty different andmerge
is just not working. So, the sooner team members get familiar with more Git commands, the better.This article is just scratching the surface and there are a lot of things going on in a large codebase with a proper Git workflow. I agree deep dive into this topic can be good for an interview.
P.S. I am thinking to share more articles about problems that we encountered in our teams - one of them will be deeper look into
rebase
because when we have branch from a branch things get messy.The additional difficulty of conflict resolution with rebase made me lean towards merge more and more... I hate conflicts!
Give βrerereβ a try - you wonβt need to resolve the same conflict again. Apart from that, conflicts can occur in both cases.
Thanks, I will! How reliably does it work? Any disadvantages compared to merge?
Rerere is just a Git configuration, it canβt be compared to merge. About the differences, there is some more information in the article. : )