There are two ways of doing Trunk-Based Development; the first is by committing straight into master, the second by using short-lived feature branches, this article describes the second one.
2. What is Trunk-Based Development?
A source-control branching model, where developers collaborate on code in a single branch called trunk *, resist any pressure to create other long-lived development branches by employing documented techniques. They therefore avoid merge hell, do not break the build, and live happily ever after.
* master, in Git nomenclature
And we can do it by committing straight into master or, in our case, by using short-lived feature branches:
one person/pair over a couple of days (max) and flowing through Pull-Request style code-review & build automation before “integrating” (merging) into the trunk (or master)
3. Trunk-Based Development in practice
We are going to see now an example on how to use this model, assuming that we have in place a continuous integration workflow similar to the one described in this article that will run some checks whenever we create a Pull Request.
3.1 Start work on a new feature
There is a feature ready to be picked up in the Backlog; we take it.
Features in the Backlog should take a max of two days to complete; otherwise, we should divide them into smaller ones.
We make sure we have the latest changes from master:
We start by implementing the test first and the code later, following a TDD approach.
3.2 Create a Pull Request
We have finished the implementation of the new feature in less than a day ideally, two days max.
We create a short-lived feature branch and commit our changes:
To create the Pull Request, we push the changes with the following command:
As a result, git shows us a link in the terminal that we can use to create the Pull Request on GitHub.
After creating the Pull Request, automated checks run on it.
3.3 Make requested changes
Another programmer/pair has reviewed our Pull Request and pointed out some improvements that we need to do and some flaws we need to correct. We proceed to make the changes, and when we finish, we commit them:
Another programmer/pair has merged changes into master before us. In this case, we need to rebase before we can merge our Pull Request into master:
We resolve conflicts if any, and then push:
3.5 Squash and Merge
All checks pass on the Pull Request, and we got the approval from our peers. Now we click the Squash and Merge button in GitHub to merge the changes into master.
4. Why use Trunk-Based Development with short-lived feature branches?
By following this model, we take a more continuous delivery approach to software development, with short-lived branches, we can release new features quickly while avoiding merge hell.
For unfinished work, we can use feature flags to keep incomplete features hidden until all the necessary code is shipped.
We keep master green and deployable at all time by making sure that before merging a Pull Request, we always run automatic checks: build, validate code formatting, run tests, measure code coverage, etc. These are just examples of checks you may run, depending on your needs.
Also, having a code review from another programmer/pair before merging any changes into master might help us to find possible problems that the automatic checks can’t find.
In this article, we have looked at how to use Trunk-Based Development with short-lived feature branches. I’m not saying this is the best branching model. There are other models like GitFlow, GitHub Flow, Trunk-Based Development committing straight to master, which might work better for you depending on the project you are working.
It’s always good to try different models until you find the one that works better for your team.