17

I had set up my git to use P4Merge as the diff tool, as described here. So, git diff will trigger the P4Merge.

However, sometimes I find working with the UNIX diff is faster and more efficient (because no GUI involved). How do I set up git so that I can easily choose which diff tool I would like to trigger? Is this possible? For example:

$ git diff     # to trigger P4Merge
$ git difftool # to trigger UNIX diff

My git config --list:

code.editor=vi
merge.tool=p4merge
mergetool.extMerge.cmd=extMerge $BASE $LOCAL $REMOTE $MERGED
mergetool.extMerge.trustexitcode=false
diff.external=extDiff
mergetool.prompt=false
mergetool.keepbackup=false
mergetool.p4merge.path=/usr/local/bin/p4merge
1
  • The URL here mentioned above is broken, can you please update?
    – realPK
    Commented Aug 15, 2014 at 0:49

5 Answers 5

10

You can just explicitly indicate which difftool you want to use. I have this in my ~/.gitconfig:

[diff]
    tool = vimdiff

[difftool "winmerge"]
    name = WinMerge
    trustExitCode = true
    cmd = "/c/Users/rkasten/Google\\ Drive/Apps/WinMerge/WinMergeU.exe" -u -e $LOCAL $REMOTE

And then I have the following aliases setup:

alias gdt='git difftool'
alias gdtw='git difftool --tool=winmerge'

Using masukomi's example, you could just add the following to your gitconfig:

[difftool "Kaleidoscope"]
    cmd = ksdiff --whatevs

And use alias gdtk='git difftool --tool=Kaleidoscope' to use Kaleidoscope.

All this works in git 2.7.

5

Git can easily manage a visual and command line diff. No fancy tweaking is required

git diff (by default) uses unix diff

if you want to use a visual diffing tool as well the correct way to set it up is in your ~/.gitconfig file with a section like this:

[difftool "Kaleidoscope"]
    cmd = ksdiff --partial-changeset --relative-path \"$MERGED\" -- \"$LOCAL\" \"$REMOTE\"

What comes after the cmd = is specific to your particular visual diffing application.

It is not standard practice to manipulate git diff to send content to a visual diffing app. As such, the question seeks an answer that is 100% backwards from the built in functionality.

See the git-difftool man page for more details.

5

UPDATE: If like OP you want to make git difftool invoke the default diff functionality instead of an external tool then simple version at the end of this answer works. However the method I prefer and recommend if you just want multiple diff tools is the .gitconfig file method as described in DrStrangeprok's answer.


You can set the following bash script as your external editing tool.
(ie: replace the contents of extDiff with it)
It is not quite as simple as git diif1 / git diff2 but it works.

EDIT: see bottom for a simpler version

#!/bin/bash

# Parameters from git:
# 1    2        3       4        5        6       7
# path old-file old-hex old-mode new-file new-hex new-mode

CONTINUE=1
while [ $CONTINUE == 1 ]
do

    # Present Options
    echo "1. P4Merge"
    echo "2. Unix diff"
    echo "3. Cancel"
    echo -n "Choose diff tool[1]: "

    # Read in user choice
    read -n 1 OPTION

    # move down a line
    echo ""

    # if user didn't enter a choice default to 1
    if [[ $OPTION == "" ]] ; then
        OPTION="1"
    fi

    # Launch diff tool based on OPTION
    case $OPTION in
        1) /Applications/p4merge.app/Contents/MacOS/p4merge "$2" "$5" ; CONTINUE=0 ;;
        2) diff "$2" "$5" ; CONTINUE=0 ;;
        3) exit ;;
        *) echo "\"$OPTION\" is not valid " ;;
    esac


    # This sleep has two purposes
    # 1) on an invalid choice it delays the menu just a hair
    # 2) keeps this script alive long enough that git will not just move onto the next file
    #    instantly if diffing multiple files.
    sleep 1

done

Simple Version without a menu
add this function to your .bashrc if you use 'git difftool' then it will use the default diff

function git {

    if [[ $1 == "difftool" ]] ; then
        git config --global --unset diff.external
        command git diff
        git config --global diff.external extDiff
    else
        command git "$@"
    fi

}
3
  • Anything simpler than this? :)
    – moey
    Commented Jan 27, 2012 at 16:52
  • 1
    Yes actually, I just thought of another way much more like what you wanted, I edited my answer above
    – Appak
    Commented Jan 27, 2012 at 17:21
  • @Appak you probably need to make it command git "$@" instead because otherwise git commit -am "all done" won't work Commented Sep 18, 2012 at 13:39
1

It'd be nice if Git can somehow have different settings for each, but if not, to expand on Appak's answer, the following added to .bashrc can invoke text diff, opendiff (FileMerge), or P4Merge diff:

function git {
    if [ $1 == "tdiff" ]
    then
        git config --global --unset diff.external
        command git diff
    elif [ $1 == "diff" ]
    then
        git config --global diff.external ~/bin/git-diff-opendiff
        command git diff
    elif [ $1 == "pdiff" ]
    then
        git config --global diff.external ~/bin/git-diff-p4diff
        command git diff
    else
        command git "$@"
    fi
}

and just make sure you have the proper git-diff-opendiff and git-diff-p4diff already set up (they are the shell scripts).

0

You write

However, sometimes I find working with the UNIX diff is faster and more efficient (because no GUI involved). How do I set up git so that I can easily choose which diff tool I would like to trigger?

So the answer to this question should simply take advantage of git's ability to differentiate between console- and gui-based diff tools and not rely on writing an external command.

By providing the -g option to git difftool, the diff tool to use will be read from the configured variable diff.guitool instead of diff.tool.

[alias]
    d = difftool -g
    dc = difftool
[diff]
    guitool = p4merge
    tool = diff

That's it. You would invoke your gui tool p4merge using git d <file1> <file2> or similar and your console tool using git dc <file1> <file2>.

Not the answer you're looking for? Browse other questions tagged or ask your own question.