THIS EXPLANATION
THE ROOM
CDA·137 Computing, Data & AI 6 MIN · 8 STATIONS

Merging often

A Socratic walk-through of merging often — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

Why do teams that merge their work several times a day spend less time merging than teams that do it monthly?

Merging is unpleasant, so the sensible response seems to be doing it less: work on a branch, finish the feature, integrate once at the end. Merging twenty times instead of once looks like twenty chances at the thing you were avoiding.

Yet teams integrating several times a day report spending less total time on merges than teams integrating monthly — and the monthly teams are the ones with a dreaded "integration week" on the calendar. If merging were simply work that had to be done, splitting it into twenty pieces would not shrink it. So merge cost cannot be proportional to the amount of change. Something about it must grow faster than that.

b

Reasoning it through

REASONING #

Ask what a conflict actually is. It is not two changes existing; it is two changes to the same place that the tool cannot reconcile. So conflict count is not driven by how much you changed, but by how much your changes and everyone else's overlap.

That distinction lets us reason about the growth. Suppose the rest of the team touches some quantity of code per day, and so do you. After a day apart, your edits meet one day of theirs; after thirty days, thirty days meet thirty. If edits are scattered across the codebase, the chance that some pair collides scales roughly with the product of the two sides' sizes — so expected conflict work grows with the square of the time apart, not linearly.

Now compare the two strategies over a month. Merge once: one comparison, both sides at full size. Merge twenty times: twenty comparisons, each side a twentieth of the size, so each costs roughly one four-hundredth of the big one — and twenty of those is about a twentieth of the single merge. Total conflict work falls roughly in inverse proportion to how often you integrate.

Be careful here: that is a simplifying model, not a measured law. It assumes edits are spread independently across the code, which is often false — two people asked to work on the same module will collide on day one. Treat the square as an explanation of why the cost is superlinear rather than a coefficient you can plan with.

And the model still understates the effect, because it counts only conflicts a tool can see. Consider the ones it cannot.

A semantic conflict merges cleanly and breaks anyway. You renamed a method's meaning while I wrote three new callers of the old meaning; the text does not overlap, so the merge is silent and the failure appears at runtime. No version control system detects this, because it reasons about lines rather than behaviour. What detects it is running the tests on the merged result — which is why the practice is integrate and verify, not merely merge.

Then there is the human cost, which scales with memory. Resolving a conflict means deciding what both sides intended. If both changes were made this morning, you know both. If yours is four weeks old and theirs is three, you are reconstructing two forgotten intentions and guessing which resolution preserves both. Forgetting is not linear in the delay either, so a month-old conflict is far more than thirty times harder than a day-old one.

And there is a failure mode with no gradual version at all. Suppose someone performs a broad refactor on the mainline — restructures a module your entire branch is built on. A branch merged daily meets that refactor once, as a modest adjustment. A month-old branch meets it as a wholesale rewrite, and sometimes the honest answer is to abandon the branch. Long-lived branches accumulate not merely conflicts but the risk of being invalidated outright.

Then the objection that keeps the practice from spreading: how do you merge unfinished work? Integrating a half-built feature puts broken code on the mainline. The answer is to separate integration from release — merge the work, keep it dark. The tools are feature flags, where the code ships but the path is off until complete, and branch by abstraction, where a seam lets the new implementation be built incrementally and switched to when ready. Neither is free: a forgotten flag is a real source of defects.

One thing worth stating plainly: the daily-merge claim is not folklore. Repeated years of the DORA research programme identify trunk-based development — short-lived branches, integrated at least daily — as correlating with higher software delivery performance. That is survey correlation rather than a controlled trial, so read it as strong support rather than proof.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of two people writing a report in separate copies. Reconcile after a paragraph and you compare two paragraphs, remember exactly what you each meant, and the differences are obvious. Reconcile after forty pages and you must read eighty pages, work out where the arguments have drifted apart, and decide which version of a claim you both revised is now correct — and if one of you restructured the whole argument in the meantime, the other's forty pages may not fit anywhere.

WHERE IT BREAKS DOWN

two report drafts can be merged by reading them, whereas merged code can be textually perfect and behaviourally wrong — so the analogy misses the class of conflict that only running the thing reveals, which is exactly the class that grows most dangerously with time apart.

d

Clarifying the model

THE MODEL #

The misconception worth correcting is that continuous integration is a server that runs your tests. That is a build service. The practice is that every developer integrates into the shared mainline at least daily and verifies it there; automated builds make that verification cheap enough to do so often. A team with an elaborate pipeline and three-week feature branches has bought the tooling, skipped the practice, and will still have an integration week.

Two refinements connect the reasoning. First, merging often is not sufficient on its own — it must be paired with a mainline that is kept working, or frequent integration just distributes the breakage. That is why the practice comes bundled with a fast test suite and a norm of fixing a red build before anything else.

Second, the argument is symmetric and often forgotten in one direction. It is not enough to pull from the mainline frequently; the benefit comes from your work being visible to everyone else too. A developer who rebases daily but pushes monthly still forces everyone else to integrate against a month of hidden change — which is why the practice is stated as merging to trunk rather than merging from it.

e

A picture of it

THE PICTURE #
Merging often
Merging often Follow the two branch lines separately. The upper branch rejoins the mainline after every commit, so at each merge point only one commit of each side has to be reconciled -- the overlap is small by construction. The lower branch runs for four commits while the mainline moves on independently, including a refactor it never sees; its single rejoining node has to reconcile everything both sides did in the interval at once. Both branches contain the same amount of work. The difference is entirely in how much of it meets the other side at a time. {"generator":"mermaid-svg-renderer@3.2.1","source":"../Socrates/.diagram-cache/_src/merging-often.md","sourceIndex":1,"sourceLine":4,"sourceHash":"6c18025bf6da59bda74c1f62acd9445dc616b94a18de2e7fa7dc7cb7ca7dc9ec","diagramType":"gitGraph","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":747,"height":360},"qa":{"passed":true,"findings":[]}} main daily long-lived start step 1 small step 2 small 2 wk 1 wk 2 wk 3 refactor wk 4 big merge

How to readFollow the two branch lines separately. The upper branch rejoins the mainline after every commit, so at each merge point only one commit of each side has to be reconciled — the overlap is small by construction. The lower branch runs for four commits while the mainline moves on independently, including a refactor it never sees; its single rejoining node has to reconcile everything both sides did in the interval at once. Both branches contain the same amount of work. The difference is entirely in how much of it meets the other side at a time.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

Merge cost is driven by the overlap between two sets of changes, and overlap grows with the product of how much each side changed — so waiting doubles the cost roughly four times over, while frequent integration keeps every reconciliation small enough to be trivial. The real risks that grow with time apart are the ones a merge tool cannot see: semantic conflicts, forgotten intent, and a mainline refactor that invalidates the branch entirely.

g

Where to go next

ONWARD #
  • What branch by abstraction costs on a large refactor, and when a temporary flag is the cheaper instrument.
h

Key terms

TERMS #
TermWhat it means
Continuous integrationthe practice of every developer merging into the shared mainline at least daily and verifying the merged result, not merely a build server.
Semantic conflicttwo changes that merge cleanly at the text level but break behaviour together; invisible to version control, detectable only by running the merged code.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4