当我输入 时git diff
,我想使用我选择的视觉差异工具(Windows 上的 SourceGear “diffmerge”)查看输出。我如何配置 git 来做到这一点?
26 回答
从 Git1.6.3 开始,您可以使用git difftool 脚本:请参阅下面的答案。
也许这篇文章会对你有所帮助。以下是最好的部分:
指定外部差异工具有两种不同的方法。
第一个是您使用的方法,通过设置 GIT_EXTERNAL_DIFF 变量。但是,该变量应该指向可执行文件的完整路径。此外,由 GIT_EXTERNAL_DIFF 指定的可执行文件将使用一组固定的 7 个参数调用:
path old-file old-hex old-mode new-file new-hex new-mode
由于大多数 diff 工具将需要不同的参数顺序(并且仅需要一些),因此您很可能必须指定一个包装脚本,而后者又会调用真正的 diff 工具。
我更喜欢的第二种方法是通过 "git config" 配置外部差异工具。这是我所做的:
1)创建一个包装脚本“git-diff-wrapper.sh”,其中包含类似
-->8-(snip)--
#!/bin/sh
# diff is called by git with 7 parameters:
# path old-file old-hex old-mode new-file new-hex new-mode
"<path_to_diff_executable>" "$2" "$5" | cat
--8<-(snap)--
如您所见,只有第二个(“旧文件”)和第五个(“新文件”)参数将传递给 diff 工具。
2) 类型
$ git config --global diff.external <path_to_wrapper_script>
在命令提示符处,替换为“git-diff-wrapper.sh”的路径,因此您的 ~/.gitconfig 包含
-->8-(snip)--
[diff]
external = <path_to_wrapper_script>
--8<-(snap)--
确保使用正确的语法来指定包装脚本和差异工具的路径,即使用正斜杠而不是反斜杠。就我而言,我有
[diff]
external = \"c:/Documents and Settings/sschuber/git-diff-wrapper.sh\"
在 .gitconfig 和
"d:/Program Files/Beyond Compare 3/BCompare.exe" "$2" "$5" | cat
在包装脚本中。注意尾随的“猫”!
(我想 ' | cat
' 仅适用于某些可能无法返回正确或一致的返回状态的程序。如果您的差异工具具有明确的返回状态,您可能想尝试不使用尾随猫)
该
cat
命令是必需的,因为diff(1)
如果文件不同,默认情况下会以错误代码退出。
Git 期望外部 diff 程序仅在发生实际错误时以错误代码退出,例如内存不足。
通过管道输出git
到cat
非零错误代码被屏蔽。
更有效的是,程序可以只exit
使用 0 的参数运行。)
那(上面引用的文章)是通过配置文件(而不是通过环境变量)定义的外部工具的理论。
在实践中(仍然是外部工具的配置文件定义),您可以参考:
- 如何使用 msysgit / gitk 设置 DiffMerge?它说明了 MsysGit 和 gitk 的 DiffMerge 和 WinMerge 的具体设置
- 如何设置编辑器以在 Windows 上使用 Git?用于将 Notepad++ 定义为外部编辑器。
要完成上面我之前的“diff.external”配置答案:
正如Jakub 所说,Git1.6.3 引入了git difftool,最初于 2008 年 9 月提出:
USAGE= '[--tool=tool] [--commit=ref] [--start=ref --end=ref] [--no-prompt] [file to merge]'
(请参阅--extcmd
此答案的最后一部分)
$LOCAL
包含起始修订版$REMOTE
中的文件内容,并包含结束修订版中文件的内容。
$BASE
包含工作中文件的内容
它基本上
git-mergetool
被修改为在 git index/worktree 上操作。此脚本的常见用例是当您有暂存或未暂存的更改并且您希望在并排差异查看器中查看更改(例如
xxdiff
,tkdiff
等)。
git difftool [<filename>*]
另一个用例是当您想查看相同的信息但正在比较任意提交时(这是 revarg 解析可能更好的部分)
git difftool --start=HEAD^ --end=HEAD [-- <filename>*]
最后一个用例是当您想将当前工作树与 HEAD 以外的其他内容(例如标签)进行比较时
git difftool --commit=v1.0.0 [-- <filename>*]
注意:从 Git 2.5 开始,git config diff.tool winmerge
就足够了!
参见“ git mergetool winmerge ”
从 Git 1.7.11 开始,您可以选择--dir-diff
生成外部差异工具,这些工具可以在填充两个临时目录后一次比较两个目录层次结构,而不是为每个文件对运行一次外部工具实例。
在 Git 2.5 之前:
difftool
使用自定义差异工具进行配置的实际案例:
C:\myGitRepo>git config --global diff.tool winmerge
C:\myGitRepo>git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
C:\myGitRepo>git config --global difftool.prompt false
将 winmerge.sh 存储在 PATH 的目录部分中:
#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"C:/Program Files/WinMerge/WinMergeU.exe" -u -e "$1" "$2" -dl "Local" -dr "Remote"
如果您有其他工具(kdiff3、P4Diff、...),请创建另一个 shell 脚本和相应的difftool.myDiffTool.cmd
配置指令。
然后您可以轻松地使用diff.tool
配置切换工具。
您还拥有Dave 的此博客条目以添加其他详细信息。
(或者这个问题的winmergeu
选项)
此设置的有趣之处在于winmerge.sh
脚本:您可以自定义它以考虑特殊情况。
例如,请参阅下面的David Marble的回答,以获取处理以下内容的示例:
- 源或目标中的新文件
- 删除源或目标中的文件
正如Kem Mason在他的回答中提到的那样,您还可以通过使用以下--extcmd
选项来避免任何包装:
--extcmd=<command>
指定用于查看差异的自定义命令。
git-difftool
忽略配置的默认值并$command $LOCAL $REMOTE
在指定此选项时运行。
例如,这就是gitk
能够运行/使用任何diff
工具的方式。
使用新的 git difftool,只需将其添加到您的.gitconfig文件中即可:
[diff]
tool = any-name
[difftool "any-name"]
cmd = "\"C:/path/to/my/ext/diff.exe\" \"$LOCAL\" \"$REMOTE\""
(可选)还添加:
[difftool]
prompt = false
另请查看diffall,这是我编写的一个简单脚本,用于扩展令人讨厌的(IMO)默认差异行为,即以串行方式打开每个。
Windows 上的全局 .gitconfig 位于%USERPROFILE%\.gitconfig
我对此有一个补充。我喜欢定期使用不支持作为默认工具之一的差异应用程序(例如万花筒),通过
git difftool -t
我也喜欢将默认值设置diff
为常规命令行,因此设置GIT_EXTERNAL_DIFF
变量不是一个选项。
diff
您可以使用以下命令一次性使用任意应用程序:
git difftool --extcmd=/usr/bin/ksdiff
它只是将 2 个文件传递给您指定的命令,因此您可能也不需要包装器。
基于VonC处理文件删除和添加的答案,使用以下命令和脚本:
git config --global diff.tool winmerge
git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\" \"$BASE\""
git config --global difftool.prompt false
这与将其放入全局文件.gitconfig 相同:
[diff]
tool = winmerge
[difftool "winmerge"]
cmd = winmerge.bat "$LOCAL" "$REMOTE" "$BASE"
[difftool]
prompt = false
然后将以下内容放入文件winmerge.sh中,该文件必须位于您的路径中:
#!/bin/sh
NULL="/dev/null"
if [ "$2" = "$NULL" ] ; then
echo "removed: $3"
elif [ "$1" = "$NULL" ] ; then
echo "added: $3"
else
echo "changed: $3"
"C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$1" "$2"
fi
Windows/ MSYS Git解决方案
阅读答案后,我发现了一种更简单的方法,即只更改一个文件。
使用参数 2 和 5 创建一个批处理文件来调用您的 diff 程序。该文件必须在您的路径中的某个位置。(如果您不知道它在哪里,请将其放在C:\windows中。)例如,将其称为“gitdiff.bat”。我的是:
@echo off REM This is gitdiff.bat "C:\Program Files\WinMerge\WinMergeU.exe" %2 %5
将环境变量设置为指向您的批处理文件。例如:
GIT_EXTERNAL_DIFF=gitdiff.bat
。或通过 PowerShell 键入git config --global diff.external gitdiff.bat
.重要的是不要使用引号或指定任何路径信息,否则它将不起作用。这就是为什么gitdiff.bat必须在你的路径中。
现在,当您键入“git diff”时,它将调用您的外部差异查看器。
如果您通过Cygwin执行此操作,则可能需要使用cygpath:
$ git config difftool.bc3.cmd "git-diff-bcomp-wrapper.sh \$LOCAL \$REMOTE"
$ cat git-diff-bcomp-wrapper.sh
#!/bin/sh
"c:/Program Files (x86)/Beyond Compare 3/BComp.exe" `cygpath -w $1` `cygpath -w $2`
在查看了其他一些外部差异工具后,我发现diff
IntelliJ IDEA(和 Android Studio)中的视图对我来说是最好的。
第 1 步 - 设置 IntelliJ IDEA 以从命令行运行
如果您想使用 IntelliJ IDEA 作为您的差异工具,您应该首先设置 IntelliJ IDEA,以便按照此处的说明从命令行运行:
在 macOS 或 UNIX 上:
- 确保 IntelliJ IDEA 正在运行。
- 在主菜单上,选择
Tools | Create Command-line Launcher
。创建启动器脚本对话框打开,其中包含启动器脚本的建议路径和名称。您可以接受默认值,也可以指定自己的路径。请注意它,因为稍后您将需要它。在 IntelliJ IDEA 之外,将启动器脚本的路径和名称添加到您的路径中。
在 Windows 上:
- 在 Path 系统环境变量中指定 IntelliJ IDEA 可执行文件的位置。在这种情况下,您将能够从任何目录调用 IntelliJ IDEA 可执行文件和其他 IntelliJ IDEA 命令。
第 2 步 - 配置 git 以使用 IntelliJ IDEA 作为 difftool
按照此博客文章中的说明进行操作:
重击
export INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
PATH=$IDEA_HOME $PATH
鱼
set INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
set PATH $INTELLIJ_HOME $PATH
现在将以下内容添加到您的 git 配置中:
[merge]
tool = intellij
[mergetool "intellij"]
cmd = idea merge $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE") $(cd $(dirname "$BASE") && pwd)/$(basename "$BASE") $(cd $(dirname "$MERGED") && pwd)/$(basename "$MERGED")
trustExitCode = true
[diff]
tool = intellij
[difftool "intellij"]
cmd = idea diff $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE")
您可以尝试使用git difftool
或git difftool HEAD~1
这适用于我在 Windows 7 上。不需要中间sh脚本
.gitconfig 的内容:
[diff]
tool = kdiff3
[difftool]
prompt = false
[difftool "kdiff3"]
path = C:/Program Files (x86)/KDiff3/kdiff3.exe
cmd = "$LOCAL" "$REMOTE"
对以前的好答案的简短总结:
git difftool --tool-help
git config --global diff.tool <chosen tool>
git config --global --add difftool.prompt false
然后通过键入(也可以指定文件名)来使用它:
git difftool
介绍
作为参考,我想包括我对VonC 的回答的变体。请记住,我使用的是 MSys 版本的 Git(此时为 1.6.0.2)并修改了 PATH,并从 PowerShell(或 cmd.exe)而不是 Bash shell 运行 Git 本身。
我引入了一个新命令,gitdiff
. 运行此命令会临时重定向git diff
以使用您选择的可视差异程序(与 VonC 永久执行此操作的解决方案相反)。这使我可以同时拥有默认的 Git 差异功能 ( git diff
) 和视觉差异功能 ( gitdiff
)。两个命令都采用相同的参数,例如,为了直观地区分特定文件中的更改,您可以键入
gitdiff path/file.txt
设置
请注意,$GitInstall
它用作安装 Git 的目录的占位符。
创建一个新文件,
$GitInstall\cmd\gitdiff.cmd
@echo off setlocal for /F "delims=" %%I in ("%~dp0..") do @set path=%%~fI\bin;%%~fI\mingw\bin;%PATH% if "%HOME%"=="" @set HOME=%USERPROFILE% set GIT_EXTERNAL_DIFF=git-diff-visual.cmd set GIT_PAGER=cat git diff %* endlocal
创建一个新文件,
$GitInstall\bin\git-diff-visual.cmd
(用[visual_diff_exe]
您选择的 diff 程序的完整路径替换占位符)@echo off rem diff is called by git with 7 parameters: rem path old-file old-hex old-mode new-file new-hex new-mode echo Diffing "%5" "[visual_diff_exe]" "%2" "%5" exit 0
你现在完成了。从 Git 存储库中运行
gitdiff
现在应该为每个更改的文件调用您的可视差异程序。
这是一个适用于 Windows 的批处理文件 - 假设 DiffMerge 安装在默认位置,处理 x64,根据需要处理正反斜杠替换,并且能够自行安装。应该很容易用您最喜欢的差异程序替换 DiffMerge。
安装:
gitvdiff --install
gitvdiff.bat:
@echo off
REM ---- Install? ----
REM To install, run gitvdiff --install
if %1==--install goto install
REM ---- Find DiffMerge ----
if DEFINED ProgramFiles^(x86^) (
Set DIFF="%ProgramFiles(x86)%\SourceGear\DiffMerge\DiffMerge.exe"
) else (
Set DIFF="%ProgramFiles%\SourceGear\DiffMerge\DiffMerge.exe"
)
REM ---- Switch forward slashes to back slashes ----
set oldW=%2
set oldW=%oldW:/=\%
set newW=%5
set newW=%newW:/=\%
REM ---- Launch DiffMerge ----
%DIFF% /title1="Old Version" %oldW% /title2="New Version" %newW%
goto :EOF
REM ---- Install ----
:install
set selfL=%~dpnx0
set selfL=%selfL:\=/%
@echo on
git config --global diff.external %selfL%
@echo off
:EOF
安装融合:
# apt-get install meld
然后选择它作为 difftool:
$ git config --global diff.tool meld
如果要在控制台中运行它,请键入:
$ git difftool
如果要使用图形模式,请键入:
$ git mergetool
输出将是:
'git mergetool' will now attempt to use one of the following tools:
meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse
diffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiff
Merging:
www/css/style.css
www/js/controllers.js
Normal merge conflict for 'www/css/style.css':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (meld):
所以只需按下Enter使用融合(默认)。这将打开图形模式。进行魔法保存并按下解决合并的按钮。就这样。
对于如何在 1.6.3 之前的 Git 版本上配置差异工具的 Linux 版本(1.6.3 将差异工具添加到 Git),这是一个很棒的简明教程。
简单来说:
第 1 步:将其添加到您的 .gitconfig
[diff]
external = git_diff_wrapper
[pager]
diff =
第 2 步:创建一个名为 git_diff_wrapper 的文件,将其放在 $PATH 中的某个位置
#!/bin/sh
vimdiff "$2" "$5"
在 Mac OS X 上,
git difftool -t diffuse
在 Git 文件夹中为我完成这项工作。对于安装Diffuse,可以使用端口 -
sudo port install diffuse
您可以使用git difftool
.
例如,如果你有Meld,你可以编辑分支master
并devel
通过:
git config --global diff.external meld
git difftool master..devel
以下可以从这里的其他答案中收集到,但对我来说这很困难(信息太多),所以这里是 tkdiff 的“只需输入”答案:
git difftool --tool=tkdiff <path to the file to be diffed>
你可以用你最喜欢的 diffing 工具的可执行文件名替换 tkdiff。只要(例如 tkdiff),(或您最喜欢的差异工具)在您的 PATH 中,它就会被启动。
我在这里尝试了花哨的东西(使用 tkdiff),但对我没有任何用处。所以我写了下面的脚本,tkgitdiff。它做我需要它做的事情。
$ cat tkgitdiff
#!/bin/sh
#
# tkdiff for git.
# Gives you the diff between HEAD and the current state of your file.
#
newfile=$1
git diff HEAD -- $newfile > /tmp/patch.dat
cp $newfile /tmp
savedPWD=$PWD
cd /tmp
patch -R $newfile < patch.dat
cd $savedPWD
tkdiff /tmp/$newfile $newfile
我在 Ubuntu 上使用Kompare :
sudo apt-get install kompare
比较两个分支:
git difftool -t kompare <my_branch> master
我已经在文件~/.gitconfig
中使用这个位很长时间了:
[diff]
external = ~/Dropbox/source/bash/git-meld
与git-meld
:
#!/bin/bash
if [ "$DISPLAY" = "" ];
then
diff $2 $5
else
meld $2 $5
fi
但是现在我厌倦了总是在图形环境中使用Meld,并且使用这个设置调用普通的差异并不是一件容易的事,所以我切换到了这个:
[alias]
v = "!sh -c 'if [ $# -eq 0 ] ; then git difftool -y -t meld ; else git difftool -y $@ ; fi' -"
使用此设置,类似这样的工作:
git v
git v --staged
git v -t kompare
git v --staged -t tkdiff
而且我仍然可以保持良好的旧状态git diff
。
如果您碰巧已经有一个与文件类型关联的差异工具(例如,因为您安装了带有差异查看器的 TortoiseSVN),您可以将常规git diff
输出通过管道传输到“临时”文件,然后直接打开该文件而无需知道关于观众的任何事情:
git diff > "~/temp.diff" && start "~/temp.diff"
将其设置为全局别名效果更好:git what
[alias]
what = "!f() { git diff > "~/temp.diff" && start "~/temp.diff"; }; f"
如果您不是命令行用户,那么如果您安装TortoiseGit,您可以右键单击文件以获取带有“Diff later”选项的 TortoiseGit 子菜单。
当你在第一个文件上选择它时,你可以右键单击第二个文件,进入 TortoiseGit 子菜单并选择“Diff with ==yourfilehere==”。这将为结果提供 TortoiseGit 合并 GUI。