Accidental journey of moving towards Trunk-Based Development

Leo Chen
6 min readNov 25, 2023

--

Our team recently (well, it was my previous job) started a new project and took the chance to find a git workflow that fits us. This article discusses our journey and insights, hoping to assist other teams.

Initial Approach Adopted

Initially, we used a centralized workflow with a single branch for all changes, pushing directly to it and releasing from this branch to internal testers.

After several months, while our team was content with the centralized workflow, we faced two challenges as the project approached delivery to external users:

  1. Issue with Development Continuity: Nearing a release, a code freeze was needed for quality stability, but this halted further code commits, disrupting the team’s development rhythm.
  2. Challenge with Hotfix Management: Post the release of version 1.0, while working on version 2.0 in the same branch, a critical translation error in version 1.0 required an immediate fix. The dilemma was how to patch this without inadvertently releasing the incomplete features of version 2.0.

We discovered from other teams that to address the Issues with Development Continuity, they create a new branch for ongoing development prior to a release. This approach circumvents the code freeze impact but leads to a proliferation of branches, each needing careful management for code commits.

To solve the Challenge with Hotfix Management, a common approach is:

  1. Rebase the codebase to version 1.0
  2. Provide a hotfix
  3. Build
  4. Release
  5. Return to the pre-step one codebase

The advantage of this method is that you become more familiar with git commands. The disadvantage is that it’s very prone to errors and can be very messy!

Due to these issues, we recognized that the Centralized Workflow was unsuitable for us and explored various workflows online: Feature Branch, OneFlow, Forking, Gitflow, and GitHub. We concluded that no workflow is perfect; the crucial factor is finding one that aligns with your team and product. For teams developing an MVP to test market demand, a simpler workflow is advisable, whereas for products demanding strict error-free processes, the Gitflow Workflow might be more appropriate.

After careful consideration, we felt that our workflow, in addition to solving the Development Continuity and Hotfix Management issues, should also achieve the following two objectives:

  1. Enable anytime, anywhere version releases for quick business response.
  2. Simplify operations by managing a single branch.

Below, we share the workflow we are currently trying.

The Git workflow we are currently trying

Development Flow

Similar to the Centralized Workflow, we will only have one branch, which we refer to as master.

To develop a new feature, we create a dedicated feature branch (e.g., Feature B) and merge it back into the master branch upon completion. This method promotes collaboration, reducing the risk of a future silo effect. However, a drawback is that if the feature branch remains separate for too long, it may significantly diverge from the master branch, potentially resulting in a challenging ‘merge hell’ when reintegration is attempted.

To minimize the risk of difficult merges, we focus in sprint planning meetings on breaking down each story as much as possible, aiming to shorten the lifespan of feature branches. However, sometimes a story may take longer to develop than expected. In such cases, we employ feature toggles to temporarily disable partially developed features.

To illustrate with the above diagram:
We can safely release version 1.0.0.1. Additionally, version 1.0.0.2 is releasable because Feature B, still in development, hasn’t been merged yet, and Feature A, despite partially merged, remains hidden to users via feature toggles, ensuring release safety. Finally, version 1.0.0.3, including both Feature A and Feature B, is also viable for release.

We avoid merge hell through short-lived feature branches, and we achieve the goal of anytime and anywhere release through the use of feature toggles.

Release Flow

The described development process, while effective in some aspects, doesn’t fully address the issue of development continuity due to ongoing code freezes. As a release date approaches, the team tends to be more cautious with code commits, leading to hesitancy in committing many changes, thus impacting our development flow. While feature toggles help in selectively disabling less reliable code, this approach is typically suitable at the feature level and isn’t practical for every bug fix or refactoring.

To further address this problem, we adopt the strategy of creating a release branch as the release date nears. This branch is dedicated to maintaining stability and is used exclusively for significant bug fixes. By implementing a release branch, we effectively bypass code freezes, enabling uninterrupted development at our regular pace on the master branch.

As per the diagram: When the release date was near and our features nearly finalized, we created a branch named release-1.1.x, starting as version 1.1.0.0. This branch’s focus was on enhancing stability, so most updates were bug fixes, leading to versions 1.1.0.1 and 1.1.0.2. The establishment of this release branch enabled ongoing development on the master branch, preserving our daily development rhythm without interruption.

We solved the problem of development continuity through the use of short-lived feature branches and the creation of release branches.

Hotfix Flow

While the release process we implemented resolves the issue of development continuity, it makes the goal of dealing with only one branch unfeasible. The existence of multiple branches necessitates committing code to several branches, an aspect we’re not keen on. To simplify the process, we decided that everyone should commit only to the master branch. We introduced a new rotating role within the team, the release engineer, whose main duty is to manage the release branch. This involves cherry-picking essential changes to the release branch, allowing other team members to focus solely on the master branch.

To illustrate with the diagram above:
For the upcoming release, we initiated the release-1.1.x branch. When a severe bug is found in this branch, the usual practice is to fix it directly in the branch and then cherry-pick it to the master. However, we chose a different approach: developers first commit fixes to the master branch, and then the release engineer cherry-picks these changes to the release-1.1.x branch. This method offers three key benefits:

  1. Achieves the goal of ‘the team only needing to face one branch’, as team members only need to commit code to one branch, and their involvement ends there.
  2. Minimizes Release Errors: Committing changes first to the master and then cherry-picking to release-1.1.x reduces the likelihood of overlooking important changes. The reverse process, where changes are first made to the release branch and then cherry-picked to the master, can easily lead to missed updates. This oversight could result in confusion when an issue fixed in one release reemerges in the next. By standardizing the process of committing to the master first, we ensure that future release branches will consistently include these changes.
  3. Improved Project Awareness: The release engineer’s role in maintaining the release branch and overseeing releases enhances overall project awareness. This responsibility encourages more vigilant monitoring of the project’s timeline. By rotating this role, we also ensure that release-related expertise isn’t limited to just one person, thereby reducing the risk of over-reliance on any single team member.

We solved the problem of hotfix management by creating a release branch. We also achieved the goal of single branch through the role of the release engineer.

Conclusion

This workflow, known as Trunk Based Development, is not unique to our team but is also utilized by major tech companies like Google, Facebook, and Microsoft. It’s highlighted in the book ‘Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations’ as one of the 24 capabilities essential for high-performing teams. According to descriptions, this method lays the groundwork for implementing Continuous Integration/Continuous Deployment (CI/CD) and Lean Experiments. In today’s rapidly evolving digital landscape, such an approach is increasingly crucial. Our aim is to familiarize ourselves with Trunk Based Development and subsequently progress towards adopting CI/CD and Lean Experiments in our future endeavors.

--

--

Leo Chen
Leo Chen

Written by Leo Chen

Hi, I'm Leo, a software engineer with over 15 years of work experience in mobile application development.

No responses yet