30

How do I make git automatically run git mergetool for any merge conflict? This should apply for all merges, using merge, rebase, pull, etc.

5
  • 1
    Maybe you can use a githook, e.g. post-checkout (I don't know if it is actually invoked during a merge. post-merge requires a successful merge) Commented Aug 3, 2012 at 8:35
  • 1
    @TobiasKienzler You might be on to something. If you can figure out a working solution I'll give you the bounty for this question. Commented Jul 14, 2013 at 23:03
  • @QuinnStrahl I don't think there currently exists a hook which is executed before each of the various commands leading to a merge, so rospov's wrapper is probably the easiest solution. That or modifying the git source to implement a pre-merge hook functionality, in which case you could of course simply have git run mergetool on conflicts depending on a config setting anyway... Commented Jul 15, 2013 at 7:54
  • 1
    Hm, okay. Thanks for the help. I think I'll submit a patch. Commented Jul 15, 2013 at 13:17
  • @QuinnStrahl In case you have submitted a Patch by now, I would appreciate a link here :) Commented Dec 12, 2016 at 19:57

3 Answers 3

8

You cannot (yet) make git do this.


This may or may not be an acceptable workaround.

Create a function in your ~/.bashrc:

git() { if [[ $1 == "merge" ]] || [[ $1 == "rebase" ]] || [[ $1 == "pull" ]]; then command git "$@" rc=$? if [[ $rc == 1 ]]; then echo "There are conflicts, better run git-mergetool!!!" # There might be some other condition that returns a '1', # if so you can add another check like this: # if grep Conflicts $(git --git-dir)/MERGE_MSG; command git mergetool fi else command git "$@" fi } 

Mergetool isn't invoked when it merges:

$ git merge non_conflicting_branch Merge made by the 'recursive' strategy. bar | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bar 

Mergetool is called when there are conflicts:

$ git merge conflicting_branch Auto-merging foo CONFLICT (content): Merge conflict in foo Automatic merge failed; fix conflicts and then commit the result. There are Conflicts, better run git-mergetool!!! 

Mergetool is not called on other errors:

$ git merge adasds fatal: adasds - not something we can merge 
Sign up to request clarification or add additional context in comments.

12 Comments

This isn't making git automatically open mergetool, this is making the shell do it.
Why the downvote? This is essentially a cleaner way to implement rosipov's answer.
How is it cleaner? You're missing some kinds of conflicts (such as git stash pop). Since he doesn't filter by command, that's not an issue. As you note yourself, the current code will launch git mergetool on any error with 1 status.
I cannot say for sure if there are any other errors with a return value of 1 for the commands in question as git return values are generally undocumented. I have yet to find one that wasn't a merge conflict though.
@QuinnStrahl git cannot do it (yet), so is it a wrong answer to accomplish it through the shell?
|
4

You could always use alias

alias 'git-merge'='git merge && git mergetool' alias 'git-rebase'='git rebase && git mergetool' alias 'git-pull'='git pull && git mergetool' 

And/or write a helper script along these lines

#/bin/bash git $* [ "$(git ls-files –abbrev –unmerged | wc -l)" -gt 0 ] && git mergetool 

and then

alias git='~/.git/git-script' 

There is no direct way of invoking mergetool, because it is only one of several ways to merge (see "HOW TO RESOLVE CONFLICTS" in man 1 git-merge).

2 Comments

As I mentioned, I only want to call mergetool if there is a conflict. The "only one of several ways to merge" argument isn't convincing. Yes, there are multiple ways, but it's quite reasonable to want to choose one as the default.
git mergetool won't do anything if there is no conflict.
2

As far as I know, there is no porcelain way to do it.

You can have a wrapper around git like this (file git_mergetool.sh, on your path, +x):

#!/bin/bash SEARCH="CONFLICT" OUTPUT=$(git "$@" 2>&1 | tee /dev/tty) if `echo ${OUTPUT} | grep -i "${SEARCH}" 1>/dev/null 2>&1` then git mergetool fi 

Then add alias:

echo alias git=\"git_mergetool.sh\" >> ~/.bashrc 

Every time you invoke git, the wrapper will check if the word "CONFLICT" pops up. If it does - wrapper launches mergetool.

This can be improved by adding more precise phrase to $SEARCH (like "Automatic merge failed; fix conflicts and then commit the result.") as well as by checking if first argument ($1) is in the list of commands resulting in merge conflict (pull, merge, etc...). Otherwise you will end up parsing a lot of unnecessary data if git command output is too long.

3 Comments

Is it possible without effectively aliasing git?
@QuinnStrahl You can name script git (without file extension) and put in on your path before the actual git executable. But it is pretty much just another way of aliasing. So no, I don't know of a way to accomplish that without aliasing git.
Should be somewhat workable, but the CONFLICT regex needs improvement. I think it will currently pick it up anywhere, even in e.g. diff output. At least you can filter by line position (e.g. an anchor), and maybe expand the text.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.