When resolving merge conflicts in git, it is, of course, critical that the finally committed result has been manually reviewed to be sensible, complete, and correct. This is why it is particularly absurd that (as of writing, and for many years prior) git always includes the --auto
argument when invoking KDiff3 as its mergetool. This causes KDiff3 to save and exit, without allowing the user to review the results of its automatic merge, if it has decided upon unambiguous resolutions for every change.
Note this doesn't imply that KDiff3 decided upon the correct resolution for every change. I've been burned by this on more than one occasion. Don't get me wrong: I'm not saying KDiff3's choices are regularly wrong (they're typically very good). But it is not sufficiently reliable that it can be left to operate without supervision by default—yet, that is how git chooses to operate it.
Now, I realise it's still possible to review the contents of the git index before committing the merge result, but that's considerably less convenient than reviewing at the time of the merge itself: you lose the ability to see where individual changes originated from. And if you're doing a big merge, it's not so easy to keep track of the files you already went through in cases where KDiff3 didn't automatically merge all changes, to avoid needlessly reviewing them a second time.
I am not the first to encounter this problem. Sadly, suggestions to use the “Command line options to ignore” setting in KDiff3 simply failed to function for me. What did finally work were the suggestions to just overrule git's default invocation of KDiff3 entirely, by manually configuring mergetool and difftool commands like so:
git config --global mergetool.kdiff3.cmd 'if $base_present; then "$merge_tool_path" --L1 "$MERGED (Base)" --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" >/dev/null 2>&1; else "$merge_tool_path" --L1 "$MERGED (Local)" --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE" >/dev/null 2>&1; fi'
git config --global difftool.kdiff3.cmd '"$merge_tool_path" --L1 "$MERGED (A)" --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" >/dev/null 2>&1'
These do exactly the same thing as git's default invocations would, minus the --auto
nonsense.
For Windows installs it is slightly different, but the intent is the same. It might not actually be possible to set this up via commands due to quoting/escaping rules, but your global git config (git config --global --edit
) should include this:
[difftool "kdiff3"]
cmd = \""C:/Program Files/KDiff3/bin/kdiff3.exe\"" --L1 \"$MERGED (A)\" --L2 \"$MERGED (B)\" \"$LOCAL\" \"$REMOTE\" >/dev/null 2>&1
trustExitCode = false
[mergetool "kdiff3"]
cmd = "if $base_present; then \""C:/Program Files/KDiff3/bin/kdiff3.exe"\" --L1 \"$MERGED (Base)\" --L2 \"$MERGED (Local)\" --L3 \"$MERGED (Remote)\" -o \"$MERGED\" \"$BASE\" \"$LOCAL\" \"$REMOTE\" >/dev/null 2>&1; else \""C:/Program Files/KDiff3/bin/kdiff3.exe"\" --L1 \"$MERGED (Local)\" --L2 \"$MERGED (Remote)\" -o \"$MERGED\" \"$LOCAL\" \"$REMOTE\" >/dev/null 2>&1; fi"
trustExitCode = false
[diff]
tool = kdiff3
guitool = kdiff3
[merge]
tool = kdiff3
Those last parts set KDiff3 to be the default tool. And all that assumes KDiff3 is installed to the default location.
Comment to add? Send me a message: <brendon@quantumfurball.net>