我该如何在msysgit/gitk中设置DiffMerge?

21

我刚开始使用Git,可能会错过一些显而易见的东西,但是我会尽力描述:

  • 我正在Windows XP上使用msysgit 1.6.2.2
  • 在安装时,我选择了选项1 "仅使用Git Bash"

我正在试图编写一个包装脚本,以便我可以用DiffMerge替换内置的git diff。根据这个线程中的说明,我创建了以下批处理文件:

@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%

我将bat文件放在%GIT_INSTALL%/cmd下,并编辑了我的.gitconfig文件,如下所示:

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

如果我打开 Git Bash 并执行 git diff HEAD HEAD~ -- myfile 命令,会出现一个错误提示:File (\dev\null) not found。鉴于我使用的是 Windows 系统,这个错误并不奇怪。

然后,我尝试着在 Gitk 中选择了相同的包装脚本(wrapper script),并在 Edit>Preferences 下启用了 "external diff" 选项进行文件比较。但是,当我尝试针对某个文件使用 "external diff" 选项时,却收到了一条晦涩的错误信息:Unknown Option "

显然,我已经迷失在了这些命令中,所以任何帮助都将不胜感激。


刚刚按照要求加入了一些“DiffMerge”特定的元素,回答完毕。 - VonC
4个回答

15

我在互联网上寻找这个答案,尝试了所有上面和其他地方提供的解决方案。我可以使合并部分工作而不是差异部分,或者反过来。最终我采用自己从互联网上获得的信息拼凑出了我自己的简单解决方案,适用于我。它不需要任何脚本,只需要编辑您的.gitconfig文件,该文件通常位于以下目录中:C:\Documents and Settings\[username]。您需要已经安装DiffMerge程序。

下面是我的.gitconfig文件的相关摘录。您只需要编辑到您版本的DiffMerge所在的路径即可。请注意,我在路径中使用了旧的DOS 8.3格式。

[diff]
    tool = diffm
[difftool "diffm"]
    cmd = "H:/PROGRA~1/SourceGear/DiffMerge/DiffMerge.exe $LOCAL $REMOTE"
    prompt = false

[merge]
    tool = diffmerge
[mergetool "diffmerge"]
    cmd = "H:/PROGRA~1/SourceGear/DiffMerge/DiffMerge.exe --merge --result=$MERGED $LOCAL $BASE $REMOTE" 
    trustExitCode = false
    keepBackup = false

如果你想这样做,你也可以使用命令 git config --replace --global [options] 来设置它。


这个简单的解决方案对我也完美地奏效。对于更近期的DiffMerge版本(3.3.1),命令路径需要更改:

    cmd = "C:/PROGRA~1/SourceGear/Common/DiffMerge/sgdm.exe ...etc..."

简单明了的解决方案值得称赞。 - Bnjmn
像@Bnjmn所说,+1是一个简单的解决方案,只需要编辑.gitconfig文件。 - JeffH
对我来说关键是将 ... /merge /replace=... 改为 ... --merge --replace=...SourceGear 的文档 似乎是错误的。 - Kenny Evitt

9
我刚刚在使用msysgit1.6.2.2时,遇到了与将Notepad++设置为我的外部编辑器类似的问题。

关键是要意识到包装器不是DOS脚本,而是/bin/sh脚本。

所以尝试在你的“.bat”中添加以下内容(即使它并不完全是一个批处理脚本,在这里扩展名并不重要):

#!/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

不用担心将所有的“\”转换为“/”:这是通过Git脚本调用外部差异工具完成的。

我没有使用DiffMerge进行测试,但是使用WinMerge,无论从DOS会话还是Git Shell中,都可以正常工作。

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

(使用'-e'选项,我只需键入'ESC'就能关闭和退出diff 工具:这很好用!)

alt textaverage_geek 在评论中补充道:

添加了 '/bin/sh' 头并尝试再次运行 git diff。
这次的错误是:
Unexpected parameter 'C:/Docume~/avggeek/LOCALS~1/Temp/.diff_b08444
是否有办法看到我调用 git diff 时传递的参数是什么?

1/ 实际上有一种方法可以查看正在传递的参数是什么!
将以下行添加到文件C:\Program Files\Git\libexec\git-core\git-sh-setup 中:

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}" '"$@"'
}

您将看到调用哪个编辑器以及使用了什么参数。
现在,关于“意外的参数”部分:
当我使用“/e /ub”而不是“-e -ub”调用WinMergeU.exe时,我也遇到了同样类型的错误,因此第一个问题是:
您确定“/title1”不能作为“-title1”或“-t1”或“--title1”或“--t1”吗? 这是从DiffMerge的pdf文档的第9章“命令行参数”中可以看到的内容。
如果不行,我怀疑需要加上双引号来正确地分隔不同的参数。类似这样:
"/title1="Old Version"" "$2" "/title2="New Version"" "$5"
or
"/title1=\"Old Version\"" "$2" "/title2=\"New Version\"" "$5"

但我更愿意使用"-title1"或"-t1"这种形式:

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

应该可以正常工作。

我添加了/bin/sh头并尝试再次运行git diff。这次的错误是: 意外参数'C:/Docume`/avggeek/LOCALS1/Temp/.diff_b08444有没有办法查看在调用git diff时传递了哪些参数? - avggeek
关键是要意识到这个包装器不是一个DOS脚本,而是一个/bin/sh脚本。对于像我这样没有激活"仅使用Git Bash"选项的人来说,它必须是一个Windows脚本(.cmd更时髦...)。与你的方式相同,但使用%2代替$2。 - PhiLho

8
以下是我的做法:
~/.gitconfig文件中添加以下内容:
[merge]
tool = diffmerge
[mergetool "diffmerge"]
cmd = \"C:/Program Files/git/cmd/git-diffmerge-merge.sh\" \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
trustExitCode = false

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"

一部分功劳归功于 http://therightstuff.de/2009/01/28/Setting-Up-SourceGear-DiffMerge-With-Git.aspx ;)


谢谢。你帮我解决了这个问题。 - Alex

4

VonC——切换到-t1和-t2修复了错误。Diffmerge现在适用于git bash :)

在对添加了外部差异支持的gitk补丁进行一番探索后,我意识到它直接使用两个文件作为参数调用了外部差异程序。因此,我修改了gitk>编辑>首选项,并将以下命令直接放入“外部差异工具”选项中:

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

现在我已经让DiffMerge能够在gitk中工作了 :-)

最新的Diffmerge路径更可能是“C:/Program Files/SourceGear/Common/DiffMerge/sgdm.exe”,而-t1/-t2不再起作用。如果你忽略这个问题,至少可以得到比较窗口。 - Ghita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接