In favour of git rebase
Rebasing gets a bad rap for being a destructive procedure that changes the history of your project. But in experienced hands it can lead to a clean and legible record of your app.
In case you've never used git rebase
[↗] before, it essentially allows you to (in the most common use-case) update the parent branch of your current branch and then move your branch's creation to a point after all of the pulled parent commits. Basically resetting your branch to seem like it was just forked from the main branch.
Adding the -i
flag additionally allows renaming commits on your current branch or merging them together (squashing) before the reset happens. This is the part that creates the most controversy - you're basically rewriting your commit history.
Rebasing can cause issues in the wrong hands. I've had junior devs rebase the master branch onto their feature branch, rather than the other way around. And if someone has merged the master branch into their own feature branch before doing a rebase you get all kinds of merge conflicts with previous changes clashing with themselves. If you've got a team that doesn't have fixed rules about branching and merging or teammates who just can't seem to wrap their heads around rebasing then I can understand this would cause you to write off rebasing entirely.
But rebasing has one serious thing going for it - a clean git history.
At my previous job where rebasing wasn't used the git log for a project would be chock full of mini-commits such as 'Fix icon' or 'Remove comment'. Those commits are obviously helpful during development because it's basically a quick save of your work, but down the line no one is going to be searching for the exact moment a line of commented text was removed. These commits are superfluous and just create noise around the important changes. (And lets face it, reading a git log is already difficult enough as it is).
Rebase in combination with squashing allows you to turn this:
- Fix tests
- Add tests
- Remove comments
- Add new icon and fix label placement
- Feature: Add alert banner component
into this:
- Feature: Add alert banner component
with all the code from the original 5 commits contained within one feature commit. This makes it super simple to find a code change in the future because all of the changes for a feature are kept together.
At my current company we just hit our 1000th merge request. If we assume every feature has on average 4 commits and that Gitlab shows 25 commits per page, that's 160 pages of separate commits compared to 40 pages using rebase. I'll let you decide which one you would prefer to navigate through when trying to find the cause of a regression bug.
So, on the off chance you've been persuaded to use git rebase -i
, here are my tips for rebasing without issues:
- Allows checkout and pull the parent branch beforehand
- Rebase your feature branch onto the parent branch (not the other way around!)
- When squashing, the first commit should ideally be the one that remains (is 'picked') and the rest should be squashed into it. You can rename this commit during the rebase, but it's easier to just give the first commit the correct name to begin with
- Use a git UI like GitKraken[↗] which hugely simplifies the process
- When fixing inevitable merge conflicts, always accept the changes from the parent branch and then fix your code after the rebase is done. If there are multiple commits that conflict with your changes you don't want to fix the first one to work with your feature, only for the next commit to come along and conflict with your newly created code. It is far simpler to repair your own work afterwards.