Main Line

When you use an agile software development process, you plan incrementally and iteratively. You want your codeline process to support your approach to delivery. This pattern describes the high-level structure — a Main Line — that makes it easier to deploy code quickly to reveal business value while maintaining stability and traceability by providing a central integration point for code.

Challenges of Balancing Speed and Stability

Agile software development is based on frequent iteration and feedback as measured by inspecting working software. But stability and speed can appear to be at odds, especially in a shared codebase where many people contribute.

Some teams try to reduce the risk of error by slow, disciplined steps when integrating work into a delivery code line. These teams may have:

The team integrates into a single shared code line only once it is “certain” that the code works. For example, in a GitFlow model {Atlassian #13833}, work in progress is integrated into a “Develop” branch, which is considered a working branch. The changes are merged to the shared mainline only after they have been approved for release.

There are variations, all of which work on the belief that isolation and moving slowly is safer. Keeping work on isolated branches preserves the stability of the eventual target branch in the short term but defers the problem: the target branch receives changes slowly, leading to process and business risk:

Since agile software development is about adapting to uncertainty in the project space, it is valuable to evaluate the current state of the code sooner.

Moving slowly can lead to a self-fulfilling dynamic:

Faster integration means you could miss an error, but slow integration doesn’t guarantee perfect software. Regardless of the size of the unit of work or how quickly you integrate it, merging code that breaks the shared integration codeline will slow down the entire team.

Frequent integration is more productive: the more frequently you integrate, the simpler each integration will be because the change is smaller and the work started with more recent code. You want a solution that balances stability and speed, allowing you to deliver code rapidly,

Create a Stable Baseline

** Work on a Main Line, where all work is integrated. Use mechanisms to allow work to be integrated frequently while maintaining stability so that the Main Line is potentially deployable.**

A Main Line is a code line that:

The Main Line is never deleted. It lives throughout the entire project, and the entire team contributes to it.

Work in progress, before it is merged to the Main Line could be:

Following our principle of working in small batches and building quality in, high- performing teams keep branches short-lived (less than one day’s work) and integrate them into trunk/master frequently.

The goal of Agile Software development is to manage uncertainty. As Mike Cohn wrote in Agile Estimating and Planning {Cohn, 2006 #222473}:

The best way of dealing with uncertainty is to iterate. To reduce uncertainty about what the product should be, work in short iterations, and show (or, ideally, give) working software to users every few weeks…

Being biased toward quicker integration into a shared Main Line, rather than reducing error, can help you manage uncertainty by showing you an accurate current state. Errors will still happen; being able to recover when they do is more valuable than slowing down in an attempt to avoid them all. As Gary Klein writes in Seeing What Others Don’t {Klein, 2015 #156450}:

“When we put too much energy into eliminating mistakes, we’re less likely to gain insights. Having insights is a different matter from preventing mistakes.”

A Main Line model makes you more responsive, and the tradeoff between stability and speed can be reconciled with a bias toward speed {Forsgren et al., 2018 #92987}:

This huge increase in responsiveness does not come at a cost in stability, since these organizations find their updates cause failures at a fraction of the rate of their less-performing peers, and these failures are usually fixed within the hour. Their evidence refutes the bimodal IT notion that you have to choose between speed and stability—instead, speed depends on stability, so good IT practices give you both.

A goal of an agile project is to gain insights into the state of the software by frequently inspecting the latest code in a running application.

Migrating to a Mainline

The end state of the Main Line model is continuous deployment once code is merged to main. While many teams embrace “Continuous Integration” to the Main Line, continuous deployment from the main line to production can take a few step to get there:

A reasonable migration path is:

Example

A Main Line development flow will look like the following, though each team can decide what the correct length of time is:

  1. Checkout the HEAD of the Main Line into a development workspace
  2. Code, backed by a Task Branch
  3. Within a day, merge the code after an appropriate feedback process.

Cautions

Maintaining an active, healthy, Main Line takes discipline. An occasional error is inevitable, so while you might feel comfortable eliminating intermediate branches and getting code to the Main Line quickly, you may be tempted to add extra gates between “merged to main” and “released.” While this might be a reasonable starting place, you want to work to get to a point where the merge to the_ Main Line_ is quick, automated, and gives you high confidence.

Next Steps

While the Main Line model’s simplicity, with fewer codelines, has advantages, you need some mechanisms to allow frequent integration to happen safely and reliably. You can’t avoid all errors, but you can avoid major ones and reduce the impact of any that slip through.

To help ensure a healthy Main Line you need to:

References