如何使用我喜欢的diff工具/查看器查看'git diff'输出?

当我键入git diff时,我想使用我选择的视觉差异工具(Windows上的SourceGear“扩散”)查看输出。我如何配置git来做到这一点?

501267 次浏览

从Git1.6.3开始,您可以使用git扩散工具脚本:参见我的答案在下面


也许这个文章会帮助你。以下是最好的部分:

有两种不同的方法来指定外部差异工具。

第一种是您使用的方法,通过设置GIT_EXTERNAL_DIFF变量。但是,该变量应该指向可执行文件的完整路径。此外,GIT_EXTERNAL_DIFF指定的可执行文件将使用一组固定的7个参数调用:

path old-file old-hex old-mode new-file new-hex new-mode

由于大多数diff工具需要不同的参数顺序(并且只需要一些),因此您很可能必须指定包装器脚本,这反过来又会调用真正的diff工具。

第二种方法,我更喜欢,是通过“git”配置外部diff工具配置"。这是我所做的:

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)--

如您所见,只有第二个(“old-file”)和第五个(“new-file”)参数将是传递给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的路径工具,即使用正斜杠而不是反斜杠。在我的情况下,我有

[diff]external = \"c:/Documents and Settings/sschuber/git-diff-wrapper.sh\"

在. gitconfig和

"d:/Program Files/Beyond Compare 3/BCompare.exe" "$2" "$5" | cat

在包装脚本中。注意尾随的“猫”!

(我想'| cat'仅适用于某些可能无法返回正确或一致返回状态的程序。如果您的diff工具具有显式返回状态,您可能希望尝试不带尾随猫)

Diomidis Spinellis加上在评论

cat命令是必需的,因为如果文件不同,默认情况下diff(1)会退出并显示错误代码。
Git期望外部diff程序仅在发生实际错误时退出错误代码,例如,如果它运行内存溢出。
通过将git的输出管道传输到cat,非零错误代码被屏蔽。
更有效的是,程序可以运行exit,参数为0。)


(上面引用的文章)是外部工具通过配置文件定义的理论(不是通过环境变量)。
在实践中(仍然是外部工具的配置文件定义),可以参考:

导言

作为参考,我想包括我在VonC的回答上的变体。请记住,我正在使用带有修改后的PATH的MSys版本的Git(1.6.0.2),并从PowerShell(或cmd.exe)运行Git本身,而不是Bash shell。

我引入了一个新命令gitdiff。运行此命令会暂时重定向git diff以使用您选择的可视化diff程序(而不是VonC的永久解决方案)。这使我能够同时具有默认的Git diff功能(git diff)和可视化diff功能(gitdiff)。这两个命令都采用相同的参数,例如在您可以键入的特定文件中进行可视化差异更改

gitdiff path/file.txt

设置

请注意,$GitInstall用作安装Git的目录的占位符。

  1. 创建一个新文件,$GitInstall\cmd\gitdiff.cmd

     @echo offsetlocalfor /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.cmdset GIT_PAGER=catgit diff %*endlocal
  2. 创建一个新文件,$GitInstall\bin\git-diff-visual.cmd(将[visual_diff_exe]占位符替换为您选择的diff程序的完整路径)

     @echo offrem diff is called by git with 7 parameters:rem path old-file old-hex old-mode new-file new-hex new-modeecho Diffing "%5""[visual_diff_exe]" "%2" "%5"exit 0
  3. 你现在完成了。从Git存储库中运行gitdiff现在应该为每个更改的文件调用你的可视化diff程序。

Windows解决方案/MSYS Git

阅读答案后,我发现了一种更简单的方法,只需要更改一个文件。

  1. 创建一个批处理文件来调用你的diff程序,参数2和5。这个文件必须在你的路径中的某个地方。(如果你不知道它在哪里,把它放在C:\windows。)称之为,例如,“gitdiff.bat”。我的是:

    @echo offREM This is gitdiff.bat"C:\Program Files\WinMerge\WinMergeU.exe" %2 %5
  2. 将环境变量设置为指向您的批处理文件。例如:GIT_EXTERNAL_DIFF=gitdiff.bat。或通过键入git config --global diff.external gitdiff.bat通过PowerShell。

    重要的是不要使用引号或指定任何路径信息,否则它将无法工作。这就是为什么gitdiff.bat必须在您的路径中。

现在,当您键入“git diff”时,它将调用您的外部diff查看器。

这是一个适用于Windows的批处理文件-假设DiffMerge安装在默认位置,处理x64,根据需要处理前进到反斜杠替换,并且能够自行安装。应该很容易用您最喜欢的diff程序替换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=%2set oldW=%oldW:/=\%set newW=%5set newW=%newW:/=\%

REM ---- Launch DiffMerge ----
%DIFF% /title1="Old Version" %oldW% /title2="New Version" %newW%
goto :EOF


REM ---- Install ----:installset selfL=%~dpnx0set selfL=%selfL:\=/%@echo ongit config --global diff.external %selfL%@echo off

:EOF

完成我上面的"diff.external"配置答案

作为雅库布提到,Git1.6.3引入了git扩展工具,最初是在2008年9月提出的:

USAGE='[--tool=tool] [--commit=ref] [--start=ref --end=ref] [--no-prompt] [file to merge]'
(参见答案最后一部分中的--extcmd

$LOCAL包含起始版本的文件内容,$REMOTE包含结束版本的文件内容。
$BASE包含wor

中文件的内容

它基本上是git-mergetool修改以在git索引/工作树上操作。

此脚本的通常用例是当您有暂存或未暂存的更改并且您希望在并排差异查看器(例如xxdifftkdiff等)中查看更改时。

git difftool [<filename>*]

另一个用例是当您希望看到相同的信息但正在比较任意提交时(这是Revarg解析可能更好的部分)

git difftool --start=HEAD^ --end=HEAD [-- <filename>*]

最后一个用例是当您想将当前工作树与HEAD以外的东西(例如标签)进行比较时

git difftool --commit=v1.0.0 [-- <filename>*]

注意:从Git 2.5开始,#0就足够了!
返回“git mergetool win合并

自Git 1.7.11以来,您有选项--dir-diff,以便生成外部diff工具,这些工具可以在填充两个临时目录后一次比较两个目录层次结构,而不是每个文件对运行一次外部工具的实例。


在Git 2.5之前:

使用自定义diff工具配置difftool的实用案例:

C:\myGitRepo>git config --global diff.tool winmergeC:\myGitRepo>git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""C:\myGitRepo>git config --global difftool.prompt false

winmerge.sh存储在PATH的目录部分:

#!/bin/shecho Launching WinMergeU.exe: $1 $2"C:/Program Files/WinMerge/WinMergeU.exe" -u -e "$1" "$2" -dl "Local" -dr "Remote"

如果你有另一个工具(KDiF3, P4Diff,…),创建另一个外壳脚本和适当的difftool.myDiffTool.cmd配置指令。然后您可以使用diff.tool配置轻松切换工具。

您还有这个Dave的博客条目来添加其他细节。
(或这个问题winmergeu选项)

此设置的兴趣在于#0Script:您可以自定义它以考虑特殊情况。

例如,请参阅David Marble下面的答案,了解处理以下内容的示例:

  • 新的文件在来源或目的地
  • 删除文件在来源或目的地

正如凯姆梅森他的回答中提到的,您也可以使用#0选项避免任何包装器

--extcmd=<command>

指定用于查看差异的自定义命令。git-difftool忽略配置的默认值并在指定此选项时运行$command $LOCAL $REMOTE

这就是为什么#0能够运行/使用任何#1工具

使用新的git扩散工具,只需将其添加到. gitconfig文件中即可:

[diff]tool = any-name[difftool "any-name"]cmd = "\"C:/path/to/my/ext/diff.exe\" \"$LOCAL\" \"$REMOTE\""

可选地,还添加:

[difftool]prompt = false

另请查看差异,一个简单的脚本,我写的扩展恼人的(IMO)默认差异行为打开每个在串行。

Windows上的Global. gitconfig位于%USERPROFILE%\.gitconfig

对于如何在1.6.3之前的Git版本上配置diff工具的Linux版本(1.6.3向Git添加了Diff工具),这个是一个很棒的简洁教程。

简言之:

第1步:将其添加到您的. gitconfig

[diff]external = git_diff_wrapper[pager]diff =

第2步:创建一个名为git_diff_wrapper的文件,将其放在$PATH中的某个位置

#!/bin/sh
vimdiff "$2" "$5"

我在Ubuntu上使用Kompare

sudo apt-get install kompare

比较两个分支:

git difftool -t kompare <my_branch> master

试试这个解决方案:

$ meld my_project_using_git

Meld理解Git并提供围绕最近更改的导航。

如果您通过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`

您可能想尝试xd,它是Git/SVN diff的GUI包装器。它是没有本身是一个diff工具。

当您想运行git diffsvn diff时,您运行xd,它会显示一个文件列表、一个预览窗口,您可以启动任何您喜欢的diff工具,包括tkdiff、xxdiff、gvimdiff、Emacs(edff)、XEmacs(edff)、Meld弥漫KompareKDiff3。您还可以运行任何自定义工具。

不幸的是,该工具不支持Windows。

披露:我是这个工具的作者。

基于VonC的回答来处理文件删除和添加,请使用以下命令和脚本:

git config --global diff.tool winmergegit 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/shNULL="/dev/null"if [ "$2" = "$NULL" ] ; thenecho "removed: $3"elif [ "$1" = "$NULL" ] ; thenecho "added: $3"elseecho "changed: $3""C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$1" "$2"fi

我还有一个补充。我喜欢经常使用不支持作为默认工具之一的diff应用程序(例如万花筒),通过

git difftool -t

我也希望默认的diff只是常规命令行,所以设置GIT_EXTERNAL_DIFF变量不是一个选项。

您可以使用以下命令一次性使用任意diff应用程序:

git difftool --extcmd=/usr/bin/ksdiff

它只是将2个文件传递给您指定的命令,因此您可能也不需要包装器。

如果您在Mac上并且安装了Xcode,那么您安装了文件合并。终端命令是opendiff,因此您可以执行:

git difftool -t opendiff

这适用于我在Windows 7上。不需要中间sh脚本

. gitconfig的内容:

    [diff]tool = kdiff3
[difftool]prompt = false
[difftool "kdiff3"]path = C:/Program Files (x86)/KDiff3/kdiff3.execmd = "$LOCAL" "$REMOTE"

我在文件~/.gitconfig中使用了很长时间:

[diff]external = ~/Dropbox/source/bash/git-meld

使用git-meld

#!/bin/bashif [ "$DISPLAY" = "" ];thendiff $2 $5elsemeld $2 $5fi

但是现在我厌倦了总是在图形环境中使用Meld,并且使用此设置调用正常的diff并不是微不足道的,所以我切换到这个:

[alias]v =  "!sh -c 'if [ $# -eq 0 ] ; then git difftool -y -t meld ; else git difftool -y $@ ; fi' -"

有了这个设置,像这样的工作:

git vgit v --stagedgit v -t komparegit v --staged -t tkdiff

我仍然可以保持良好的旧git diff

我在这里(使用tkdiff)尝试了一些花哨的东西,但没有任何效果。所以我写了以下脚本,tkgitdiff。它做了我需要它做的事情。

$ cat tkgitdiff#!/bin/sh
## tkdiff for git.# Gives you the diff between HEAD and the current state of your file.#
newfile=$1git diff HEAD -- $newfile > /tmp/patch.datcp $newfile /tmpsavedPWD=$PWDcd /tmppatch -R $newfile < patch.datcd $savedPWDtkdiff /tmp/$newfile $newfile

您可以使用git difftool

例如,如果您有Meld,您可以通过以下方式编辑分支masterdevel

git config --global diff.external meldgit difftool master..devel

如果你碰巧已经有一个与文件类型相关联的diff工具(比如,因为你安装了TortoiseSVN,它附带了一个diff查看器),你可以将常规的git diff输出管道到一个“temp”文件,然后直接打开该文件,而不需要了解查看器的任何信息:

git diff > "~/temp.diff" && start "~/temp.diff"

将其设置为全局别名效果更好:git what

[alias]what = "!f() { git diff > "~/temp.diff" && start "~/temp.diff"; }; f"

对以前的精彩答案的简短总结:

git difftool --tool-helpgit config --global diff.tool <chosen tool>git config --global --add difftool.prompt false

然后通过键入来使用它(也可以选择指定文件名):

git difftool

安装Meld

 # apt-get install meld

然后选择它作为扩散工具:

 $ 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 diffusediffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiffMerging:www/css/style.csswww/js/controllers.js
Normal merge conflict for 'www/css/style.css':{local}: modified file{remote}: modified fileHit return to start merge resolution tool (meld):

因此,只需按输入即可使用meld(默认)。这将打开图形模式。进行魔术保存并按下解决合并的按钮。仅此而已。

如果您不适合使用命令行,那么如果您安装了TortoiseGit,您可以右键单击一个文件以获得带有“稍后比较”选项的TortoiseGit子菜单。

当您在第一个文件中选择此项时,您可以右键单击第二个文件,转到TortoiseGit子菜单并选择“Diff with==Your filehere==”。这将为结果提供TortoiseGit合并GUI。

在Mac OS X上,

git difftool -t diffuse

在Git文件夹中为我完成这项工作。要安装弥漫,可以使用端口-

sudo port install diffuse

在查看了其他一些外部diff工具后,我发现IntelliJ IDEA(和Android Studio)中的diff视图最适合我。

步骤1-设置IntelliJ IDEA从命令行运行

如果您想使用IntelliJ IDEA作为您的diff工具,您应该首先按照说明这里将IntelliJ IDEA设置为从命令行运行:

在macOS或UNIX上:

  1. 确保IntelliJ IDEA正在运行。
  2. 在主菜单上,选择Tools | Create Command-line Launcher。打开创建启动器脚本对话框,其中包含启动器脚本的建议路径和名称。您可以接受默认值,也可以指定自己的路径。注意它,因为你以后会需要它。在IntelliJ IDEA之外,将启动器脚本的路径和名称添加到您的路径中。

在Windows上:

  1. 指定IntelliJ IDEA可执行文件在Path系统环境变量中的位置。在这种情况下,您将能够从任何目录调用IntelliJ IDEA可执行文件和其他IntelliJ IDEA命令。

第2步-配置git以使用IntelliJ IDEA作为扩散工具

按照这篇博客文章上的说明:

Bash

export INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOSPATH=$IDEA_HOME $PATH

set INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOSset 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 difftoolgit difftool HEAD~1

以下内容可以从这里的其他答案中收集到,但对我来说很难(太多信息),所以这里是tkdiff的“只需输入”答案:

git difftool --tool=tkdiff <path to the file to be diffed>

您可以将您最喜欢的差异工具的可执行名称替换为tkdiff。只要(例如tkdiff)(或您最喜欢的差异工具)在您的PATH中,它就会启动。