How do I make git automatically open the mergetool if there is a merge conflict?
Asked Answered
S

3

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.

Ster answered 5/4, 2012 at 16:18 Comment(5)
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)Friederike
@TobiasKienzler You might be on to something. If you can figure out a working solution I'll give you the bounty for this question.Scuffle
@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...Friederike
Hm, okay. Thanks for the help. I think I'll submit a patch.Scuffle
@QuinnStrahl In case you have submitted a Patch by now, I would appreciate a link here :)Landman
A
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
Abney answered 17/7, 2013 at 7:35 Comment(12)
This isn't making git automatically open mergetool, this is making the shell do it.Scuffle
Why the downvote? This is essentially a cleaner way to implement rosipov's answer.Abney
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.Ster
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.Abney
@QuinnStrahl git cannot do it (yet), so is it a wrong answer to accomplish it through the shell?Abney
@Abney Yes. The question was how to make git do it, not how to make the shell do it.Scuffle
+1, @Quinn: as @Abney noted, git cannot do it. Don't be pedantic; the OP wants a way to run git mergetool automatically, and I highly doubt he cares whether it's git or the shell doing it.Yalonda
@BrianVandenberg Given that OP personally (and rightfully) criticised this answer and has yet to accept it (or any of the other answers that fail to address the question as literally asked), I'm inclined to disagree with you. Furthermore, this answer was posted after I placed a bounty that specifically requested a git-native method.Scuffle
@QuinnStrahl, I've seen people be openly hostile of answers they get to questions they ask, even when the answers are good ones. That doesn't validate (or invalidate) the criticism. Furthermore, there's a list of thousands of questions marked as unanswered because the OP either doesn't bother or doesn't care.Yalonda
@BrianVandenberg It was not my objective to convince you that hostility evidences the validity of criticism. Perhaps the OP forgot to accept this answer after pointing out why it was not good one, but I don't think it likely.Scuffle
-1: I'm with Quinn. It does not do it using git, which was part of the question - I do find the answer using an alias more appropriate.Landman
The answer is "You cannot (yet) make git do this", the rest was a helpful suggestion on how you might get the same effect. I will edit the answer to make that clearer.Abney
M
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).

Moskow answered 5/4, 2012 at 16:46 Comment(2)
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.Ster
git mergetool won't do anything if there is no conflict.Moskow
C
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.

Confucius answered 12/7, 2013 at 16:52 Comment(3)
Is it possible without effectively aliasing git?Scuffle
@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.Confucius
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.Ster

© 2022 - 2024 — McMap. All rights reserved.