Skip to content

Conflict resolution: fully support all conflict types (deletes, renames, binary, symlinks, mode, encodings) #5393

Description

@ianhattendorf

Description

Conflict resolution (both the manual take-side flow and the AI resolution flow) currently handles only a subset of Git conflict types well. The common content conflict (UU modified-by-both) is fully supported, but many other unmerged states are either skipped, silently dropped, or surfaced as "unsupported." We should audit and fill in handling so that every conflict type a rebase/merge/cherry-pick/revert can produce has a sensible, predictable resolution path.

Current state

Manual take-sideclassifyConflictAction (packages/git/src/utils/conflictResolution.utils.ts):

  • Handles UU, AA, UD, DU, DD via take-current / take-incoming / delete.
  • AU + take-incoming and UA + take-current are classified unsupported — single-file UI hides them; bulk resolve reports them as skipped.
  • No special handling for renames, mode-only (exec-bit) changes, file/directory clashes, or binary/encoded files beyond "take a whole side."

AI resolution@gitkraken/conflict-tools via src/plus/coretools/conflict/integration.ts:

  • ConflictType is only 'text' | 'delete-modify'.
  • extractConflict returns null for anything without parseable text markers (binary, symlink, add/add without markers, mode-only, encoded). Those files are recorded as skipped with reason 'no-markers' — i.e. the AI flow quietly leaves them for the user with no guidance.

Conflict types to support / verify

Scenario Unmerged status Manual take-side AI flow Notes
Modified by both (content) UU ✅ text Baseline — works
Overlapping hunks UU ✅ text Verify multi-hunk
Add/Add (both added) AA ✅ take-side ⚠️ skipped (no-markers) AI should diff/merge the two added versions
Modify/Delete UD ✅ delete-modify Verify keep-vs-delete UX
Delete/Modify DU ✅ delete-modify Verify keep-vs-delete UX
Delete/Delete DD ✅ delete ⚠️ skipped Trivial but confirm
Add by us / Add by them AU / UA ⚠️ one side unsupported ⚠️ skipped Clearer UX than a silent skip when the requested side is absent
Rename/Rename (diverging targets) No rename-aware handling
Rename/Delete No rename-aware handling
Rename + Modify Content edit on a renamed file
File/Directory clash (obstacle) One side file, other side directory
Mode-only change (exec bit) ⚠️ ⚠️ skipped Take-side may not preserve/choose mode
Binary file ⚠️ take-side ⚠️ skipped No diff UI; AI can't parse
Symlink (divergent targets) ⚠️ ⚠️ skipped AI can't parse
Encoded / UTF-16 (binary-treated) ⚠️ ⚠️ skipped No marker parsing
Empty after rebase Edge case — verify it doesn't error

(✅ supported · ⚠️ partial/silent-skip · ❌ no handling · ❔ unverified)

Goals / acceptance criteria

  • Every unmerged status and conflict scenario above has a defined, predictable outcome in both the manual and AI flows — resolved, or explicitly surfaced with an actionable next step (never silently dropped).
  • "Unsupported" / "no-markers" cases present clear UI (e.g. "this is a binary/symlink/mode conflict — choose a side" or "rename conflict — pick a target") instead of disappearing from the results.
  • Renames, mode changes, file/dir clashes, binary, symlink, and encoded files each get appropriate take-side (and where feasible AI) handling.
  • Verified against the test branches below.

Test references

Internal conflict test branches live in ~/dev/test/dummy-repo-private. Rebasing main onto each tier produces the scenarios in rebase-conflicts/:

  • origin/rebase-conflict-test-base → common ancestor (ours-side changes)
  • origin/rebase-conflict-test-core → 8 core scenarios: both-modify, overlap, both-added, modify-vs-delete, delete-vs-modify, rename-rename, rename-vs-delete, file-vs-dir
  • origin/rebase-conflict-test-extended → core + mode + binary + symlink
  • origin/rebase-conflict-test-all → extended + rename-modify + UTF-16 + empty-after-rebase

Scenario files: rebase-conflicts/{core-both-modify,core-overlap,core-both-added,core-delete-vs-modify,core-modify-vs-delete,core-rename-vs-delete,theirs-renamed,all-rename-modify}.txt, core-obstacle/nested.txt, ext-mode.sh, ext-binary.png, ext-symlink, all-utf16.txt, all-empty-after-rebase.txt.

Also: ianhattendorf/conflict/multi-file/{base,left,right} for multi-file conflicts.

Metadata

Metadata

Assignees

Labels

area-aiIssues or features related to AIneeds-verificationRequest for verificationpending-releaseResolved but not yet released to the stable edition

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions