What’s the alternative to complex branching and pull requests? Trunk-only development drives practices such as testing, incremental development, and branching by abstraction. It also improves communication within the team.
I recently had an exchange of words with a “devops developer”, who was absolutely appalled by the fact that our team didn’t use the Gitflow workflow. In his world, developing software without branching from branches was absolutely impossible and people who did it should be sentenced to the sixth level of Dante’s inferno asap… or so I understood his position 🙂
As always, there’s a time and place for everything, and having a structured, documented, and globally accepted standard for branching is fantastic… for large codebases distributed across many teams and timezones. One can only applaud. For a codebase maintained by a few individuals who interact with each other eight hours a day, this type of approach is mostly cumbersome overhead. But that is not what this post is about.
Having started my revision control practices with tools like
co (anyone even remember those?) and then CVS, I have seen my fair share of merge hell. I also have tons of stories “from the trenches” of branching going wrong and weeks of work being wasted. But that is not what this post is about either.
Instead, I will share, what I consider to be, the advantages of trunk-only development. First, I’m stating my bias: trunk only development is a tool for optimal programming for continuous deployment, meaning, that properly done it’s a critical enabler of a workflow that enables tens or even hundreds releases into production every day. How come? Trunk-only development in conjunction with continuous deployment is quite unsafe—whatever you push will go into production—which means that a number of practices must be strengthened to make it work.
To feel safe you need tons of tests: unit tests, integration tests, end-to-end tests, you name them. If you want to feel safe committing your code to production, you’ll no doubt write as many tests as you need to get to that feeling of safety. My experience is that teams that do trunk-only development are great at writing all sorts of tests. While nothing prevents good test practices when branching around, the feeling of delay and a few pull requests while you’re at it usually result in worse test suites, in my experience, at least.
Incremental Development: Small Commits (pushes)
I’ve been around for long enough to call what git calls a push a commit. Nevermind. The point is that trunk-only developers usually want to touch as little as possible to avoid large commits (pushes). Since they simply want to know what they’re pushing to production, they’ll typically do one push per refactoring. Not only does this produce razor-sharp commit messages, it also turns development into a sequence of tiny well-executed steps toward the final functionality. The opposite is to throw everything up into the air, refactor and add the new functionality, and rely on the test suite. It works. For sure. But being able to break development into small steps is a skill in itself, because it keeps you more in control.
Branching by Abstraction
Branching by abstraction and feature toggling is a prerequisite for trunk-only development. At the end-of the day, you do want the users to get a full feature, not the thirty increments that it consists of. What’s absolutely fantastic about branching by abstraction is that it enforces architectural stringency; you have to be able to isolate the functionality you’re changing or adding so that it can be replaced and/or toggled on. This prohibits certain constructs from ever emerging in your codebase. And it’s driven by trunk-only development…
Communication and Cooperation
Given that a team wants to use trunk-only development to release code frequently, it cannot throw pull requests around for every single teeny tiny change. That would result in too much interruption. Instead, such teams go back to basics and rely more on pair programming and communication, structured code reviews, and design meetings. To be fair, this is more a consequence of abolishing pull requests, but it stems from the intention to avoid pull requests.
What About Manual Testing?
It’s neither controversial, nor a bad idea to have a feature branch undergo manual testing. The same applies to trunk-only development, but it happens when a feature is about to be toggled on. No difference.
Branching from branches to develop code may work in large settings with hard demarcation lines. Trunk-only development drives a number of good practices that every programmer and team should master.