Sunday, May 1, 2011

How do I setup DiffMerge with msysgit / gitk?

I've just started using Git and it's possible I've missed something obvious, but here goes:

  • I'm using msysgit 1.6.2.2 on Windows XP
  • While installing, I picked option 1 to "Use Git Bash only"

I'm trying to put together a wrapper script that I can use to replace the built in git diff with DiffMerge. Based on this thread on SO, I created the following batch file:

@echo off
REM ---- Switch forward slashes to back slashes ----
set oldW=%2
set oldW=%oldW:/=\%
set newW=%5
set newW=%newW:/=\%

REM ---- Launch DiffMerge ----
"C:/Programs/SourceGear/DiffMerge/DiffMerge.exe" /title1="Old Version" %oldW% /title2="New Version" %newW%

I placed the bat file under %GIT_INSTALL%/cmd and edited my .gitconfig file as follows:

[diff]
external = C:/Programs/git/cmd/git-diff-wrapper.bat

If i launch Git Bash and execute git diff HEAD HEAD~ -- myfile

I get a message File (\dev\null) not found - which given I'm on Windows is not surprising.

Pressing on, I launched gitk and under Edit>Preferences, I chose the same wrapper script. Trying the "external diff" option for a particular file gives the cryptic error message Unknown Option "

Clearly, I have no idea what I'm doing anymore so any help would be much appreciated.

From stackoverflow
  • I just experienced a somewhat similar experience with setting Notepad++ as my external editor with msysgit1.6.2.2.

    The key was to realize the wrapper was not a DOS script, but a /bin/sh script.

    So try to put in your ".bat" (even though it is not exactly a bat script, the extension is not important here):

    #!/bin/sh
    
    # diff is called by git with 7 parameters:
    # path old-file old-hex old-mode new-file new-hex new-mode
    
    "C:/Programs/SourceGear/DiffMerge/DiffMerge.exe" /title1="Old Version" "$2" /title2="New Version" "$5" | cat
    

    Do not worry about making all the '\' go '/': it is done by the Git scripts calling the external diff tool.

    I did not test it with DiffMerge, but with WinMerge, it works just fine, both from a DOS session or a Git Shell.

    #!/bin/sh
    "C:/Program Files/WinMerge/WinMergeU.exe" -e -ub "$2" "$5" | cat
    

    (with the '-e' option, I have just ot type on 'ESC' to close and quit the diff tool: that works great!)


    alt textaverage_geek adds in the comments:

    added the '/bin/sh' header and tried running git diff again.
    This time the error is:
    Unexpected parameter 'C:/Docume~/avggeek/LOCALS~1/Temp/.diff_b08444
    Is there a way to see what are the parameters getting passed when I call git diff ?

    1/ There actually is a way to see what are the parameters getting passed!
    Add the following line in the C:\Program Files\Git\libexec\git-core\git-sh-setup file:

    git_editor() {
        : "${GIT_EDITOR:=$(git config core.editor)}"
        : "${GIT_EDITOR:=${VISUAL:-${EDITOR}}}"
        case "$GIT_EDITOR,$TERM" in
        ,dumb)
         echo >&2 "No editor specified in GIT_EDITOR, core.editor, VISUAL,"
         echo >&2 "or EDITOR. Tried to fall back to vi but terminal is dumb."
         echo >&2 "Please set one of these variables to an appropriate"
         echo >&2 "editor or run $0 with options that will not cause an"
         echo >&2 "editor to be invoked (e.g., -m or -F for git-commit)."
         exit 1
         ;;
        esac
    #### ADD THIS LINE BELOW
        echo >&2 "editor is ${GIT_EDITOR:=vi} $@."
    #### END ADDITION ABOVE
        eval "${GIT_EDITOR:=vi}" '"$@"'
    }
    

    You will see what editor is being called, with what parameter.

    Now, regarding the "Unexpected parameter" part:
    I did have the same kind of error when I called WinMergeU.exe with "/e /ub" instead of "-e -ub", so first question is:
    Are you sure that the "/title1" bit could not be used as "-title1" or "-t1" or "--title1" or "--t1" ? That is what Is can see from the chapter 9 "Command Lines Arguments" of the pdf documentation of DiffMerge.
    If not, I suspect some double quotes are in order for delimiting properly the different parameters. Something like:

    "/title1="Old Version"" "$2" "/title2="New Version"" "$5"
    or
    "/title1=\"Old Version\"" "$2" "/title2=\"New Version\"" "$5"
    

    But my money would rather be on the "-title1" or "-t1" form:

    -t1="Old Version" "$2" -t2="New Version" "$5"
    

    should work just fine.

    average_geek : I added the `/bin/sh` header and tried running git diff again. This time the error is: Unexpected parameter 'C:/Docume~`/avggeek/LOCALS~1/Temp/.diff_b08444 Is there a way to see what are the parameters getting passed when I call `git diff`?
  • VonC - switching to -t1 and -t2 fixed the errors. Diffmerge now works for git bash :)

    After a little bit of poking at the gitk patch that added External Diff support, I realized that it's calling an External Diff program directly with the two files as arguments. So I modified gitk>Edit>Preferences and put the following command directly into the External Diff Tool option:

    "C:/Programs/SourceGear/DiffMerge/DiffMerge.exe" -t1="Old Version" -t2="New Version"
    

    Now I have DiffMerge working for gitk too :-)

    VonC : Awesome, it did work! And thank you for the feedback on gitk. +1
  • This works for me with as follows:

    In ~/.gitconfig:

    [merge]
    tool = diffmerge
    [mergetool "diffmerge"]
    cmd = \"C:/Program Files/git/cmd/git-diffmerge-merge.sh\" \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
    trustExitCode = false
    

    In C:\Program Files\Git\cmd\git-diffmerge-merge.sh:

    #!/bin/sh
    
    localPath="$2"
    basePath="$1"
    remotePath="$3"
    resultPath="$4"
    
    if [ ! -f $basePath ]
    then
        basePath="~/diffmerge-empty"
    fi
    
    "C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" --merge --result="$resultPath" "$localPath" "$basePath" "$remotePath" --title1="Mine" --title2="Merged: $4" --title3="Theirs"
    

    Part of the credit goes to http://therightstuff.de/2009/01/28/Setting-Up-SourceGear-DiffMerge-With-Git.aspx ;)

0 comments:

Post a Comment