How could I force mergetool GUI (KDiff3) to be always shown?
Asked Answered
F

7

34

How could I force the mergetool GUI to be always shown and disable any automatic resolving?

Sometimes when there is a conflict during a merge and I use the mergetool, it simply immediately returns after I hit Enter on question "Hit return to start merge resolution tool (kdiff3)" and no GUI is shown and the conflict appears to be resolved.

I have Git configured to use KDiff3 as the mergetool now, but it happened also when I have codecompare as the mergetool specified. I know that there is an option "Auto save and quit on merge without conflicts" in KDiff3, which could theoretically cause the described behaviour, but I have this option disabled/unchecked all the time.

Also, there is the trustExitCode option directly in Git mergetool gitconfig, which I have set to true, but even if I set it to false, the GUI is not shown.

I am not sure who does the auto resolving anyway. Mergetool in some preprocessing or KDiff3?

I am running on Windows and have the Git-extensions installed.

Similar question specific to KDiff3, was asked also here: Kdiff3 won't open with mergetool command

Feoffee answered 10/3, 2013 at 10:59 Comment(0)
I
36

Git has --auto hard coded as a command-line option to KDiff3, which causes the GUI not to show up if all conflicts are auto-resolvable by KDiff3. In the KDiff3 settings you can specify command line options to ignore, but putting --auto there did not work for me.

As a workaround I configured my own variant of KDiff3 as the merge tool:

git config --global mergetool.kdiff3NoAuto.cmd "kdiff3 --L1 \"\$MERGED (Base)\" --L2 \"\$MERGED (Local)\" --L3 \"\$MERGED (Remote)\" -o \"\$MERGED\" \"\$BASE\" \"\$LOCAL\" \"\$REMOTE\""

This is very similar to what Git uses by default for KDiff3, but without the --auto flag.

Now you can call git mergetool -t kdiff3NoAuto or configure kdiff3NoAuto as mergetool globally and KDiff3 will always show up when resolving conflicts.

Regarding the second part of your question, if you really want to disable any automatic resolving, just add --qall to the kdiff3 command line above. But then you have to manually resolve all changes in the file manually, even the ones that did not result in a Git conflict. The best scenario would be: KDiff3 shows how Git merged the files and leaves the conflicts open for the user to choose.

Isabellisabella answered 4/4, 2013 at 13:44 Comment(4)
Wauu, that's great. Thanks! You might consider to answer the linked question as well or put some comment comment there as it is probably exactly the same problem in the end.Feoffee
Thanks. I have linked to this answer in the other question.Isabellisabella
Adding '--auto' to the ignored command line option worked for me with KDiff3 0.9.98 (64bit). Settings menu -> Configure KDiff3 -> Integration tab. The auto resolved info dialog appears, but then the resulting merge is displayed, allowing further editing.Chinkapin
@bobesponja Why not add your solution as an answer? :)Estimable
T
5

Bob esponja's comment to the accepted answer worked perfectly for me using KDiff3 0.9.98.

Add --auto to Command line options to ignore: under

Settings | Configure KDiff3... | Integration tab.

KDiff3 comes up with the Conflicts dialog indicating Nr of unsolved conflicts: 0, but then you have can inspect/modify the merged state as needed.

A bit more convenient than configuring your own variant as it will work as intended whether from git mergetool, Source Tree or whatever tool engages mergetool.

Tennessee answered 24/4, 2020 at 18:44 Comment(2)
NOTE THE DOUBLE-DASH: '--auto'. All the defaults Kdiff3 had already use a single dash (implying '-auto'), which I tried first... but single-dash did not work for me.Newsdealer
The accepted answer does work. However, this answer also works AND does so without requiring extra git configuration, or using special flags.Pylos
F
3

The behavior of git mergetool is entirely dependent on the merge tool chosen and the command line Git passes to it. Therefore, to change its behavior, you need to find a command line that does what you want and configure Git to use that command line.

I had this question myself (specifically in regard to KDiff3), and PiQuer's answer got me part of the way, but it got me to thinking. There ought to be a way to replicate Git's default behavior exactly for KDiff3 except without the --auto option (which is what causes KDiff3 not to display the GUI).

It looks like the source for the default command for the KDiff3 merge tool is in the file git/mergetools/kdiff3. That looks like a shell script, so we ought to be able to copy it exactly! Putting that on one line, removing --auto, and escaping things gives us this:

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"

The base_present and merge_tool_path variables are not specifically mentioned in the Git documentation as being available to use in mergetool.<tool>.cmd, so it is possible at some point in the future that this command may not work as-is. However, they could easily be replaced with a command to test whether BASE refers to a file that exists, and a hard-coded path for KDiff3, respectively.

Note that the above command replaces the default command for Git's kdiff3 merge tool rather than creating a separate one.

Regarding a couple of other points in the original question:

  • The trustExitCode setting tells Git whether the exit code of the merge tool is a proper indication of whether the merge was successful. It will not affect the behavior of the merge tool but rather the behavior of Git once the merge tool has exited. See the manual for git-mergetool.
  • The automatic resolution you are seeing after typing git mergetool is all done by the merge tool itself. git mergetool merely invokes the external tool on the file versions that need to be merged.
Felafel answered 28/2, 2017 at 22:59 Comment(3)
How do I undo this? I executed the command, now kdiff3 doesn't open at all anymore, and I realised that the command is probably Linux-only while I'm on Windows. How do I go back to default behavior?Ballew
You use git config --unset to remove settings. If you used the exact command I gave above, then git config --global --unset mergetool.kdiff3.cmd will remove just that setting. This setting definitely works fine on Windows. I mostly use Git on Windows. It am not sure why you experienced a problem. One thing that may be needed for this to work (depending on your system) is to set mergetool.kdiff3.path to the full path to KDiff3.Felafel
I was wrong. I didn't realize that I was actually in the WSL/Ubuntu environment of Windows 10, where I can't use kdiff3. So after exiting WSL, on Windows I ended up using the solution of PiQuer (so I wouldn't overwrite the kdiff3 command again) which works, but I trust that your solution would also work. Thanks.Ballew
R
1

The simplest approach I've found is:

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'

For reference, see the long-standing default directly in the source on GitHub, which I've changed only by removing --auto.

If you run into any problems, restore the default with:

git config --global --unset mergetool.kdiff3.cmd
git config --global --unset difftool.kdiff3.cmd
Rowell answered 14/12, 2021 at 6:29 Comment(1)
The thing I like most here is the quote style which makes it a lot more readable than having to escape double quotes within double quotes.Fremantle
M
0

Instead of configuring mergetool which is called only when there is a conflict, simply set up a merge driver with KDiff3:

git config merge.kdiff.driver 'kdiff3  "%O" "%A" "%B" -o "%A" --L1 "Nearest Common ancestor"  -L2 "Working Copy" --L3 "Version from Other Branch"'

You can make this driver global by adding --global. But you need to add a .gitattribute in your repository:

*  merge=kdiff
Mackay answered 20/5, 2016 at 16:1 Comment(0)
E
0

If the problem strictly relates to unwanted conflict auto-resolution...

Once KDiff3 has opened, you could just press a Merge / Set Deltas to Conflicts from the menu, and the state gets updated to a beautiful, man-driven conflict resolution problem.

Erb answered 20/3, 2019 at 9:17 Comment(1)
git mergetool --tool=kdiff3 ?Erb
I
0

With newer kdiff3 versions, it seems no longer possible to avoid the auto-merge by adding "--auto" to the list of ignored commands. According to https://kdiff3.sourceforge.net/doc/documentation.html, the "ignore" feature is there to prevent kdiff3 from aborting with an error if an unknown command line option is received. "--auto" is not an unknown command line option, so it will be handled in any case. I suspect that it used to be some buggy behavior that the ignore-filter was applied before evaluating any command line options, which could then be used to filter out even the known and valid command line options.

Inn answered 21/7 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.