Engineering practice

Your branch doesn't grow while you're away. The trunk does.

Everyone estimates a merge by looking at their own diff, which is the one part of the problem that stopped changing the moment they stopped typing. The cost is set by the other side — by how far the trunk moved, multiplied by how long you were gone.

00 — Guess first

Commit before you look.

You write 40 lines on a branch and then leave it open for four weeks — a holiday, a reprioritisation, a review that never came. Meanwhile eight teammates keep merging to trunk. Your branch is still 40 lines. How hard is the merge?

01 — The mechanic

The divergence clock.

Two lanes: yours and the trunk. Every day apart, both keep moving, and the gap between them grows as the product of the two — which is why it feels fine for a week and impossible by week four. Drive the days, the size of the team you are diverging from, and how much of the hot code your change touches.

Answer the question in 00 — Guess first to unlock the clock.
02 — Practice

Which of these will Git actually tell you about?

You have been away three weeks. Here is what happened on trunk while you were gone. For each one, decide whether your merge will stop and demand a decision — or whether it will succeed silently, compile, go green, and fail later.

Called: 0 of 5 · Correct: 0

03 — How it's different

Branch lifetime is not the same lever as batch size.

They are cousins, and teams often conflate them. Small Batches is about how much goes out in one release — blast radius, and how many changes you have to bisect. This is about how long your work stays unintegrated — divergence, and how much reality moved underneath it. You can have a small change that is a catastrophic merge, which is exactly the case the batch-size lens misses.

Long-lived branch Short-lived branch
Merge cost Grows with the square of the time away. Near-constant, and small.
Conflicts arrive All at once, at the worst moment. One at a time, in the flow of the work.
Semantic conflicts Many, and invisible until runtime. Caught within a day, while you remember why.
Review quality "LGTM" on 4,000 lines nobody can hold in their head. Real comments, because the diff is readable.
Rework risk High — the design you built on may have moved. Low — you are building on today's code.
Who absorbs it Whoever merges last. Usually not the person who caused it. Everyone, continuously, in tiny amounts.

"But my feature isn't finished"

This is the real objection, and it deserves a real answer rather than an exhortation to be braver. The answer is to separate merging from releasing: put the unfinished code on trunk behind a switch that is off, and integrate every day anyway. That is what feature flags are for, and it is why trunk-based development and flags are always taught together — neither works properly without the other.

Semantic conflicts are the expensive half

A textual conflict is a good outcome. Git stops, shows you both versions and makes you decide, while you still remember the context. The costly ones share no lines at all: someone renamed the function you call, made the column you read nullable, or changed an endpoint to return a list. Those merge clean and build green. You find them at runtime, on a Thursday, and the person who made the change has long since moved on.

Merging four branches is not four merges

Integration week reads like four tasks. It is n(n−1)/2 reconciliations — six pairwise interactions for four branches, ten for five — and each one can undo a decision made in another. That is why "we'll integrate at the end" scales so much worse than anyone plans for, and why the week is always the one that slips.

04 — In the wild

Four branches that were only going to be open for a couple of days.

Nobody sets out to keep a branch for three months. Every one of these started as a reasonable plan with a short horizon.

Anti-pattern

The release branch that became a fork

A "stabilisation branch" is cut for a big release so that trunk can carry on. Six weeks of fixes then land on both sides, in slightly different forms. Half of them get lost in the reconciliation, and one bug gets quietly un-fixed by a merge that resolved in favour of the older version.

The move: stabilise on trunk and cut the release from a tag. A branch that accepts its own fixes is a second product.
Sunk cost

The refactor nobody could merge

Three months of "clean architecture" work touching almost every file. By the time it is ready, trunk has moved so far that the merge is a rewrite of the rewrite. The branch is quietly abandoned, and the lesson the team takes away is "refactoring doesn't work here" — which is the wrong lesson entirely.

The move: refactor in place, in small reversible steps behind the existing interface. Big-bang refactors fail on divergence, not on ambition.
Review

The review nobody could do

A 4,000-line pull request gets "LGTM" in eight minutes. A 60-line pull request from the same reviewer, the same afternoon, gets three substantive comments and a question about naming. The reviewer did not get lazier between the two.

The move: branch lifetime sets review quality. If you want real review, ship diffs a human can actually hold in their head.
Practice

Trunk-based, with the lights off

Everyone commits to trunk at least daily. Half-finished work goes in behind a flag that is off in production, so "not finished" and "not integrated" stop being the same thing. The frightening integration happens thirty times, in pieces small enough that nobody notices it happening.

The move: make the safe thing the default thing. Integrate continuously; release when you are ready.
05 — Go deeper

A branch is a bet that the world will hold still.

Every branch is a wager that nothing you depend on will move before you come back. Over a day that is a safe bet. Over a month, on a team of eight, it is a bad one — and the losses land on whoever merges last, which is rarely the person who placed it. Changing that is mostly a matter of policy and nerve rather than tooling, which is why it is work we do with teams rather than for them.

Talk to us about coaching
TAKE ONE

Divergence is a product, not a sum

Your change times their change times time apart. That is why a branch feels fine for a week and impossible by week four — the cost curve bends upward while your diff stands still.

TAKE TWO

The conflicts you see are the cheap ones

Git stops for overlapping lines. It says nothing about a renamed function, a newly nullable column or a changed return shape — and those merge clean, build green, and break later.

TAKE THREE

Unfinished and unintegrated are different

The only reason to hold work back is that it is not ready for users — and a flag solves that without holding it back from the codebase. Integrate daily; release when ready.