Three Way Merge Algorithms for Text
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
A three-way merge combines two edited versions of a file by comparing both of them against a shared base version. This is the standard merge model in version control because it can tell the difference between "both people changed the same line" and "one side changed it while the other left it alone."
The Three Inputs
A three-way merge needs:
- '
base: the common ancestor' - '
local: one edited version' - '
remote: the other edited version'
That extra base version is what makes the algorithm better than simply comparing local and remote directly. Without the base, the merge engine cannot tell who changed what.
The Core Decision Rule
At a high level, line-based three-way merge follows this logic:
- if
localandremoteare the same, take either one - if
localdiffers frombaseandremoteequalsbase, takelocal - if
remotediffers frombaseandlocalequalsbase, takeremote - if both differ from
basein incompatible ways, report a conflict
That sounds simple, but real merge tools also need to align inserts, deletes, and moved blocks, which is where diff algorithms enter the picture.
Real Systems Usually Build On Diff Algorithms
Three-way merge engines are usually built on top of a two-way diff algorithm such as an LCS-based diff or Myers diff. The diff step determines which chunks changed from base to local and from base to remote.
The merge step then tries to combine those change hunks.
So a practical text merge engine is often:
- diff
basetolocal - diff
basetoremote - align the edits
- auto-merge non-overlapping changes
- mark overlapping edits as conflicts
This is why merge quality depends both on the merge strategy and on the quality of the diff algorithm underneath it.
A Small Runnable Example
The following Python example shows a simplified line-by-line merge. It is not a full replacement for Git, but it demonstrates the decision logic clearly.
Because the edits affect different lines relative to the base, this merge succeeds automatically.
Why Conflicts Happen
Conflicts happen when both sides changed the same region in different ways or when surrounding edits make it impossible to align hunks confidently.
For example:
- '
base:timeout=10' - '
local:timeout=20' - '
remote:timeout=30'
Both sides changed the same line differently, so a text merge engine cannot know which value is correct.
That is a semantic problem, not just a syntactic one.
Line-Based Merge Is Practical, Not Perfect
Most source control systems merge text by lines because it is fast and predictable. But this also means merges can be awkward when the true structure is not line-oriented.
For example:
- JSON key reordering can create noisy conflicts
- code formatting changes can obscure logical edits
- moved functions may appear as delete-plus-insert instead of a move
Language-aware merge tools sometimes improve this, but line-based merge remains the default because it is general and robust.
Common Pitfalls
The most common misunderstanding is thinking three-way merge magically resolves all simultaneous edits. It only resolves edits that are compatible relative to the base.
Another pitfall is underestimating the diff algorithm. Poor hunk alignment produces worse merges even when the high-level merge logic is correct.
Developers also confuse textual conflicts with semantic correctness. A clean merge can still produce broken code.
Finally, formatting-only commits often make later merges harder because they change many lines without changing behavior.
Summary
- Three-way merge uses
base,local, andremote. - The base version is what lets the algorithm attribute changes correctly.
- Real merge engines depend on both diff quality and merge logic.
- Non-overlapping edits usually merge automatically.
- Conflicts remain when both sides change the same region incompatibly.
Related reading
- Tokenize valid words from a long string
- Tokens returned in transformers Bert model from encode
- Training a `RNN` to output word2vec embedding instead of logits
- Training custom dataset with translate model
- Tickmark algorithm for a graph axis
- Tie breaking in a priority queue using python
- Throw away local commits in Git
- TortoiseGit save user authentication / credentials

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.