Beware: opinions ahead.
Principle 1: All commits from the main
branch should be deployable
Need to roll back Production? Where should I roll back to? When commits are squashed, it’s reasonably easy to see what to do: go back one commit and re-deploy. When commits are not squashed it becomes harder to see where the last “good state” was – were there commits from the last PR that were good, should we revert everything? When squashing commits this search simply isn’t necessary.
Principle 2: Pull Requests should contain a single, cohesive piece of work
If we follow Principle 2, then after the PR is merged there should be no need to deal with different parts of it separately. It should be treated as a unit. The simplest way to enforce this rule is to cram all of the changes into a single commit once it hits main
.
Principle 3: Development should allow for experimentation
I’d like to be able to try out multiple approaches on a branch, iterate on my solution, and incorporate feedback without force-pushing, rewriting Git history, or engaging in anything potentially complex in managing my Git history. I’d like to see CI run and fail, and be able to handle the consequences without worrying about polluting main
. When I’m reviewing code, dealing with a force-push divorcing my comments from the code they were about can be disconcerting. Development branches should be allowed to be the Wild West, but we want to contain that chaos. The best way to keep it contained is to squash the final result before applying that to main
.
Principle 4: Rebasing from main
should be a simple process
When I want to rebase from main
, I don’t want to walk through every single commit made by every other developer. I want to apply the PRs as units and deal with the consequences. Rebasing every little commit from every development branch is a waste of time and energy, especially for commits that were eventually walked back.
Principle 5: Merging from main
should not pollute the history
Sometimes rebasing is more of a pain than it’s worth. I want to be able to merge main
into my branch without worrying about generating a big ugly merge commit that then becomes visible on main
after merge. This is related to development branches needing to be a bit wild west, but it’s important: I’ve seen developers waste days on a rebase when a merge would have been 10 times faster. We should take whatever velocity gains we can. Git is a very smart merge tool – why give up that advantage?
Conclusion
Squashing merges helps the whole development team move faster. It’s worth enforcing this merge strategy on repositories across the organization.