有没有办法在 git 中使用 Winmerge 来做 Diffs?
9 回答
2015 年 6 月更新,6 年后:
如“ git mergetool winmerge ”中所述,一个简单的git config diff.tool winmerge
就足够了。
Git 2.5+(2015 年第二季度)现在意识到 Winmerge 是一种差异或合并工具!
原始答案(2009-2012)
(msysgit,1.6.5,DOS 会话)
第一部分(使用 winmerge)在“如何使用可视差异程序查看 'git diff' 输出? ”中进行了描述。
C:\myGitRepo>git config --replace --global diff.tool winmerge
C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
C:\myGitRepo>git config --replace --global difftool.prompt false
存储在winmerge.sh
您的目录部分中PATH
:
#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -e -u -dl "Local" -dr "Remote" "$1" "$2"
(请参阅WinMerge 命令行选项)
git difftool
现在将启动 WinMerge。
如果要git diff
启动 WinMerge,只需设置:
set GIT_EXTERNAL_DIFF=winmerge.sh
但真正的附加值来自于使用相同的差异工具在一批中呈现所有差异而不是按顺序呈现它们的能力,这迫使您一次关闭一个文件的差异工具窗口。
2012 年 6 月更新(两年半后):
比较目录而不是逐个文件将很快可用:
请参阅[ANNOUNCE] Git 1.7.11.rc1:
”
git difftool
“学习了“--dir-diff
”选项来生成外部差异工具,该工具可以在填充两个临时目录后一次比较两个目录层次结构,而不是每个文件对运行一次外部工具的实例。
有关详细信息,请参阅“补丁difftool
:教difftool
处理目录差异”和答案“ Git 分支的目录比较”。
目录脚本的原始差异工具(2009 年 12 月)
正如Seba Illingworth在他的回答中提到的那样,脚本 git-diffall.sh (也放在路径中)可以做到这一点:
#!/bin/sh
git diff --name-only "$@" | while read filename; do
git difftool "$@" --no-prompt "$filename" &
done
但这仅适用于为n 个文件打开n 个窗口(如果您尝试使用WinMerge 选项,它将无法正常工作,因为 difftool 过早删除了临时文件)-s
这就是为什么我喜欢GitDiff.bat 的方法 - 使用 GI 进行功率差异,它允许您在选择一个文件来检查其内部差异之前查看有差异的文件列表。
我已将其调整为仅使用 DOS 命令
@echo off
setlocal
if "%1" == "-?" (
echo GitDiff - enables diffing of file lists, instead of having to serially
echo diff files without being able to go back to a previous file.
echo Command-line options are passed through to git diff.
echo If GIT_FOLDER_DIFF is set, it is used to diff the file lists. Default is windff.
goto END
)
if "%GIT_DIFF_COPY_FILES%"=="" (
rd /s /q %TEMP%\GitDiff
mkdir %TEMP%\GitDiff
mkdir %TEMP%\GitDiff\old
mkdir %TEMP%\GitDiff\new
REM This batch file will be called by git diff. This env var indicates whether it is
REM being called directly, or inside git diff
set GIT_DIFF_COPY_FILES=1
set GIT_DIFF_OLD_FILES=%TEMP%\GitDiff\old
set GIT_DIFF_NEW_FILES=%TEMP%\GitDiff\new
set GIT_EXTERNAL_DIFF=%~dp0\GitDiff.bat
echo Please wait and press q when you see "(END)" printed in reverse color...
call git diff %*
if defined GIT_FOLDER_DIFF (
REM This command using GIT_FOLDER_DIFF just does not work for some reason.
%GIT_FOLDER_DIFF% %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
if exist "%ProgramFiles%\Beyond Compare 2\BC2.exe" (
set GIT_FOLDER_DIFF="%ProgramFiles%\Beyond Compare 2\BC2.exe"
"%ProgramFiles%\Beyond Compare 2\BC2.exe" %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
"%ProgramFiles(x86)%\WinMerge\WinMergeU.exe" -r -e -dl "Local" -dr "Remote" %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
REM diff is called by git with 7 parameters:
REM path old-file old-hex old-mode new-file new-hex new-mode
copy %TEMP%\%~nx2 %GIT_DIFF_OLD_FILES%\%1
copy %5 %GIT_DIFF_NEW_FILES%
:END
它不足以处理不同目录中同名的文件,但它让您大致了解什么是可能的:
这里只会打开一个 WinMerge,文件列表具有内部差异。您可以单击要检查的那些,然后简单地ESC关闭所有WinMerge-diff
会话。
我在 2 个地方使用第一部分时遇到了麻烦,并将其修复如下
用于设置 winmerge.cmd 的第二个命令需要在 cmdline 上添加一个额外的斜杠(在 $LOCAL 和 $REMOTE 之前),否则 cygwin 正在替换 cmdline 中的变量
C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
将 winmerge.sh 文件更改为(没有这个,出现正确路径无效错误)
#!/bin/sh echo Launching WinMergeU.exe: "$(cygpath -aw "$1")" "$(cygpath -aw "$2")" "$PROGRAMFILES/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
我有一个脚本,它将使用不需要单独的 .sh 文件存在的适当参数在 Git 配置中设置 Diff 和 Merge 工具。它似乎对我来说工作得很好。
git config --global diff.tool winmerge
git config --global difftool.prompt false
git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
git config --global merge.tool winmerge
git config --global mergetool.prompt false
git config --global mergetool.winmerge.trustExitCode true
git config --global mergetool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""
注意- 引用整个 .cmd 部分,以便参数将正确地列在 .gitconfig 中
由于线程变得混乱和分叉,这里是针对 msysgit Git Windows 的目录列表“--dir-diff”WinMerge 方法的综合说明。
第 1 步- 在路径可访问的位置(例如 /home/bin/winmerge.sh)创建一个名为 winmerge.sh 的文件,其中包含以下内容。
#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -r -ub -dl "Remote" -dr "Local" "$1" "$2"
第 2 步- 在 Git Bash 中键入以下命令以指示 git 使用 winmerge.sh 作为 difftool(这些选项存储在 /home/.gitconfig 中):
git config --replace --global diff.tool winmerge
git config --replace --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
git config --replace --global difftool.prompt false
第 3 步- 现在您可以通过在 Git Bash 中键入以下命令来启动 WinMerge diff 进行测试:
git difftool --dir-diff
第 4 步- 为了更快地访问,通过将此行添加到主文件夹中的 .bashrc 来为此命令创建一个别名(如果文件不存在,则使用此行创建 .bashrc 文件):
alias diffdir='git difftool --dir-diff'
第 5 步- 现在您只需在 Git Bash 中输入以下命令即可快速查看 WinMerge 中的差异
diffdir
无配置:
git difftool --tool winmerge
假设:
- 已安装 Winmerge
- 从“git version 2.12.0.windows1”或更高版本安装了 Windows 的 Git(尽管早期版本的 git 可能已经引入了该命令)。
在 Windows 上,您可以这样做:
1) 打开 .gitconfig 文件。它位于您的主目录中:c:\users\username.gitconfig
2)添加下面的行。注意包含 winmerge 路径的单引号:
[diff]
tool = winmerge
[difftool "winmerge"]
cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$LOCAL" "$REMOTE"
[difftool]
prompt = false
[merge]
tool = winmerge
[mergetool "winmerge"]
cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" \"$MERGED\" \"$REMOTE\"
[mergetool]
keepBackup = false
trustExitCode = false
我对为什么将解决方案呈现为 DOS 批处理文件感到困惑,因为我的 Git 安装带有 bash shell。我也无法从 bash 运行 DOS 上下文,因此我尝试调整以前在 bash 上下文中共享的内容。
由于git diff
似乎为每个文件运行一次指定的命令,因此我将解决方案拆分为两个 bash 脚本:
首先,配置gitprepdiff.sh
为前面提到的difftool
#!/bin/sh
#echo ...gitprepdiff.sh
cp -v $1 "$TMP/GitDiff/old/$2"
cp -v $2 "$TMP/GitDiff/new"
我还注意到git configure
命令的结果可以直接在C:\Users\<username>\.gitconfigure
gitdiff.sh
然后在您通常调用的命令行中运行git diff
#!/bin/sh
#echo Running gitdiff.sh...
DIFFTEMP=$TMP/GitDiff
echo Deleting and re-creating $DIFFTEMP...
rm -rf $DIFFTEMP;
mkdir $DIFFTEMP;
echo Creating $DIFFTEMP/old...
mkdir $DIFFTEMP/old;
echo Creating $DIFFTEMP/new...
mkdir $DIFFTEMP/new;
git diff --name-only "$@" | while read filename; do
git difftool "$@" --no-prompt "$filename";
done
"$PROGRAMFILES\WinMerge\WinMergeU.exe" -r -e -dl "Repository" -dr "Working" $LOCALAPPDATA\\Temp\\1\\GitDiff\\old $LOCALAPPDATA\\Temp\\1\\GitDiff\\new
另外值得注意的是,在我的安装中,/tmp
(在 bash 中)映射到%LOCALAPPDATA%\Temp\1\
(在 Windows 中),所以这就是我在调用 WinMerge 时使用后者的原因。
我可以在这里看到很多冗长且令人困惑的答案,因此在 windows10 上发布了 2021 年对我有用的简化和最小版本
git config diff.tool winmerge
git config --replace --global difftool.prompt false
git config --global diff.tool winmerge
git config --global difftool.winmerge.cmd "\"$PROGRAMFILES\\WinMerge\\WinMergeU.exe\" -u -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
git config --global difftool.prompt false
根据WinMerge 命令行手册:“参数以正斜杠 (/) 或破折号 (-) 字符为前缀”