Thursday, March 27, 2014

How to resolve huge merge conflicts?

Let's say you and another company have both modified a single long file, and the automatic resolution by git merge only results in a huge mess of "<<<" sections. You need to take matters in your own hands, and here is how.

Identifying files that need manual resolution

They first appear when you pull or merge:

git pull https://github.com/OtherCompany/CmisSync.git
[...]
Auto-merging CmisSync.Lib/Cmis/Database.cs
CONFLICT (content): Merge conflict in CmisSync.Lib/Cmis/Database.cs
[...]


If you want to test see the list again, just use git status:

git status
[...]
    both modified:      CmisSync.Lib/Cmis/Database.cs
[...]

Getting all necessary data

First, identify the ancestor, the commit from which the two branches have split:

git merge-base gds2-master master
1ae00e720522a8f099e8ec3dae0b34e3a8a603cd

There will be 4 versions involved:
- Ancestor
- Theirs
- My version before the merge
- The result version
Note that we don't keep Git's failed merge attempt.

git show 1ae00e720522a8f099e8ec3dae0b34e3a8a603cd:CmisSync.Lib/Cmis/Database.cs > /tmp/ancestor
git show gds2-master:CmisSync.Lib/Cmis/Database.cs > /tmp/theirs
git show master:CmisSync.Lib/Cmis/Database.cs > CmisSync.Lib/Cmis/Database.cs
cp CmisSync.Lib/Cmis/Database.cs /tmp/original

Merging


Then a three-way merge tool that allows editing.
There does not seem to be any such tool yet, so I use a combination of kdiff3 and meld:

kdiff3 /tmp/ancestor /tmp/theirs CmisSync.Lib/Cmis/Database.cs &
meld /tmp/original CmisSync.Lib/Cmis/Database.cs &

For each of their changes that you want to benefit from:
  1. Copy/paste the change from kdiff3's middle pane to Meld's right pane,
  2. Save,
  3. Refresh in kdiff3.
That's it!
Now you can mark the conflict as solved:

git add CmisSync.Lib/Cmis/Database.cs

Nicolas Raoul

No comments: