5

I like to use git on cygwin, but the only downside I have is when I want to git difftool I cannot use anything useful. git diff is fine for me most of the time, but sometimes I'd like to use winmerge to view these diffs via git difftool is there some way to set this up?

erikvold
  • 15,988
  • 11
  • 54
  • 98
  • 2
    http://stackoverflow.com/questions/255202/how-do-i-view-git-diff-output-with-visual-diff-program is a good start for that kind of feature. – VonC Aug 29 '10 at 17:26
  • Note: to be tested in cygwin, but [Git 2.5 is now aware of Winmerge as a diff or merge tool](http://stackoverflow.com/a/30699239/6309) – VonC Jun 07 '15 at 22:53

1 Answers1

11

For cygwin, the SO question "How can I configure Mercurial to use WinMerge for merges, under cygwin?" can be applied to git (when combining the following winmerge script with the older question "use Winmerge inside of Git to file diff")

#!/bin/sh
"/cygdrive/c/Program Files/WinMerge/WinMergeU.EXE" /e /ub /dl other /dr local `cygpath -aw $1` `cygpath -aw $2` `cygpath -aw $3`

Process

You have more details in this article "Git + WinMerge + Cygwin" (from Thiru Thirunavukarasu):
(but I would still recommend the WinMergeU.exe options from above)

Add the following lines to your .gitconfig file:

  [diff]
    tool = winmerge
  [difftool "winmerge"]
    cmd = git-difftool-winmerge-wrapper.sh \"$LOCAL\" \"$REMOTE\"
  [difftool]
    prompt = false

The last option (prompt = false) is optional. You can omit it if you do want Git to prompt you before opening each diff.

Create a file named git-difftool-winmerge-wrapper.sh and place it in your path.
I just dropped it in my home directory. You can change the default Cygwin path to include your home directory by modifying the .bash_profile file (also in your home directory) and adding PATH=${PATH}:${HOME}

Add the following to git-difftool-winmerge-wrapper.sh:

  #!/bin/sh
  echo "Launching WinMergeU.exe \"$(cygpath -aw "$1")\" \"$(cygpath -aw "$2")\""
  if [ -f "$1" -a -f "$2" ]
  then
    "C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -u -wl -dl "Base" -dr "Mine" "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
  else
    echo "skipping as one file doesn't exist"
  fi

(again, do some testing with those WinMerge options)


Scripts

If you want to go "all WinMerge", both for diff and merge git functions, you have this gist page to follow from ecerulm (Ruben Laguna):

diffmerge-diff.sh

#!/bin/sh
# Use SourceGear DiffMerge as mergetool for git in cygwin.
#   git config --global mergetool.diffmerge.cmd "diffmergetool.sh \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""
#   git config --global mergetool.diffmerge.trustExitCode false
#   git difftool -t diffmerge branch1..branch2

# Reference: http://www.tldp.org/LDP/abs/abs-guide.pdf

library=githelperfunctions.sh

#[ -f $library ] && . $library
. $library

echo Launching DiffMerge.exe - diffmerge-diff.sh: 

set_path_vars "$1" "$2" "$3" "$4"

echo "$diffmergewinpath" -t1=FROM_VERSION -t2=TO_VERSION --caption=$caption $localwinpath $remotewinpath
"$diffmergewinpath" -t1=FROM_VERSION -t2=TO_VERSION --caption="$caption" "$localwinpath" "$remotewinpath"

diffmerge-merge.sh

#!/bin/sh
# Use SourceGear DiffMerge as mergetool for git in cygwin.
#   git config --global mergetool.diffmerge.cmd "diffmergetool.sh \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""
#   git config --global mergetool.diffmerge.trustExitCode false
#   git mergetool -t diffmerge

# Reference: http://www.tldp.org/LDP/abs/abs-guide.pdf

library=githelperfunctions.sh

#[ -f $library ] && . $library
. $library

echo Launching DiffMerge.exe - diffmerge-merge.sh: 

set_path_vars "$1" "$2" "$3" "$4"

"$diffmergewinpath" --merge -t1=FROM_VERSION -t2=MERGED -t3=TO_VERSION --result="$mergedwinpath" --caption="$caption" "$localwinpath" "$basewinpath" "$remotewinpath"

unix2dos "$merged"

githelperfunctions.sh

# Helper functions


convert_path () {
    file=$1

    if [ "$file" == '/dev/null' ] || [ ! -e "$file" ]
        then 
           file="/tmp/nulla"
           `echo "">$file`
    fi
    echo `cygpath -w -a "$file"`
}


set_path_vars () {
    local=$1
    remote=$2
    base=$3
    merged=$4

    echo ========= Cygwin paths =======
    echo "LOCAL   :  $local"
    echo "REMOTE  :  $remote"
    echo "BASE    :  $base"
    echo "MERGED  :  $merged"

    localwinpath=$(convert_path "$local")
    remotewinpath=$(convert_path "$remote")
    basewinpath=$(convert_path "$base")
    mergedwinpath=$(convert_path "$merged")

    echo ========= Win paths =======
    echo "LOCAL   :  $localwinpath"
    echo "REMOTE  :  $remotewinpath"
    echo "BASE    :  $basewinpath"
    echo "MERGED  :  $mergedwinpath"

    caption=`basename "$merged"`
    diffmergewinpath="C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe"
    winmergewinpath="C:/Program Files/WinMerge/WinMergeU.exe"
#   diffmergewinpath=`cygpath -u C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe`
#   winmergewinpath=`cygpath -u \"C:\Program Files\WinMerge\WinMergeU.exe\"`
}

winmerge-diff.sh

#!/bin/sh
# Use winmerge as mergetool for git in cygwin.
#   git config --global difftool.winmerge.cmd "winmerge-diff.sh \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\""
#   git config --global mergetool.winmerge.trustExitCode false
#   git difftool -t winmerge branch1..branch2   

# Reference: http://www.tldp.org/LDP/abs/abs-guide.pdf
# Reference: http://winmerge.org/docs/manual/CommandLine.html


library=githelperfunctions.sh

#[ -f $library ] && . $library
. $library

echo Launching winmerge.exe - winmerge-diff.sh: 

set_path_vars "$1" "$2" "$3" "$4"

"$winmergewinpath" /dl "LOCAL.$caption" /dr "TO_VERSION.$caption" "$localwinpath" "$remotewinpath" 

winmerge-merge.sh

#!/bin/sh
# Use winmerge as mergetool for git in cygwin.
#   git config --global mergetool.winmerge.cmd "winmerge-merge.sh \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""
#   git config --global mergetool.winmerge.trustExitCode false
#   git mergetool -t diffmerge

# Reference: http://www.tldp.org/LDP/abs/abs-guide.pdf
# Reference: http://winmerge.org/docs/manual/CommandLine.html

library=githelperfunctions.sh

#[ -f $library ] && . $library
. $library

echo Launching winmerge.exe - winmerge-merge.sh: 


set_path_vars "$1" "$2" "$3" "$4"

# -- use WinMergeU conflictFile
"$winmergewinpath" "$mergedwinpath"
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • As a result of some spaces in my folder structures, I had to alter the if test in the the git-difftool-winmerge-wrapper.sh to `if [ -f "$1" -a -f "$2" ]` or the test would fail; unsure if this is version specific. – Chris Mar 08 '17 at 09:18
  • 1
    @Chris Thank you. I have edited the answer accordingly. – VonC Mar 08 '17 at 09:21