feat(merge): line-level (diff3) blob merge for non-overlapping edits (#62) #38
feat/line-level-3way-merge
into main
Closes #62.
Problem
ExGitObjectstore.Merge did a tree-level merge only: any file whose blob differed on both sides was declared a conflict, with no line-level merge. This false-conflicted every merge where main advanced onto a file a branch also touched — surfaced as Anvil PR #159 showing mergeable: conflict while git merge-file merges cleanly. It backs merge_branches/squash_merge and Anvil’s compute_mergeable_status, so it affected both the badge and the actual merge.
Fix
New ExGitObjectstore.Merge.Diff3 — a diff3 line merge on the existing Diff.Myers edit script — wired into resolve_divergent for regular files (exec-bit/mode reconciliation; symlinks, gitlinks, deletions, binaries fall through to conflict).
Fidelity to git
- Byte-for-byte parity with
git merge-fileon realistic (distinct-line) inputs — differential fuzz test. - Conservative on pathological repeated-line inputs: an 8000-case adversarial fuzz produces zero false auto-merges (never clean where git conflicts); residual is safe-direction over-conflicts only. Achieved via down-slide compaction + refusing to anchor inside a repeated run. Full
xdl_mergeparity is a follow-up.
Tests
diff3 unit cases (clean/conflict/repeated-line), git merge-file differential fuzz, tree/commit integration, exec-bit reconciliation, symlink/gitlink conflict. Full suite 969 tests, 0 failures; mix credo --strict clean.
🤖 Generated with Claude Code