This essay is part of the series "Strong Opinions, Moderately Held", an indefinite journey into thoughts, ideas, and convictions regarding a plethora of subjects.

There are many ways to work with a version control system like git branches. Over the years I've developed a strong preference for rebasing my feature branch on the master [1] branch and then squashing it into a single commit on the master branch. I prefer it over the alternatives to the point that I tend to disable the possibility to perform normal merges on my Github/Gitlab repositories.

There are several upsides to this approach, but I'll delve into my favourite three that can be summarized as Tidy, Focused Noise Reduction.

Tidy

The master branch is kept clean and tidy. Any single commit will be a coherent, cohesive change of the code. This might at first glance seem like an aestehetic choice, but I find it making sense of the sequence of code changes applied and deployed to production much, much easier.

Focused

The meandering path that a feature branch takes to its completion is replaced with a single commit where the relevant changes are described in sufficent detail. When pushed into production, there's really no inherent difference between a tiny commit directly to master and the many commits of a feature branch. What matters is that the actual code changes are described well enough to make sense of them weeks or months later. The individual commits aren't what we should be interested in, but rather the resulting code changes. If these are made as a single commit or ten has more to do with the development process than being a boon to the archelogical developer debugging something gone astray.

Noise Reduction

However, there is indeed a valid point to be made for a single, huge commit making life very hard indeed when it comes to future troubleshooting. As this is a very common argument against squashing commits I'd like to point out that that argument is misguided and orthogonal to prefering a single squashed commit over merging. The real problem has to do with size, the huge part of that argument. Large code changes are always problematic and by squashing commits this becomes evident rather than being hidden among the twenty or so commits usally being merged at once into master.

Feature branches and hence squashed commits to master must be kept relatively small in size and focused to enable future understanding and troubleshooting. As an added bonus, this lends itself really well to the deliberate practice of separating structural and behavioural code changes into separate commits and branches [2].


  1. Or main branch as some call it. Whatever the name, the branch of interest here is the one being used to deploy code changes to production. ↩︎

  2. Kent Beck describes this practice in SB Changes ↩︎