If you’re like most developers, you probably have a development process that looks something like this:
- You make a change to your local branch and push it to a central repository.
- Your teammates pull the changes down and integrate them into their own local copies of the codebase.
- Once everyone has updated their code, you run a series of tests to make sure the changes haven’t broken anything.
- If the tests pass, you create a Pull Request (PR).
- Your teammates review the Pull Request.
- If everything looks good, you merge it to the main branch.
This process works well enough, but it has a few drawbacks. Firstly, it’s quite slow. It can take days or even weeks to go from making a change to seeing it live in production.
Secondly, it’s quite error-prone. It’s all too easy for changes to get lost or overwritten during the code merge process, and if tests are only run after the code has been merged then it’s quite possible for changes to break things that you didn’t even know were there.
Thirdly, code review may take a long time, and merge conflicts may appear. In some cases, two branches may have so many contradicting conflicts that a time-consuming refactoring is required.
That’s where trunk-based development (TBD) and continuous deployment can help.
Trunk-based development is a methodology where developers work directly on the main branch of the codebase (the “trunk”). This means that there are no long-running development branches that need to be regularly merged back into the trunk; all changes are made directly on the trunk and deployed immediately. No feature branches and no pull requests are used in trunk-based development. Feature flags are commonly used instead of feature branches.
Continuous deployment is a practice where code changes are automatically deployed to production as soon as they’re pushed to the main branch. This means that there’s no need for a separate staging environment; changes are deployed to production immediately after they’re pushed to the codebase.
Advantages of trunk-based development
There are many advantages to using trunk-based development (TBD) over other development models:
- TBD ensures that all changes committed to the main branch (trunk) are always in a working state, as every change is immediately integrated and tested. This helps to avoid “Integration Hell” during which various changes conflict with each other and cause the main branch to break.
- The frequent, small commits made in TBD make it easier to find and fix bugs, as there is less code to search through and changes can be traced back more easily.
- Smaller commits also make it easier to review code changes, as there is less new code to review in each commit.
- The close collaboration required by TBD can help to improve communication among team members and build a stronger team spirit. Often pair programming is used to enhance TBD.
- TBD can help to get feedback faster on your change. It reduces the risk of project failure, as any issues are found and fixed more quickly.
- Finally, TBD can lead to faster delivery of new features and improvements, as there is no need to wait for lengthy integration and testing phases. Instead, changes can be released as soon as they are ready.
Disadvantages of TBD
While there are many advantages to using trunk-based development, there are also some potential disadvantages that should be considered.
One such disadvantage is the potential for increased conflicts when multiple developers are working on the same code base. This is because each developer will have their own local copy of the code and changes made by one developer may not be immediately reflected in the other developer’s code base. This can lead to merge conflicts when developers attempt to push their changes back to the central repository.
The solution for this problem would be to push small chunks of code regularly and do a regular pull. This way you will catch conflicts at an early stage when it’s easy to solve. Large commits are not acceptable in TBD.
2. Difficult to implement
Another potential disadvantage of trunk-based development is that it can be difficult to implement in large organizations with hundreds or thousands of developers. This is because each developer would need to have their own local copy of the code, which would require a lot of storage space. Additionally, it would be difficult to manage and keep track of all the different code bases.
Splitting engineers to smaller teams and splitting large applications into microservices and packages helps to solve this problem.
3. Difficult to roll back changes
Finally, trunk-based development can also make it difficult to roll back changes. This is because each change is made directly in the trunk and there is no separate branch for holding previous versions of the code. If a change needs to be rolled back, it can be difficult to identify which change caused the problem and how to revert it.
Despite these potential disadvantages, trunk-based development can be a very effective way to manage code changes and allow multiple developers to work on the same code base without causing conflicts. When implemented correctly, it can lead to faster development times and fewer problems.
One of the characteristics of TBD is no Feature Branches and no Pull Requests as there are no branches to merge. But how do we make sure that nobody messes things up without PR? There is a great tool that helps to solve this problem – pair programming.
Pair programming is a method of programming where two or more developers work together at the same time on the same code. This can be done in person or over a video call.
Pair programming can also help improve communication between developers. By working together, two developers can share knowledge and ideas, and each can help keep the other accountable for following best practices. In addition, pair programming can help reduce the number of potential bugs in a codebase. This can lead to improved code quality.
Pair programming helps to ensure that all code changes are reviewed before they are committed to the main branch. The review goes along with actual coding. Usually, one developer does the actual coding, and the other one does a real-time review and helps with ideas. The code has better quality because there are two pairs of eyes looking at it and it does not need any additional review. That’s why it is often used in conjunction with TBD.
How to implement trunk-based development in your project
There are a few key steps that you’ll need to take:
- Choose the main branch.
The first step is to choose the main branch (trunk) that all developers will work off of. This branch should be stable and should only be updated with the new code that has been thoroughly tested.
2. Use feature flags.
When developers want to add new features, they should use feature flags. This allows them to work on their changes without affecting the stability of the application. By default, the feature flag should be disabled. When the feature is complete and tested the feature flag can be enabled.
3. Merge/pull changes regularly.
The code should be merged into the main branch on a regular basis. This allows everyone to have the latest changes and helps to avoid conflicts. Working on a feature merges small pieces of the change consistently instead of merging the whole feature when it’s complete.
4. Test thoroughly.
Thorough testing is essential in trunk-based development. All changes should be tested before they are merged into the main branch.
5 . Use continuous integration.
Continuous integration is a practice in which code changes are automatically built and tested. This helps to ensure that changes don’t break the build and that they don’t introduce new bugs. You can use tools such as Jenkins to build your pipeline and automate tests.
6. Practice Pair programming with your team.
A pair creates code and reviews it at the same moment. It helps to avoid bad-quality code being merged into the trunk. This is a crucial moment as there is no PR and no PR reviews.
If you follow these steps, you’ll be well on your way to implementing trunk-based development in your own process.
TBD can be scary at first. Before trying it, I was hesitant that it was going to work at all. Pushing your code directly to the main branch without a proper PR process seemed like a crazy idea. What if someone will mess something up and we as a team will miss it? How are we going to roll back those changes? How do we avoid conflicts, working in parallel with the same branch? How do we manage all the feature flags that need to be implemented to avoid some unfinished code will go to production and will be accessible to the user?
But after trying it for one year I loved it. Everything works smoothly. Pair Programming helps to make sure that only good-quality code gets into the trunk. The team became more productive. No back and forth between branches and no big merge conflicts. No long waiting for code review. The code is integrated quickly, and developers get feedback fast. A well-configured continuous integration pipeline helps to catch any code inconsistencies, bugs, and other issues early.
Trunk-based development can be a great way to improve your software development process and development experience. Give it a try in your own environment and see how it can help you!