These are two approaches to insert changes from a feature branch to a development/master/other branch in Git. A lot of people ask what is the difference. I will attempt to answer that question.
Git merge is definitely the easier and faster way to work, but isn't also writing all your code in a single class? Can you really tell what happened in a history with thousands of merges, going in and out in random places?
You can organize the messy history into this nice tidy one:
Your visual git editor will also load faster. Not only that but you can do all other awesome stuff with rebase, like edit commits further down in your history.
What's the catch?
Rebase it hard to master, and even if you do, to make it efficient to work with, you would need to separate code domains really well, because conflicts can be very annoying to solve with rebase. Also if you don't know what you are doing you may deform your branch, lose changes, and get frustrated and so on...
What should I choose?
Is a history tree really worth this effort? Is it important like the code base? To be honest, not so much. This is why many companies don't bother using rebase, especially when working with big versatile teams. There is even an easy popular way to achieve clean git history with merge - simply by squashing the merged branch. If you happen to be a geek and love being in control over your code, and organize it to your liking, and your teammates are in the same mindset, you may proceed using rebase.
How do I learn rebase?
The best way to learn it is to open a small repo and practice it, so that you are not be afraid to break anything and you can play with it until it sits well with you. If you use a visual git tool, I don't know if it even supports this feature, as I mostly work with git bash.
Your workflow with rebase would be:
1) put some commits on master
2) open a feature_branch and put some commits on it
3) put some more commits on master
4) get back to feature_branch and use 'rebase master'
What will happen now is this (you changed the base of your branch aka re-base):
5) Now if you get back to master and merge the feature branch you will get this, instead of this:
I don't like it linear because it does not show the feature branch, therefore I add the no fast forward flag
git merge --no-ff feature_branch
The final result is this:
If you repeat this method to every feature branch merge, your master will be nice and tidy.
Beware
You will need to know how to face the following problems:
1) Why am I solving conflicts over and over again???
It is because rebase tries to place commit after commit from your feature branch to the master (like cherry-pick command). Instead of solving your conflicts in a single merge commit, you solve the conflicts one by one. Since the commits contain the delta of the changes, the conflicts can bubble up all the way though all your commits in the feature branch.
Each time you solve a conflict you need to commit the changes and do rebase --continue until the process is done. If you messed up and you are still in rebase, you can abort by using rebase --abort which returns to the state before the rebase.
2) I can't push and pull from my remote feature branch anymore!!!
A branch before rebase is not the same as a branch after rebase. If you pushed it before rebasing you would need to override it by using force push. This command needs be handled with care since it can delete changes. Don't ever force push to master (you shouldn't have permission to), but you can force push to your own feature branch (still don't be reckless and know what it means). If you work on it with other people, or unsure that there are important commits there you can add a safety measure that the force push will fail if there are new changes there:
git push --force-with-lease
3) Why is my tree looking all weird? Where is my branch???
While rebasing you are in a detached head state. Don't worry, the branch will restore once finishing the rebase.
4) OMG, rebase doesn't stop, why are there hundreds of commits I need to solve?
A common mistake is to rebase backwards. You might have tried to put master on your feature branch. Do rebase --abort to cancel.
5) I'm afraid that I ruin my work. Is there something I can do?
You can place a temp tag or branch on your feature branch head before rebasing. That way, even if you finish the rebase and fail (during the rebase you can abort), you can return to your old changes safely.
Hopefully this covers it. I will add about other nice features I use with rebase in a different post, since this one is a bit long anyway.
Good luck!
Comments