What strategies exist for resolving complex merge conflicts, and how do tools like git rerere, merge drivers, and diff3 style help?
Quick Answer
Complex conflict resolution uses diff3 style (merge.conflictstyle = diff3) to show the common ancestor alongside both branches, git rerere to automatically re-apply previously recorded resolutions, custom merge drivers for file-type-specific merging, and mergetool integrations for visual three-pane editing. These transform conflict resolution from guesswork into a systematic, repeatable process.
Detailed Answer
Think of conflict resolution like mediating a dispute between two contract revisions. The default Git approach shows you version A and version B and says 'figure it out.' The diff3 style is like also showing the original contract before either party made changes, so you can see what each side actually changed rather than just how they differ from each other. Git rerere is like having a mediator who remembers how you resolved an identical dispute last month and applies the same resolution automatically. Custom merge drivers are like hiring a specialist mediator for specific clause types (JSON files, XML documents, lock files) who knows the domain-specific rules.
By default, Git shows conflicts with two-way markers: <<<<<<< ours, =======, and >>>>>>> theirs. Enabling diff3 style with git config merge.conflictstyle diff3 adds a third section showing the common ancestor between the two markers, delimited by ||||||| base. This is enormously helpful because seeing what the original code looked like tells you what each branch intended to change. Without the ancestor, you are comparing two modified versions and guessing at intent. With zdiff3 (available since Git 2.35), Git further reduces noise by only showing the conflicting portion of each section, automatically resolving the non-conflicting parts.
Git rerere (reuse recorded resolution) is enabled with git config rerere.enabled true. When you resolve a conflict, rerere records the pre-resolution conflict state and the resolution you applied in .git/rr-cache/. If the exact same conflict appears again (common during repeated rebases or long-lived branches), rerere applies the recorded resolution automatically. Internally, rerere hashes the conflict markers to create a fingerprint, then stores the resolution as a diff from the conflicted state to the resolved state. The git rerere forget command clears a specific recorded resolution if you realize it was wrong. This is particularly valuable in workflows where you repeatedly rebase a feature branch onto a frequently-changing main branch.
In production, advanced conflict resolution involves multiple layers. Custom merge drivers defined in .gitattributes handle file-type-specific merging: a merge driver for package-lock.json can regenerate the lockfile instead of merging it, a driver for .pbxproj files (Xcode project files) uses specialized tooling, and a 'union' driver concatenates both sides (useful for changelog files). Visual merge tools like VS Code's built-in merge editor, IntelliJ's three-pane merge tool, KDiff3, and Beyond Compare provide side-by-side visualization with the ancestor in the center pane. The git mergetool command launches your configured tool for each conflicted file. Teams dealing with monorepos or many parallel branches often combine rerere with automated CI-driven merge conflict detection, alerting developers when their branches develop conflicts with main before they attempt to merge.
A critical gotcha: rerere records resolutions silently, and a wrong resolution will be replayed silently too. Always verify rerere-resolved files with git diff --staged before committing. Another trap: the default merge conflict style without diff3 is genuinely ambiguous for many conflicts, leading to incorrect resolutions. Enabling diff3 or zdiff3 globally should be standard practice for every Git user. Also, custom merge drivers specified in .gitattributes must be configured in each developer's local git config as well, which is a distribution challenge similar to hooks. Document the required config in your project's contributing guide.