Why Squash is the Best Way to Merge

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s