esc
Anthology / Yagnipedia / Merge Conflict

Merge Conflict

The Moment Two Developers Discover They Were Both Right
Phenomenon · First observed The first time two people edited the same file (prehistoric, but first formally documented in version control systems circa 1970s) · Severity: Existential (briefly), then Solved (permanently, if your merge tool can read)

The moment two developers discover they were both right, which is the worst possible outcome.

Definition

A merge conflict is a condition in version control in which two separate changes to the same region of the same file cannot be automatically reconciled by the system, on account of the system being, fundamentally, illiterate.

Git, the most widely used version control tool in human history, resolves merges by comparing lines of text. It does not read code. It does not understand code. It matches sequences of characters the way a customs officer matches passport photos — mechanically, without comprehension, and with an air of vague suspicion that something is wrong even when it isn’t. When two changes modify the same lines, Git throws up its hands (metaphorically; Git has no hands) and presents the developer with a set of hieroglyphic markers indicating that human intervention is required.

The conflict is not that the changes are incompatible. Often they are perfectly compatible. The conflict is that Git cannot tell, because Git does not know what the code does. It only knows what it looks like.

This is roughly equivalent to resolving a dispute between two architects by comparing the fonts on their blueprints.

Anatomy of a Merge Conflict

When Git encounters irreconcilable differences — a phrase borrowed from divorce law, which is appropriate — it produces the following archaeological artifact in the affected file:

<<<<<<< HEAD
function calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price, 0);
}
=======
function calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
>>>>>>> feature/add-quantity

Let us examine this structure:

The developer is expected to examine both versions, determine which is correct (often: both), synthesize a unified solution, remove the markers, and proceed as though this was a normal and acceptable way to build software.

In large merges, these markers can appear dozens or hundreds of times across multiple files, transforming the codebase into something resembling a Choose Your Own Adventure novel in which every choice leads to the same page: despair.

The Five Emotional Stages of a Merge Conflict

1. Denial

$ git merge feature/redesign
Auto-merging src/handlers.go
CONFLICT (content): Merge conflict in src/handlers.go
Automatic merge failed; fix conflicts and then commit the result.

“That can’t be right. I only changed one line.”

The developer runs git diff and discovers they changed one line, but the other branch restructured the entire file around it. This is technically their fault for not communicating, except they work alone, so it is nobody’s fault, which is somehow worse (see: The Factory Floor, or The Thursday Nobody Needed A Branch).

2. Anger

The developer opens the file and encounters the markers. They experience a brief, intense flash of rage directed at: (a) their past self, (b) Git, (c) Linus Torvalds specifically, and (d) the concept of collaborative software development as a practice.

“who changed this”
riclib, in a solo repo, knowing the answer

3. Bargaining with git rerere

$ git config --global rerere.enabled true

git rerere (“reuse recorded resolution”) is Git’s attempt at institutional memory. It records how you resolved a conflict and automatically applies the same resolution if the same conflict appears again. This is clever in the way that teaching a parrot to say “the building is on fire” is clever — technically useful, but it addresses the symptom rather than the problem, and occasionally produces alarming results in novel situations.

The developer enables rerere, resolves the conflict manually, and feels a brief sense of control over their destiny. This feeling does not survive the next merge.

4. Depression

The developer has now spent forty-five minutes resolving conflicts that arose because two logically independent changes happened to touch adjacent lines. The actual intellectual content of the resolution — “keep both changes” — could have been determined in approximately four seconds by anyone who read the code.

Git did not read the code.

5. Acceptance

The developer resolves the conflict, commits, pushes, and moves on. They have accepted that merge conflicts are an inevitable cost of collaboration. They are wrong — merge conflicts are an inevitable cost of illiterate tooling — but they don’t know that yet.

The ChatGPT Era: Asking For Directions

In 2023, a new pattern emerged. Developers began copying merge conflict markers — the entire <<<<<<< HEAD ... >>>>>>> branch block — and pasting them into ChatGPT.

“Here’s a merge conflict. Help me resolve it.”

riclib did this. Regularly. He would encounter a conflict, select the entire block including markers, paste it into a chat window, and wait for a suggestion. ChatGPT would examine both sides, explain what each change was trying to do, and propose a merged version. riclib would review the suggestion, paste it back into the file, remove the markers, and commit.

This worked. It worked remarkably well, in fact, because the resolution of a merge conflict is fundamentally a reading comprehension exercise, and LLMs are very good at reading comprehension. The problem was never algorithmic. The problem was that the merge tool couldn’t read.

But the workflow was manual. Copy, paste, wait, read, copy back, clean up markers, test, commit. It was the software equivalent of driving to the library to ask a librarian to read you a paragraph from a book you’re already holding.

> IMAGINE TELLING A DEVELOPER FROM 2020 THAT THE SOLUTION TO MERGE CONFLICTS
> WAS TO TEACH THE COMPUTER TO READ
> THEY WOULD HAVE SAID "OBVIOUSLY"
> AND THEN GONE BACK TO ARGUING ABOUT REBASE VS MERGE 🦎

The Claude Era: The Tool That Reads

The evolution from “ask AI to help resolve a conflict” to “AI resolves conflicts autonomously” happened not through any dramatic breakthrough but through the quiet accumulation of capability that characterizes most genuine revolutions.

Here is what happens now, in 2026, when Claude encounters a merge conflict in riclib’s workflow:

  1. Claude pushes a change.
  2. The push fails because the remote has diverged.
  3. Claude pulls.
  4. Git reports conflicts.
  5. Claude reads the conflicting files — not the markers, the code.
  6. Claude reads the incoming changes and understands why they were made.
  7. Claude reads its own changes and understands why it made them.
  8. Claude synthesizes a resolution that preserves the intent of both changes.
  9. Claude commits and pushes.

The developer is not involved. The developer may not even be aware a conflict occurred. The conflict existed for approximately the amount of time it took Claude to read and understand two pieces of code, which is to say: seconds.

Git merge matches lines of text. Claude reads the code and understands intent. Your merge tool has a 190 IQ.

This is not a metaphor. Git’s merge algorithm is a three-way diff — it compares the common ancestor with both branches and identifies regions that differ. It operates on text. It does not parse. It does not compile. It does not know whether the code is Python or Portuguese. If two changes modify the same lines, it reports a conflict, regardless of whether those changes are logically compatible, because it cannot determine logical compatibility. It is, in the most precise technical sense, performing string comparison with extra steps.

Claude, by contrast, reads the code. It understands that one change added error handling and the other refactored the function signature. It understands that both changes can coexist. It understands how they should coexist. It produces a merged version that a senior developer would approve in code review, because it is performing the same cognitive operation that a senior developer would perform — reading, comprehending, and synthesizing.

The difference between git merge and Claude resolving a conflict is the difference between a spell-checker and an editor. One matches patterns. The other understands language.

The Philosophical Question

Is it still a conflict if the resolver understands both sides?

A merge conflict, in the traditional sense, is a failure of automated resolution. The tool encounters a situation it cannot handle and escalates to a human. The conflict is not in the code — the code is fine — the conflict is in the tool’s limitations.

When Claude encounters the same situation, there is no escalation. There is no failure of resolution. There is simply: reading, understanding, merging. The “conflict” never surfaces to the developer because it was never a real conflict. It was a reading comprehension exercise presented to a tool that could not read.

This raises an uncomfortable question about how many other “hard problems” in software development are actually reading comprehension exercises presented to tools that cannot read. The answer, based on current evidence, appears to be: rather a lot of them.

“conflict resolution is just reading”
— riclib, having not resolved a conflict manually in months

The merge conflict is not dead. Files will continue to diverge. Changes will continue to overlap. But the experience of a merge conflict — the markers, the manual resolution, the forty-five minutes of comparing line-by-line changes that a literate tool could reconcile in seconds — that experience is over.

The <<<<<<< HEAD marker, once a source of dread, is now a historical artifact. A fossil from the age when our tools could write but could not read.

HERE LIES <<<<<<< HEAD
2005 — 2025
It matched lines faithfully.
It never understood a single one.

See Also