DevOps is a patchwork quilt of practices, tools, philosophies and concepts. We’ve covered a few of these—like continuous integration and continuous delivery—recently, and in this post, we’re going to take a deeper dive into one of the strategies that make the CI/CD approach so effective.
Let’s talk about trunk-based development.
What is trunk-based development?
Trunk-based development (TBD) is a type of branching model used in software development.
With TBD, developers merge every code change they make—from a small fix or a whole new feature—into the central, shared branch of code.
You can visualise the version control system as a tree, where the primary repository is represented by the trunk (often referred to as the “main” branch), and individual developers create their own branches that branch off from the main branch to work on their respective tasks.
Merging code changes with the main trunk in smaller, more frequent instances cuts down on the complexity that often comes with executing large code merges. These little-and-often merges help streamline the development process, making testing and fixing bugs easier and ensuring the code is as up-to-date as possible at any given time.
How does trunk-based development fit into DevOps delivery?
If the idea of making small and frequent code commits to a shared repository sounds familiar, it may be because trunk-based development is a key part of continuous integration.
Continuous integration is, essentially, the combination of TBD and automation. If you’re using TBD alongside automated building and testing tools that check code after every commit then congratulations! You’re doing CI.
The TBD approach facilitates CI by fostering a process where developers merge their code with the main trunk several times a day.
This method of branching also paves the way for further phases of the DevOps pipeline, such as continuous delivery and continuous deployment. With developers committing, testing, and fixing code constantly in small increments, there’s always a release-ready build on hand that can be deployed into production.
How does it differ from feature branch development?
So how is trunk-based development different from other common branching methods, like the popular feature branch development method?
Let’s revisit the tree analogy for a second. With feature branch development, the secondary branches that spin off the main trunk, where developers are working on their code in isolation are merged less frequently; often not until the feature or code change is considered to be finished. It can often be weeks, or even months, before a feature branch is ready to be merged with the trunk.
As a result, these feature branches can become long and unwieldy, causing issues when they come to be merged back into the mainline where code could have changed since their branch was created. This method also generates siloes among developers, as they can’t see what their colleagues are working on, potentially creating overlap or compatibility issues that aren’t discovered until later.
But with TBD, branches of code (known as release branches) are kept small and agile and are merged into the trunk and subsequently deleted every few hours.
TBD breaks down the process of integrating and testing code changes into more manageable chunks, so that it can be done more regularly. This means teams can find and fix bugs more quickly and get working code out into production faster thanks to a reduction in the potential bottlenecks (like cumbersome code reviews or pull request analysis) that can occur during big code merges.
Why use trunk-based development?
We’ve touched on a few reasons why trunk-based development is considered by most modern development teams as the best branching strategy to use.
The number one reason is simple: if you want to adopt DevOps, trunk-based development is essential. Other, more traditional methods of branching just don’t cut it in a streamlined, speed-focused DevOps pipeline.
Here are the benefits that TBD brings to your software development process:
Speed: Strong, short feedback loops mean issues are addressed quickly. Developers can integrate and test their code in small chunks, and fix any bugs fast. Although pull requests can still be used with TBD, they’re not necessary, meaning lags are reduced.
Team cohesion: Regular merges mean changes are visible to the entire team, enabling more frequent feedback and promoting consistent collaboration between developers—rather than having them spend long periods of time working on individual branches.
Easier refactoring: With code broken up into smaller portions, fixing issues or refactoring code after testing becomes less of a hassle. And because it’s quicker and easier to carry out on bite-sized sections of code, refactoring is more likely to be done well, improving the overall quality of the product.
Lower risk of merge issues: Merging several feature branches of code that have potentially been worked on for weeks in isolation at once is a recipe for, if not disaster, then at least a headache. Making small commits periodically and testing diminutive amounts of code on a rolling basis is far less likely to result in major collisions. Anything that might break the build is found quickly, rectified, and retested before it can cause bigger issues. Throw all your team’s code changes together at once, and there’s a greater chance that something that requires significant time and resource to fix will crop up.
Use cases for trunk-based development
It’s worth noting that, like every development methodology, there’s a time and a place for TBD. Trunk-based development undoubtedly speeds up the software delivery process. It also puts a lot of faith in the developers that use it not to break the build.
For this reason, TBD is more suited to certain development projects than others. Experienced developers creating a SaaS product from scratch and looking to get a release out as quickly as possible are perfectly suited to TBD. SaaS products work especially well with TBD, as there’s typically an expectation that these kinds of applications will be updated regularly.
However, tasks that involve a wider range and greater number of people, such as open-source projects, may find that the trusting nature of TBD can lead to issues.
Best practices for succeeding with trunk-based development
Trunk-based development is a crucial part of adopting DevOps. But the work doesn’t stop once you’ve got your regular commit rhythm nailed down.
DevOps is all about constant learning and continuous improvement—learning as you go and making your process and your pipeline better all the time.
We’ve pulled together some trunk-based development best practices to get you off on the right foot.
Develop code in small batches. This might be a new concept for your development team, so be sure to support them through this organisational change and communicate the expectations that come with it. Encourage your team not to get carried away and put off merging their code.
Merge branches to the trunk at least once every 24 hours
Consistency is key. To reap the benefits of TBD, you need to be integrating release branches with the trunk often. The exact cadence of your commits will depend on the size of the project, and the number of developers on your team, but a few times a day is a good rule of thumb.
Implement code reviews Code reviews can massively improve code quality and long-term maintainability. Add a step to your CI pipeline for developers to conduct synchronous code reviews, and make them a priority so that merges aren’t held up.
Automate testing TBD is only half the equation when it comes to continuous integration. Implementing robust automated unit testing is vital to creating an effective CI pipeline, and making sure your team is actually benefiting from the TBD approach—there’s not much point in making regular commits if code is waiting forever to be tested.
The same goes for your build process. These tasks should be automated and optimised so that building and testing are done in minutes; allowing developers to tackle errors while they’re fresh.
Minimise your active branches Aim to have just a handful of active release branches at any one time to help achieve your goal of small, regular commits.
Give feature flags a try Feature flags (or feature toggles) allow developers to use code to switch functionality on and off within an application without deploying new code. By wrapping sections of code in feature flags, developers can toggle functionality on and off automatically, if certain conditions are met.
This means features can be committed but even if it’s not ‘live’, and reactivated later when the application is in production, giving developers more control over functionality, and the ability to roll out new features further down the line without deploying new code.
Getting started with trunk-based development
- Set up a single branch as your trunk
- Divide code and commit it in small batches frequently and reliably
- Don’t use feature branches unless you really have to, and if you have to, merge them into the mainline as often as possible
- Test (using automation), review, gather feedback and correct any errors
Optimise your DevOps practice with RiverSafe
Our DevOps consulting services have been designed to match where you are at in your DevOps journey. From just starting out, to a fully integrated DevOps practice, our experts can help you to improve the efficiency of your software delivery process. We work closely with you to understand your unique requirements and implement solutions, tools and processes to deploy applications quickly and securely.
We’re trusted by some of the world’s biggest companies to help improve the efficiency of their software delivery process through the adoption of DevOps.
Find out how we can help you get started with continuous integration, wherever you are in your DevOps journey.