How to Implement Trunk-Based Development: A Practical Guide


What is Trunk-Based Development

What is trunk-based development?

Trunk-based development is a software development strategy where all developers commit code changes to a single shared branch, known as the “trunk” or “mainline,” rather than working in separate branches for extended periods. This approach minimizes the complexity of merging code and aims to accelerate development by encouraging small, frequent commits to the main codebase.

If you’ve spent your career managing complex software projects using git-flow or feature branches, you will likely see your blood pressure reduced and life expectancy increased by moving to trunk-based development. This blog will explain why.

And in case the tongue-in-cheek tone of the post wasn’t clear, there are always good reasons to use other merging techniques other than TBD. There is never only one good technical solution. But in our experience, TDB is the preferred approach when velocity and risk mitigation are the goals. If you disagree, let us know! We’d love to chat.

Elements of Trunk-based development:

  1. Short-lived Feature Branches: If feature branches are used, they are kept very short-lived (e.g., hours or a day, but not more than a couple of days) before being merged back into the trunk. This reduces merge conflicts and integration challenges.
  2. Continuous Integration: Developers frequently integrate their changes into the trunk several times a day. This practice is supported by automated builds and tests to ensure that the new code integrates smoothly with the existing codebase.
  3. Feature Flags: Instead of using long-lived branches to manage the release of new features, trunk-based development often uses feature flags (also known as feature toggles) to enable or disable features in the application. This allows features to be merged into the trunk even when not ready to be released to end-users.
  4. Regular Releases: The trunk is always in a releasable state, enabling teams to release new software versions quickly and efficiently.

By minimizing the divergence between developers’ working copies and the main codebase, trunk-based development helps reduce integration issues, improve collaboration, and accelerate the delivery of functional software. A very positive side effect is fewer grumpy developers.

Trunk-based development vs feature-based development

Feature-based development, sometimes called a ‘feature branch’ workflow, involves creating a dedicated branch for each new feature, bug fix, or enhancement. Its key aspects include

  1. Long-lived Feature Branches: Unlike the short-lived branches in trunk-based development, feature branches in this methodology can exist for longer periods, allowing for more substantial features or changes to be developed, tested, and reviewed in isolation before merging.
  2. Isolation of Work: This approach helps isolate development work, potentially making it easier to manage and track changes specific to a feature. It also allows multiple features to be developed in parallel without interfering.
  3. Merge Considerations: Upon completion of a feature, the feature branch is merged back into the main branch. Depending on the length of time and the divergence from the main codebase, this merging process can be complex and require significant effort to resolve conflicts. Scars and bruising from fighting the build system are not uncommon.

The primary difference between trunk-based and feature-based development lies in how they manage code integration and the lifespan of branches.

Trunk-based development promotes frequent integration and short-lived branches to minimize merge complexities and ensure a stable, deployable mainline. Feature flags allow unfinished code to be merged into the main branch without risking poor user experience or nuclear fallout.

Feature-based development allows for more extended development cycles within isolated branches, potentially leading to more significant merge efforts but providing a clear organizational structure for concurrently working on different features or projects.

Trunk-based development vs. Gitflow

Gitflow is a specific branching model for managing software development. It was introduced by Vincent Driessen in 2010 and is designed to provide a robust framework for managing larger projects. Gitflow is more prescriptive, or opinionated than many other development workflows, specifying a set of branches for different purposes and how they should interact.

Key Elements of Gitflow:

  1. Master Branch: This branch stores the official release history, and the code here reflects the production-ready state.
  2. Develop Branch: Acts as an integration branch for features. This is where all the feature branches merge back, and it contains the project’s complete history.
  3. Feature Branches: Branch off from the develop branch. Each feature branch is meant to work on a specific feature or improvement. Once the work is completed, the feature branch gets merged back into the develop branch.
  4. Release Branches: Branch off from the develop branch once enough features for a release have been completed. The release branch is used for final bug fixes and preparation for a release. After release, it is merged into the master and back into the develop branch.
  5. Hotfix Branches: These are used to quickly patch production releases. They are the only branches that branch off from the master. Once the fix is complete, the hotfix branch is merged into both the master and the develop branch, ensuring that the fixes are applied to the next release.

Differences Between Gitflow and Trunk-Based Development:

Branching Strategy: Gitflow uses a more complex branching model with specific branches for features, releases, and hotfixes, while trunk-based development primarily focuses on the trunk (main branch) with occasional short-lived feature branches.

Integration Frequency: In trunk-based development, developers frequently merge changes to the trunk, promoting continuous integration and testing. In contrast, Gitflow allows for more extended periods of development in isolation before integrating changes, which can delay the detection of integration issues.

Release Preparation: Gitflow explicitly separates release preparation from regular development work through the use of release branches, whereas trunk-based development relies on the main branch always being in a releasable state, with features toggled off if not ready.

Hotfixes: Both methodologies handle hotfixes differently; Gitflow has a specific hotfix branch that merges into both master and develop, ensuring fixes are propagated promptly. In trunk-based development, hotfixes would be applied directly to the trunk and then deployed.

gitflow workflow diagram

Credit: https://nvie.com/posts/a-successful-git-branching-model/

Why developers shift from standard workflows to trunk-based development

Developers have shifted towards trunk-based development for several reasons, primarily driven by the need for faster, more efficient, and more reliable software delivery processes. It also helped that no one wants to spend the waning years of their life in a losing battle with git merge conflicts.

why feature flags are better than branches

The benefits of trunk-based development

You’ve probably gleaned by now that trunk-based Development is an increasingly common development method with many followers worldwide. Why? Here are the most important benefits of this practice:

  1. Adding changes quickly and efficiently. The trunk-based branching strategy allows for continuous integration of changes into the main branch, reducing the risk of bugs and integration issues.
  2. Easily deploying new software versions. Trunk-based development enables the deployment of new versions directly from the trunk, simplifying the release process.
  3. Smaller and easier code review. Small, incremental changes lead to more manageable code reviews, improving bug detection and code readability.
  4. One codebase for testing. Utilizing a single codebase for development and testing simplifies the testing process and minimizes the number of test environments.
  5. Increase speed and frequency of delivery. This approach allows for rapid and frequent updates, allowing you to gather early feedback from selected users and swiftly make necessary adjustments.

How TBD works for small teams vs large teams

While the core principles of TBD remain consistent across team sizes, the implementation details can vary between small and large teams to accommodate different challenges and dynamics.

Trunk-Based Development in Small Teams:

Direct Collaboration: Smaller teams benefit from direct and frequent communication, making coordinating changes and integrating changes easier.

Simplified Processes: With fewer developers, the process can remain relatively straightforward, minimizing the overhead of managing branches and merges.

Rapid Feedback Loops: Small teams can adapt quickly based on feedback from CI processes and peer reviews, ensuring issues are addressed promptly.

Trunk-Based Development in Large Teams:

Scaling CI/CD: Large teams may need to invest in more robust CI/CD pipelines to manage the increased volume of commits and ensure that the build and test processes are efficient and scalable.

Branching Policies: While still maintaining the principle of short-lived branches, larger teams might need more structured policies to manage the integration process and avoid bottlenecks.

Feature Flags and Modularization: Large teams often rely more heavily on feature flags/toggles and modular architecture to handle the complexity of multiple features being developed simultaneously. This approach allows them to decouple different parts of the system, enabling more independent development and testing.

How to implement trunk-based development

Implementing trunk-based development (TBD) requires a strategic shift in how your team approaches version control and collaboration. It aims to streamline the development process, reduce integration headaches, and improve code quality. Here are some things to keep in mind when implementing TBD:

Prerequisites for Implementing TBD

  1. Version Control System: A robust version control system like Git is essential. Ensure all team members are proficient in its use.
  2. Continuous Integration (CI): A CI system should be in place to automatically build, test, and verify the code in real time as changes are committed.
  3. Automated Testing: A comprehensive suite of automated tests is crucial for catching issues early and ensuring that changes do not break existing functionality.
  4. Feature Flags: Implement feature flags to manage the visibility and release of new features without impacting the main codebase.
  5. Team Buy-in: Ensure all team members understand the benefits and practices of TBD. Training or workshops might be necessary to align everyone’s approach.

Steps for Implementing TBD

  1. Consolidate to One Branch: Transition all development work to a single branch, often called ‘trunk’, ‘main’, or ‘master’. This branch should be the project’s source of truth.
  2. Frequent Commits: Encourage developers to commit small, incremental changes frequently. This practice reduces merge conflicts and integration issues.
  3. Peer Reviews: Adopt a code review process to ensure quality and share knowledge across the team. Every commit should be reviewed before it merges into the trunk.
  4. Automate Processes: Leverage your CI/CD pipeline to automate testing, builds, and deployments. This automation ensures that the trunk is always in a deployable state.
  5. Monitor and Optimize: Regularly monitor key metrics such as build times, test coverage, and deployment frequency. Use this data to improve your processes continuously.

Using Feature Flags in trunk-based development to overcome Common Challenges

Implementing trunk-based development (TBD) can significantly streamline your development process, but it’s not without its challenges. Here are some common obstacles teams might face during its implementation, with a focus on issues that can be mitigated through the use of feature flags:

  1. Managing Incomplete Features: When multiple developers commit to the trunk, incomplete or experimental features will enter the main codebase. This is a feature, not a bug, of TBD. But it can disrupt the stability of your application if you don’t manage it.Solution: Feature flags can help by allowing teams to merge code for incomplete features into the trunk without exposing these features to all users. This way, you can continue developing and testing in production-like environments without affecting end-user experience.
  2. Feature Interaction Complexity: As more features are developed concurrently and merged into the trunk, the interaction between these features can become complex, leading to unforeseen bugs or issues.Solution: Feature flags enable selective activation or deactivation of specific features or groups of features, allowing developers to isolate and troubleshoot interactions in a controlled manner. This focused approach can help identify and resolve conflicts or dependencies more efficiently.
  3. Rollback of Problematic Features: Even with thorough testing, new code can sometimes cause issues once deployed. Traditional rollback processes can be time-consuming and risky, especially under pressure.Solution: Feature flags offer a quick mechanism to disable problematic features without rolling back entire deployments. This capability allows for targeted action against the issue, minimizing disruption and reducing the scope of impact.

Best Practices for Implementing Trunk-Based Development

Implementing trunk-based development (TBD) effectively requires a blend of cultural shifts, process refinements, and strategic use of tools. In addition to automation and collaborative programming practices, here are a few more best practices to consider:

  1. No Junk in the Trunk: Ensure that the trunk always remains stable and deployable. This involves having rigorous testing protocols in place and a culture of accountability where developers are committed to maintaining the trunk’s health. Encourage developers to run local tests before committing and to prioritize fixing broken builds immediately. This approach helps maintain a robust and release-ready mainline.
  2. Small, Frequent Commits: Encourage developers to make small, manageable commits rather than large, infrequent ones. This reduces the complexity of merges and helps identify and isolate issues quickly. By breaking work down into smaller chunks, developers can integrate changes more frequently, facilitating easier peer reviews and quicker identification of integration issues or conflicts.
  3. Feature Branch Lifespan: If feature branches are used temporarily alongside TBD, ensure they are short-lived to minimize divergence from the trunk. The longer a branch exists separately from the trunk, the greater the risk of challenging merge conflicts and integration issues. Establish a guideline for the maximum age of feature branches (e.g., no longer than a day or two) and encourage frequent rebasing or merging from the trunk to keep the branches up-to-date.
  4. Enhanced Communication and Coordination: Foster open communication and coordination among team members. Ensuring everyone is aware of the changes committed to the trunk helps manage dependencies and avoid conflicts. Regular stand-ups or quick sync meetings can be instrumental in keeping team members aligned on current work and upcoming changes, especially in larger teams or distributed environments.

Trunk-Based Development with Unleash

Unleash is a powerful feature management platform that enables software teams to implement trunk-based development more effectively. By providing robust feature flagging capabilities, Unleash addresses many common challenges associated with trunk-based development and amplifies its benefits. Here’s how Unleash can add value to your TBD processes:

  1. Granular Control Over Feature Rollout: Unleash allows teams to toggle features on and off in real time, providing granular control over who sees what and when. This capability is crucial for managing the release of new features and mitigating the risks associated with deploying untested or partially completed features into the trunk.
  2. Targeted Feature Releases: With Unleash, you can release features to specific user segments or environments, facilitating more precise testing and validation. This targeting ability helps address the challenge of feature interaction complexity by enabling isolated testing of feature interactions in live environments.
  3. Decoupling Deployment from Release: By separating deploying code from the decision to release features, Unleash allows teams to integrate and test code in production-like environments without exposing unfinished features to all users. This decoupling is a cornerstone of trunk-based development, ensuring the mainline remains stable and deployable.

Essential features of Unleash for Trunk-based development

  1. Feature Flags: No surprise here. Unleash’s feature flags are central to managing the incremental development and release of features. They enable teams to merge code into the trunk at a high cadence without disrupting the user experience, directly addressing the challenge of managing incomplete features.
  2. Environment-Specific Toggles: With Unleash, you can define different toggle configurations for different environments. This feature is useful for maintaining consistency and stability in the production environment while allowing flexibility and experimentation in development and staging environments.
  3. Easy Rollback and Risk Mitigation: If a newly released feature causes issues, Unleash lets you quickly disable it without redeploying the application. This rapid response capability can be crucial for minimizing the impact of problematic features and maintaining system stability.
  4. A/B Testing and Canary Releases: Unleash supports advanced release strategies like A/B testing and canary releases, enabling more sophisticated and data-driven decision-making about feature rollouts. This aligns well with the principles of TBD, where continuous improvement and rapid iteration are key.
  5. Access controls and Change Requests: TBD means that even untested code is making its way into production. That can be scary for some organizations. That’s why Unleash enables full control over who can turn feature flags on and off in production. All changes are subject to approval by one or more approvers and are logged to make passing security and compliance audits easy.

Getting started with Trunk-based development

Whether you are just getting started with TBD or if you’ve already implemented it but need more out of your feature flag system, download Unleash today. Unleash is open source, and you can try for free. Explore more about what Unleash can do in our documentation.

Share this article