How to Resolve a Git Merge Conflict Without Guessing What the Other Side Was Trying to Do
A conflict-free merge is not the same thing as a correct one.
The merge completed cleanly — no markers, no manual resolution, git happy. It was also broken: two unrelated changes had each independently added the same piece of configuration, and a line-based diff has no way to notice that two additions collide in meaning when they don't collide in position. Nothing about "no conflicts" means nothing went wrong.
TL;DR
- Git flags a conflict when two changes touch the same lines. It has no concept of two changes touching different lines that nonetheless produce a broken result together — like two branches each independently adding the same declaration. That kind of break sails through as a clean merge.
- The fix for conflicts that git does flag isn't picking a side by guessing from a commit message or a variable name — it's reading what each side's change actually does, and what the file being merged is actually supposed to do, before deciding.
- Doing that investigation on a real conflict this way found something worth generalizing: the two competing changes turned out to be the exact same fix, written independently by two different processes. That's verifiable — and worth verifying — rather than assumed from how similar the commit messages sound.
- Not every conflict should be resolved by the same process, though. One category is worth a hard rule: when a merge touches a file that encodes judgment or policy — not just logic — a program shouldn't resolve it silently, even when a resolution is technically possible. A wrong merge there doesn't fail loudly like a broken build. It just quietly ships the wrong judgment call going forward.
| Conflict type | Safe to auto-resolve | Why |
|---|---|---|
| Two sides made the identical change independently | Yes, after confirming it | Verified duplication, not an assumption |
| Two sides changed unrelated lines that combine into a bug | No — needs a human or a careful read | Git won't flag it; nothing will unless someone checks |
| Two sides changed the meaning/policy encoded in the same content | No, ever | A wrong resolution here is silent and ongoing, not a build failure |
The middle row is the one worth sitting with: it's the conflict class where "there were zero conflict markers" gives you false confidence.
Read before you resolve: what actually changed on each side
The fast way to resolve a merge conflict is to look at the two versions, guess which one is "the real one" from context clues — which commit is newer, which branch name sounds more authoritative, which diff is shorter — and take that side. It's fast because it skips the actual question: what does each side's change do, and does the file's current behavior already match one of them?
The reliable way costs three extra steps and removes the guessing entirely — call it Read-Read-Compare:
- Read the actual diff on both sides — not the commit message summarizing it, the diff itself.
- Read the file being merged as it exists right now, independent of either side's changes, to see what behavior is currently live.
- Compare all three. Sometimes one side has already been superseded by what's live. Sometimes both sides are solving the same problem in slightly different words. Sometimes they're genuinely different fixes that both need to survive the merge.
None of this is exotic. It's the same discipline as reading a pull request properly instead of skimming the title and approving — it just gets skipped more often on a same-repo merge conflict because it feels lower-stakes than a PR someone else will see.
The verification that turned "probably the same fix" into "confirmed the same fix"
I applied Read-Read-Compare to a real conflict — the local, uncommitted side and an already-merged remote commit had each changed the same test assertions. I didn't stop at "these look like they're doing the same thing." I checked: what did the local version actually assert, what did the remote version actually assert, and — the step that matters — what does the actual source code being tested currently do?
All three agreed. Both sides had independently arrived at the identical behavioral fix; the only difference was that one had a clearer explanatory comment than the other. That's a genuinely different situation from "these look similar, keep whichever," because I checked it against ground truth (the real source code) rather than inferring it from how alike the two diffs appeared. Once confirmed, resolving it was simple: keep the better-documented, already-verified version, discard the redundant one, and — because everything the discarded side touched was independently confirmed to already exist somewhere else — nothing was lost by dropping it.
The lesson generalizes past this one conflict: "probably the same change" and "confirmed the same change" look identical until something breaks that depended on the difference. The extra step of checking against the actual current behavior of the code is what turns a guess into a fact.
The bug a clean merge would have hidden completely
Separately, I checked whether merging two diverged branches would go smoothly, using a non-destructive `git merge-tree` simulation instead of attempting the real merge — and it surfaced something more useful than the conflicts git actually reported. The dry run showed the real conflicts clearly — a handful of files both sides had reworked, resolvable with attention. But one file merged with zero conflicts reported, and the result was broken anyway: both branches had independently added an import of the same name from the same module, for unrelated reasons, and a line-based merge has no concept of "these two additions, both individually fine, produce a duplicate declaration when combined." Git's conflict detection operates on lines, not on whether the combined result actually compiles.
That's the concrete, non-obvious point worth taking away: a merge reporting zero conflicts is not the same claim as "the result is correct." It's only the claim "no two changes touched the identical lines." Anything that breaks through the combination of two individually-fine changes on different lines sails through silently, and the only way to catch it is to actually build or run the merged result before trusting that "no conflicts" meant "safe."
The merge I refused to complete automatically
The same investigation also turned up a case I deliberately left alone rather than completed: merging that branch in full meant resolving several conflicts, and one of them touched a file encoding editorial judgment calls — not application logic, but the actual rules a system uses to decide what's acceptable — against a version that had made its own unrelated edit to the same file. I resolved the rest of the branch; I didn't touch that one.
A line-based resolution of that file was technically possible. It just wasn't the right call to make without a human reviewing it, for a specific reason: a wrong merge of application logic tends to fail loudly — a test breaks, a build fails, an error shows up in a log somebody eventually reads. A wrong merge of a file encoding judgment or policy fails silently and keeps failing, indefinitely, because the system just keeps using whatever the merge produced as if it were a deliberate decision. Nothing downstream checks "was this the judgment call the two authors actually intended," because there's no test for intent.
That distinction is the actual rule worth generalizing, past git specifically: automate resolution for anything whose failure mode is a loud, checkable break. Route anything whose failure mode is a silent, ongoing wrong answer to a human, even when a mechanical resolution is available. The second category doesn't announce itself as risky the way an actual conflict marker does — it looks exactly as resolvable as anything else, right up until the wrong version quietly becomes the permanent one.
Run this yourself
A checklist for approaching a real merge conflict — or an unexpectedly clean merge you don't fully trust — without guessing:
Before resolving this merge conflict (or accepting a conflict-free merge
you're not confident in):
1. Show me the actual diff on each side of the conflict — not a summary,
the real changes.
2. Show me what the file currently does, independent of either side,
by reading the relevant source directly.
3. Determine: are both sides making the same change, a compatible change,
or a genuinely conflicting one? Justify the answer by comparing the
diffs to the actual current behavior, not by how similar the commit
messages or branch names sound.
4. Separately, check whether merging would produce a result that's
syntactically valid and non-duplicative even in files with zero
reported conflicts — specifically watch for two sides independently
adding the same import, constant, or declaration.
5. Flag any file where the conflict is about judgment, policy, or
editorial content rather than mechanical logic. Do not auto-resolve
those — describe what each side changed and let me decide.
Do not resolve anything until you've reported findings for all five.Treat step 5's findings as a stop sign, not a suggestion — the whole point is that this category doesn't look different from any other conflict until someone deliberately checks for it.
FAQ
Isn't this overkill for a routine merge?
For a genuinely mechanical conflict — formatting, an obviously superseded change, a straightforward either-side pick — no, resolve it directly. The investigation earns its cost specifically when you're not sure, when the conflict involves logic you didn't write, or when a clean merge in an unfamiliar area feels too easy to fully trust.
How do I know if a file encodes "judgment or policy" versus just logic?
A rough test: if a wrong merge would fail a test or break a build, it's logic — safe to resolve mechanically once you've verified intent. If a wrong merge would just quietly change what the system considers correct or acceptable going forward, with nothing that would ever flag it as wrong, it's policy — and it should get a human's eyes regardless of how resolvable it looks.
What's the actual risk of a merge that reports zero conflicts?
That "zero conflicts" only means no two changes touched the same lines — it says nothing about whether the combined result is valid. Two independently-fine changes on different lines can still produce a broken result together (a duplicate declaration is the clean example), and nothing about the merge process itself will surface that. Only actually building or running the result will.
Does this apply outside of git specifically?
Yes — the underlying pattern is any situation where two independent changes get combined automatically and "no reported problem" gets treated as "definitely fine." The same caution applies to merging two configuration files, combining two data imports, or reconciling two independently-updated records — the combination can be wrong even when neither individual change was.
Bottom line
A merge conflict git actually flags should be resolved by reading what each side's change does and what the file currently does — not by guessing from context clues. A merge that reports no conflicts deserves the same scrutiny, not less, because "no conflicts" is a narrower claim than "correct" and won't catch two individually-fine changes that break each other in combination. And some conflicts — the ones that encode judgment rather than logic — are worth refusing to auto-resolve entirely, because getting them wrong doesn't fail loudly. It just quietly becomes the new normal.
I bring the same "verify before you trust the combination" instinct to running experiments through GrowthLayer — two changes that each look fine independently can still interact badly, in code or in a test. Navigating a messy multi-branch codebase and want a second set of eyes on the process? Book a call and we'll scope it.