I hate squash and merge with a burning passion
Now, let’s be perfectly clear. Using git merge --squash
is not always a bad thing, the premise being that
- you have a branch with a bunch of garbage WIP commits;
- you can edit the default commit message and write something non-terrible.
But let’s be real. We already had a tool for squashing garbage
commits: it’s called git rebase -i
. Just fix up the garbage
commits, because surely if you have made a change non-trivial enough to
require WIP commits, it can’t be trivial enough to fit in a single
commit, now can it?
But git merge --squash
is not the target of my ire
today. No. It is GitHub, and it is the people who enforce only
using the squash and merge option on pull requests.
Listen. The only reason I have ever heard for enforcing squash and
merge is “it makes for a cleaner commit history”. Cleaner my foot. The
only way to have a good commit history is to commit with intention and
rebasing to clarify and clean up. Squashing will not get you there.
Sure, your two-thousand line diff is now compressed in one commit with a
terrible message like refactor backend
, rather than ten
commits with even worse messages like wip
and
done
and oops
. But that is still a terrible
commit history, only now the terribleness is compressed in less
commits.
Worse, squashing will actually delete any commits made with intention. And unless you really expect every commit to be a PR, which is patently ridiculous, you are actually removing good history and actively making it worse.
Furthermore, say you want to squash and merge and actually have a good commit message. Suppose you rewrite the entire commit message or whatever. A good commit message has appropriate line wrapping, something my editor (vim) is perfectly capable of handling properly. GitHub does not even give a whit of an indication when a line is too long. So you can’t even write a proper commit message. Ridiculous.
So what should you do? Just merge. Merge like a normal person.
git merge --no-ff
This makes a merge commit even when you could have fast-forwarded, because it explains why you are merging a certain feature.1
While I’m at it, GitHub pull requests are a disaster. As usual, the Linux Kernel is the gold standard.
When you want to merge feature
into master
you should run git merge feature
while in the
master
branch. And obviously you take care of any merge
conflicts in this merge. In particular, you do not “back merge”
master
into feature
without good
reason because
Merge branch 'feature'
Merge branch 'master'
is a really stupid commit history! But GitHub, especially with a lot of its automated CI/CD stuff encourages maintainers to put the responsibility of fixing conflicts on the people writing the PRs. So now the only thing they can do is rebase on top of master, and then re-test every commit because otherwise they’d be lying.
If you want to fast-forward, that is also fine, but in my opinion the times you should fast-forward are precisely the times when you should rebase. Yes, a fast-forward merge and rebase are identical, but it really “belongs” with rebasing.↩︎