Trunk Based Development
Overview
Trunk based development as a philosophy asserts the value of a single source of shared truth, the ' Main Branch' or 'Trunk' previously referred to as the 'Master' branch. Throughout the duration of this document, we will use the term 'Main'.
Any changes made by the team must be committed to the main branch in order to 'exist'. Think of it this way- if you spend hours fixing a bug and don't commit to Main, it doesn't matter if you've come up with the most brilliant fix possible, because there is no way for the team to functionally draw from the work you've done. In fact, by hoarding your code changes, you may have created incompatibilities with whatever solution the team may have come up with in the interim. For further discussion on why we have moved away from Git Flow, please click here.
Again, we use the Main as a shared resource so we can appropriately respond to the new logic created any time someone merges their changes. Appropriately, the 'value' of a branch shifts as well; the onus is now on committing to main as frequently as possible so that the whole team can share their successes together. This means we don't wait for perfection, shared, incremental progress is the goal.
Practice/Application
We practice trunk based development overall, with most teams
using short-lived feature branches that flow through pull-request style code-review. This means that
from a Engineer's perspective, we basically
use GitHub Flow with the addition
of explicitly naming your branches feature/*,
bugfix/*,
etc. and a few changes to address process flaws
with GitHub Flow (see below). For
the purpose providing better consistency of branch naming and to make deployment definitions easier
to write and integrate, in addition
to GitHub Flow, we also adopt some
conventions from the classic Git Flow as a way of keeping processes consistent. For
more information on why we use trunk based development instead of Github/Git Flow, see the "
Alternatives" section at the bottom of this document.
Requirements
- Git tags are used to signify release versions
- No commits directly on release branches
- Hotfixes to release branches are cherry-picked from Main
Releases and Cherry-picking1
If you are fixing bugs on the release branch and merging them down to the trunk you are doing it wrong. There is a chance you might forget to merge it down, and then there is going to be a regression at the next release moment (fresh branch cut from the trunk). Then egg on face, and recriminations.
Bugs should be reproduced and fixed on the trunk, and then cherry-picked to the release branch. A build should happen from that, a second confirmation that the issue has been remediated, and that deployment should go live (perhaps a point release). If you can not reproduce bugs on the trunk ( truly rare), then you have permission to go ahead and reproduce it on the release branch, fix it there, and merge back.
Priorities
- Feature branches are short-lived; ie deleted once merged to Main
- Trunk/Main is always release ready

How to Make a Code Change
How to develop a new feature
-
Engineer fetches latest code
-
Engineer creates a feature branch of the latest of the trunk
-
The Engineers adds commits to the branch, running CI on each commit
-
The Engineer creates a Pull Request to get their changes reviewed,
- CI Success required prior to integration
- At least one pull request approval,
- two on larger or more complicated projects
- Once PR complete, code is merged to Trunk
How to create a bug fix
-
Reproduce the bug on trunk/main
-
Engineer creates a feature branch of the latest of the trunk
-
Create a commit to trunk/main that implements a test for the bug, and fixes the bug.
- If no test was written that reproduces the bug, and no test previously found the bug (because it passed CI before getting merged in the first place), CI for these changes do not test that the bug was fixes unless a new test that covers the bug
-
The Engineer creates a Pull Request to get their changes reviewed,
- CI Success required prior to integration
- At least one pull request approval,
- two on larger or more complicated projects
-
Once PR complete, code is merged to Trunk
How to Release the Latest Code
How to release from trunk
- Create a git-tag with the release version on the latest commit to release
How to patch a release without an existing release branch
-
Engineer fetches latest code
-
Engineer creates a feature branch of the latest of the trunk
-
Engineer adds a commit that fixes the bug in production
-
The Engineer creates a Pull Request to get their changes reviewed,
- CI Success required prior to integration
- At least one pull request approval,
- two on larger or more complicated projects
-
Once PR complete, code is merged to Trunk
-
Engineer creates a release branch from the latest deployed tag
-
Engineer cherry-picks bugfix commit from Trunk to the release branch
-
Engineer applies new git tag to latest commit on release branch
How to patch a release with an existing release branch
-
Engineer fetches latest code
-
Engineer creates a feature branch of the latest of the trunk
-
Engineer adds a commit that fixes the bug in production
-
The Engineer creates a Pull Request to get their changes reviewed,
- CI Success required prior to integration
- At least one pull request approval,
- two on larger or more complicated projects
-
Once PR complete, code is merged to Trunk
-
Engineer checks out the relevant release branch
-
Engineer cherry-picks bugfix commit from Trunk to the release branch
-
Engineer applies new git tag to latest commit on release branch
