GitHub allows us to lock down who gets to commit to branches, and one easy way of using that is to disallow commits straight into the main/master branch. Because that forces all code to be code-reviewed, so only approved changes will land, and that'll mean all the changes are safer… right?
No, I'm here to argue that the impulse to increase safety by enacting more technical limitations is actually wrong, because the problem of changes being risky is fundamentally a people problem, is often theoretical, and adding technical limits reduces a team's ability to experiment. At the end of the day heavy change management processes lead to worse business outcomes, and I'd like to explain why branch limits adds more weight than one might suspect.
There is a caveat: There can be valid reasons to protect a branch, e.g. for compliance or legal reasons, or you might have a contributor-centric workflow where trust on the committers are low (e.g. open-source). But for the majority of medium-sized projects I think it's worth considering the drawbacks of enacting these limits.
My first point: How serious is the problem actually? How often is main branch broken? In principle a broken main is a crucial signal as it is an inability to deliver value to customers, so it is important a team takes it seriously. If a team doesn't care to keep their main branch green then there is a fundamental culture problem, and it won't be solved with a branch protection feature. As a basic principle main must be green.
But, that said, do you actually have a problem if main breaks? What an odd thing to ask after saying "main must be green", but what if the broken build gets fixed a minute later? What if main is broken for just a few minutes per month in total? What if the team consistently fixes the failing build quickly, and work to prevent it from happening again? In this case maybe the team is trying out ways of working faster, and the rare broken main is them finding a weakness which they then fixed… I mean, you don’t learn to run without falling, so the rare broken main can actually be a positive sign that the team is experimenting with ways to work even faster.
If that's the case it would be harmful to enact branch limits.
At the end of the day everyone benefits from a flexible, simple change management process that's as free of hard restrictions as possible. For example,
- Consider a simple typo, why should there be any friction in landing such a fix? It'd be a huge waste of everyones time to use a pull-request workflow just to fix a typo! It should literally just be “commit & push”.
- Or maybe a team makes a change together, why shouldn't that change just land in main? Since the team wrote it together there are no advantages to requesting a review, it'd just be pointless ceremony.
- Or you might be on call and see a trivial error that just needs an obvious fix. If you have high confidence in the change why shouldn't it just land? I trust you to take care of the system and so I trust your judgement call, if you believe a main-commit is safe then go for it.
Now, of course if main does actually break too often then the team should have conversations around that (it'd be an obvious topic for retrospectives). If a team reflects on why they keep breaking main I'd be shocked if they don't identify several ways to enable safer and speedier ways of working. I've seen teams slide a bit into unsafe "forgetting to run tests before pushing to main"-territory causing a few trivial broken builds, and that's a laziness that's most easily remedied by being better professionals. I mean, running tests before committing is a pretty low bar! 😅
It's not all about practical drawbacks either, it's also worth highlighting that restricting main-commits sends a signal that developers can't be trusted. That is a strange and difficult dynamic to emit into a highly-paid group of professionals. I’ve seen plenty teams with no branch protections keep main fully green and I think it's much nicer to have that result come from a place of trust than by putting hard gates in the their way.
The ideal change management process is as lightweight as possible, fundamentally designed to create and nurture a high-trust environment. I mean, yes we want as much automation in there as possible, but we need to be careful not to add rules and restrictions that can pointlessly slow us down. Teams should be encouraged to continuously experiment and refine their ways of working, and tools and heavy processes should do their best to not get in the way of that.