15

Is it possible to set Git up so that I can use the three-way compare in KDiff3?

I have two branches that are far too different to auto-merge them, I simply have to check each merge point and I think the best way would be to check out the branch I want the changes from the other branch and say

git difftool HEAD_OF_OTHER_BRANCH -- .

And then select Merge File in KDiff3. After having gone through the files I'd just commit.

I have set up merge.conflictstyle and diff.conflictstyle to diff3 but KDiff3 still starts with a two-way diff. Is this possible? I guess if Git also sends the common ancestor's hash as a parameter, this is possible, but does it?

There is discussion about how to do this with SVN and BC3, but I couldn't find anything for Git and KDiff3.

Community
  • 1
  • 1
Makis
  • 12,468
  • 10
  • 62
  • 71
  • If you are trying to do a three way merge, why aren't you using mergetool (instead of difftool) ? – CB Bailey Sep 03 '10 at 13:02
  • 2
    I don't want Git to automerge anything. I did found out that maybe I could use .gitattributes to tell Git to not automerge. Still, merge will merge the whole massive system on one go, I'd rather handle this on a by-directory basis. Yes, this is a mess, but my intention is to clean it. For that I unfortunately have to do some handiwork. – Makis Sep 03 '10 at 13:24
  • @Makis: It would seem sensible to do a proper merge but use a strategy that doesn't automerge or force the 'binary' merge driver via `.gitattributes` to always leave conflicts for the user to resolve. At least this way you can use mergetool to kick off kdiff3 in the logical way. – CB Bailey Sep 03 '10 at 13:37
  • 2
    I tried that already, problem is the tree has quite a few binary files as well. And there is a ton of conflicting files, I'm a bit hesitant to go through all of them on one go. I'd rather work in smaller batches. – Makis Sep 03 '10 at 13:42
  • Why are binary files a problem? Effectively you're just trying to treat all files as binary anyway. The problem with a true merge is that you need (at some point) to make a merge commit anyway so trying to do things in stages and getting a true history are conflicting objectives. – CB Bailey Sep 03 '10 at 13:51
  • @Charles, that's sounds interesting, how do you do that ? – mb14 Sep 03 '10 at 13:54
  • @mb14: Which approach are you referring to? – CB Bailey Sep 03 '10 at 14:08
  • @Charles: a way to disable the automerge (with you binary driver ???) – mb14 Sep 03 '10 at 14:26
  • @mb14: IIRC, you can just put a `* merge = binary` line in `.gitattributes` and conflicts won't be autoresolved at all. I haven't tried it recently, though, so I might have remembered incorrectly. – CB Bailey Sep 03 '10 at 15:47
  • @Charles: I'm not actually that worried about the history at this point. It's going to be a mess anyway. Problem is, we are talking about a *large* code base which will take several people days to sort out. Doing it all in one go is just too complex, my plan was to go through the a component at a time, where possible, and run tests in-between. As for .gitignore, I tried the unset value for merge. – Makis Sep 03 '10 at 17:08

2 Answers2

10

Run this on the command line:

git config --global mergetool.kdiff3.path /path/for/your/kdiff3/binary  

Then, when solving conflicts you just have to do:

git mergetool --tool=kdiff3
Edson Medina
  • 9,862
  • 3
  • 40
  • 51
3

It seems that git diff do only a 2-way diff (which make sense to generate patch etc) except in a merging state , you have to do a merge for that. I was in a similar situation the other day and I ended up mergin using the ours strategy. That worked but wasn't ideal. Maybe we need a 'nonresolve' merging strategy which doesn't try to resolve any conflicts. You might be able to emulate that by tweaking the .git/MERGE_* files and set all the files as conflicted.
Otherwise the obvious solution is to checkout 3 different directory and run kdiff3 , but I guess you are looking for a more elegant solution

mb14
  • 22,276
  • 7
  • 60
  • 102
  • Checking to different directories would be ok, except how do you create the third dir that holds the common ancestors? As long as I work on a single repo, Git figures the common ancestors out for me. – Makis Sep 03 '10 at 13:44
  • 1
    @makis you can use the 'git merge-base' command to find the common ancestor of two commits, handy. – mb14 Sep 03 '10 at 13:46
  • Hm, so the common ancestor is the same for all files? I thought this could differ depending on when a file is edited. If it's the same for each file, then this would definitely be a workable solution. – Makis Sep 03 '10 at 13:47
  • git merge-base will give you the commit from where you fork. This commit is the same for every files indeed, but as long as you haven't cherry-picked any files between branches, that should be a good enough approximation. – mb14 Sep 03 '10 at 13:53