Diff Each Side Against the Merge Base
Type: Open-source — client-agnostic methodology, no project-specific detail.
Created by akbarsha — https://github.com/iamakbarsha1
Distilled from a case where 3-way auto-merge silently dropped fields outside
the conflict markers, and reading only the marked regions would have shipped a
file missing content.
Licence: Released under CC BY 4.0 — share and adapt for any purpose with
credit. Full text: LICENSE at the repository root.
Feedback & Support: If a rule here proves wrong or needs sharpening,
open an issue on the repository or contact the author at the profile link
above. If the problem is the agent not following a rule below rather than
the rule itself, that's an execution failure — acknowledge and correct it.
The core rule
Conflict markers mark where git could not decide — not the full extent of what
changed. Git's 3-way merge auto-resolves every hunk it thinks is unambiguous,
and those silent auto-resolutions can drop or duplicate content when both
sides edited near the same region. Resolving a conflict by reading ONLY the
<<<<<<</>>>>>>> regions is resolving a fraction of the delta. For any
non-trivial conflict, reconstruct the real change by comparing each side
against the merge base by symbol/field inventory.
Checks
- Inventory ours, theirs, and base — not just the markers. For a
conflicted file, list the symbols/fields/exports in the merge base, in
"ours", and in "theirs". The correct resolution is the UNION of both sides'
intended changes against the base. The markers only show you the overlap git
couldn't auto-pick; everything auto-merged is still yours to verify.
(A 3-way merge auto-dropped several struct fields that existed on both the
base and one side because the other side rewrote the surrounding block;
nothing appeared between conflict markers.)
- Treat delete-vs-extend as a decision, not an auto-pick. When one side
deletes what the other extends (a field, a case, a param), auto-merge or a
careless resolution will usually keep the delete and lose the extension —
silently. Whenever the base had X, one side removed it, and the other built
on it, stop and confirm intent explicitly. (Illustrative: A base switch-case was removed
on one branch while the other branch added new handling inside that same
case; auto-merge kept the removal and silently discarded the added
handling, with no conflict marker raised.)
- Verify the merged file's inventory against both parents. After
resolving, diff the result against BOTH parents and confirm every field/
symbol that either parent intended to add is present, and every one either
intended to remove is gone. A conflict "resolved" cleanly can still be
missing content that never conflicted. (Illustrative: After a conflict resolved with
zero markers on a given function, diffing the merged file against both
parent branches showed that function had existed in one parent and was
silently missing from the merge output.)
Pre-flight check — before you commit a merge resolution
If any box is unchecked, you've resolved the markers, not the merge — go
inventory both sides.
1---2name: diff-each-side-against-merge-base3description: Use when resolving a merge or rebase conflict, or reviewing a merge commit — conflict markers show where git gave up, not the full semantic delta, and 3-way auto-merge silently drops fields outside the markers. Compare ours/theirs/base by symbol and field inventory before trusting the result. Triggers on "merge conflict", "resolve conflict", "rebase", "git merge", "auto-merge", "cherry-pick", and reviewing a large merge diff.4---56# Diff Each Side Against the Merge Base78**Type:** Open-source — client-agnostic methodology, no project-specific detail.910**Created by akbarsha — https://github.com/iamakbarsha1**1112Distilled from a case where 3-way auto-merge silently dropped fields outside13the conflict markers, and reading only the marked regions would have shipped a14file missing content.1516**Licence:** Released under CC BY 4.0 — share and adapt for any purpose with17credit. Full text: `LICENSE` at the repository root.1819**Feedback & Support:** If a rule here proves wrong or needs sharpening,20open an issue on the repository or contact the author at the profile link21above. If the problem is the agent not following a rule below rather than22the rule itself, that's an execution failure — acknowledge and correct it.2324## The core rule2526Conflict markers mark where git could not decide — not the full extent of what27changed. Git's 3-way merge auto-resolves every hunk it thinks is unambiguous,28and those silent auto-resolutions can drop or duplicate content when both29sides edited near the same region. Resolving a conflict by reading ONLY the30`<<<<<<<`/`>>>>>>>` regions is resolving a fraction of the delta. For any31non-trivial conflict, reconstruct the real change by comparing each side32against the merge base by symbol/field inventory.3334## Checks3536- **Inventory ours, theirs, and base — not just the markers.** For a37 conflicted file, list the symbols/fields/exports in the merge base, in38 "ours", and in "theirs". The correct resolution is the UNION of both sides'39 intended changes against the base. The markers only show you the overlap git40 couldn't auto-pick; everything auto-merged is still yours to verify.41 *(A 3-way merge auto-dropped several struct fields that existed on both the42 base and one side because the other side rewrote the surrounding block;43 nothing appeared between conflict markers.)*44- **Treat delete-vs-extend as a decision, not an auto-pick.** When one side45 deletes what the other extends (a field, a case, a param), auto-merge or a46 careless resolution will usually keep the delete and lose the extension —47 silently. Whenever the base had X, one side removed it, and the other built48 on it, stop and confirm intent explicitly. *(Illustrative: A base switch-case was removed49 on one branch while the other branch added new handling inside that same50 case; auto-merge kept the removal and silently discarded the added51 handling, with no conflict marker raised.)*52- **Verify the merged file's inventory against both parents.** After53 resolving, diff the result against BOTH parents and confirm every field/54 symbol that either parent intended to add is present, and every one either55 intended to remove is gone. A conflict "resolved" cleanly can still be56 missing content that never conflicted. *(Illustrative: After a conflict resolved with57 zero markers on a given function, diffing the merged file against both58 parent branches showed that function had existed in one parent and was59 silently missing from the merge output.)*6061## Pre-flight check — before you commit a merge resolution6263- [ ] For each conflicted file you compared ours/theirs/base by symbol/field64 inventory, not just the marked regions.65- [ ] Every delete-vs-extend case was resolved by an explicit decision, not an66 auto-pick.67- [ ] The final file's inventory was diffed against BOTH parents and accounts68 for every intended add and remove.6970If any box is unchecked, you've resolved the markers, not the merge — go71inventory both sides.