Skip to content

Handbooks/Software that stays in use

1Reviewed 14 Oct 2026

Continuous integration/Keep main releasable

Keep main releasable

Software stays in use when a team can still change it. Continuous integration keeps that change cheap: people merge to main at least daily, a build tests the merge, and a broken main is the team's work.

My operating rule: keep main releasable, make the failure visible immediately, and do not let a red main become normal.

Why the code stops lasting

Fowler describes the decay as a cost, not a mood. A structure that was reasonable at the start is in the way six months later. Improving it means a deep edit. On a long-lived branch that edit collides with everyone else's work. People remember the week a good change broke the team, and they stop making those changes. The awkward structure stays. New work gets slower.

The reversal he names is refactoring: small, behaviour-preserving changes to the structure, done often, on a build that can tell you the behaviour held. A refactor that sits on a branch for two weeks can improve the code and still be too expensive to merge, because everyone else spent those two weeks building on the old structure. Integrate often enough and the same change is a few hours of adjustment. A clash shows up while the two people can still talk.

That is how I use the phrase software that stays in use. The code lasts because the team can still restructure it. Rare integration is what makes the restructuring too expensive to start.

Fowler, refactoring

The practice, and my rule

Fowler's definition is the established practice. Each person merges their work into the shared codebase, together with their colleagues' changes, at least daily. Each merge is verified by an automated build that includes tests, so a fault shows up while the change is small.

A build server that only compiles feature branches does not meet that definition. He calls it semi-integration. You have pulled main into your branch. You have not combined your work with the other branches still open. The collisions wait until someone finally merges.

Hammant describes trunk-based development as one trunk, resistance to long-lived branches, and a main you can release. On that page he also describes a full build on the workstation before anyone else depends on the change. I use that workstation build as a safeguard. I do not treat it as the definition of every trunk-based team. Fowler argues the two names are one practice, and that a build server on feature branches is not it. A team can keep one trunk and still miss his rule, if the merge is rarer than daily or the build does not test it. The invariant I hold is frequent integration and a result you can trust. The tool sequence can vary. The work still has to land on main today, and the build still has to check that landing.

Fowler, daily merge·Fowler, semi-integration·Fowler, CI and trunk-based development·Hammant, trunk-based development

The day

This is the order I use on a full-time team. The pull, the build on the machine that made the change, and the push follow Fowler's walk.

  1. 01 PullTake main. If it is red, repair it before a feature.
  2. 02 ChangeA slice that can merge today.
  3. 03 TestRun the build before anyone else depends on it.
  4. 04 IntegratePull again, combine, push to main.
  5. 05 VerifyThe integration machine, not the laptop.
  6. 06 RepairFix or revert the break before the next feature.
The commit loop. Repair is part of the loop, not a later project.
  1. Pull main and run the build before you change anything. If it is red, fix that first. A new edit on a red build hides which change failed.
  2. Keep the change small enough to merge the same day. If it will not fit, split it. When the behaviour has to stay off while the code lands, Hammant uses a feature flag or a branch by abstraction. Those keep unfinished behaviour off the path a person uses. They do not make an untested change safe to release.
  3. Run the build on your machine before anyone else can depend on the result. Then pull again, combine, and run it again. Then push.
  4. Wait for the build on the integration machine. A green result on your laptop is not the gate.
  5. A pull request can carry the review when the branch is short-lived and lands the same day. Fowler's warning is the other case: a review that waits for hours or days adds enough friction to break the daily merge.

Fowler, daily merge·Fowler, code review·Hammant, trunk-based development

A broken main

A red main is the team's work, not a badge someone notices tomorrow. Fowler's rule, which he takes from Kent Beck, is that nobody has a higher priority than fixing the build. I stop further feature integration. The change that repairs the break, or reverts it, still lands. Normal integration resumes when main is green.

  1. 01 FailsThe integration build goes red.
  2. 02 StopNo further feature work lands on main.
  3. 03 FindThe change that broke it.
  4. 04 RepairFix that change, or revert it. That change still lands.
  5. 05 ResumeMain is green. Feature integration starts again.
Feature work waits. The corrective change does not.

Fowler, fix the build·SDLC field card

The tests that make the day possible

Daily merging dies if the build is too slow to run, or if red has stopped meaning anything. Fowler's ten minutes is a guideline for the commit build, the one that runs on every push to main. It is not a limit on every later stage. He splits what will not fit. The first stage compiles and runs the localized tests, with slow collaborators replaced by a double. A later stage may hit a real database and take a couple of hours. The first stage is the stop. The second stage is still fixed quickly. It is not the build you wait on before every push.

Vocke, using Mike Cohn's pyramid, is the shape inside those ten minutes. Many small fast tests. Some coarser tests. Very few that drive the whole application. He warns against a test ice-cream cone: a nightmare to maintain, and too slow to run. Test observable behaviour. A test tied to the internal structure breaks when you refactor, the safety net becomes noise, and people stop refactoring.

If the behaviour held and the test went red because a name or a collaborator moved, delete the test or rewrite it against the behaviour. An agent-written test is a draft until a person has done that once.

A control I rely on to stop a bad merge has to be able to fail the build. A review, a policy call, or a check on another cadence is a different control, and I do not describe it as that gate. NIST SP 800-218 says to integrate secure-development practices into the life cycle you already run. Practice PW.1 says you identify the security requirements and the risks the software will face, threat modeling being one form of risk modeling it names, and you track the requirements, the risks, and the design decisions. I use that record to decide which checks are gates.

  1. FastMany tests of observable behaviour, close to the change.
  2. CoarserFewer tests across a boundary, still in the commit build when they stay fast.
  3. End to endVery few. They can run in a later stage.
Most of the commit build is fast tests of behaviour. The slow end-to-end checks are few, and they are not the ten-minute loop.

Fowler, the commit build·Vocke, the test pyramid·Vocke, test behaviour·NIST SSDF·NIST SP 800-218, PW.1

What I inspect

These are the questions I ask of a team. They are my check, not a claim that Fowler or Hammant published this list.

  1. Can a developer get a meaningful result from the commit build while the change is still small?
  2. How long does a change typically sit before it is on main?
  3. When main is red, who stops, and who restores it?
  4. Do the tests fail because the behaviour changed, or because the structure moved?
  5. Can the team say what would make this change safe to release, separately from the fact that it merged?

How I would know

I track three times. How often a change reaches main. How long from that push until the integration build returns a result. How long a red main stays red. A faster build only counts if the main you restore is still one you can release. A green badge with rare merges, or a fast loop that leaves main broken, is not the practice.

Where I do not use it

Fowler's limit, which I use: a project with one or two part-time maintainers and contributors they do not work beside. Daily integration is not plausible there. The pull-request workflow came from that setting. Raise the frequency you can. A build badge is not the practice.

The practice fails without the skill under it. No self-testing build, and main goes red for reasons nobody can see. No automation, and the integration itself takes too long to do daily. A team that pushes red and walks away trains everyone else to work on a broken trunk. I do not install the daily merge until the commit build exists and someone will stop for it.

Release calendars, blast-radius proof, and the cutover sequence stay on the technology delivery field card. Fowler separates the two decisions. Once main is releasable, whether to put that build in production is a business decision. Keeping main releasable does not pick the window.

Fowler, where CI does not fit·Fowler, release is a business decision·Technology delivery field card

References