当我执行"git diff"命令时,如何获得并排差异比较?

257
当我输入git diff命令时,我想看到一个并排显示差异的视图,就像使用diff -y命令一样,或者像在交互式差异工具kdiff3中显示差异。如何实现这个功能?

可能是重复的问题:如何使用可视化差异程序查看“git diff”输出? - Greg Hewgill
请注意:您可以在 GitHub 上查看 side-by-side diff - VonC
如何使用我喜欢的差异工具/查看器查看“git diff”输出?[重复] (https://dev59.com/SHVC5IYBdhLWcg3wjx5d) - smci
这真让人恼火,无法像使用“diff”一样操作。我最好开始适应阅读非并排格式,这对于一个视觉型的人来说很困难。 - Sridhar Sarnobat
19个回答

261

试试git difftool

使用git difftool而不是git diff。你再也不会回头了。

更新以添加一个示例用法:

这是一个链接,指向另一个stackoverflow页面,讨论git difftool如何使用我喜欢的diff工具/查看器查看'git diff'输出?

对于较新版本的gitdifftool命令支持许多外部diff工具。例如,vimdiff是自动支持的,并且可以通过命令行打开:

cd /path/to/git/repo
git difftool --tool=vimdiff

其他支持的外部差异工具可以通过git difftool --tool-help列出,这里是一个示例输出:
'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff

51
如果你看到了“因为未配置‘diff.tool’而显示此消息”,可能需要返回。也许可以更新答案,提供最简单的配置说明,以便在终端中显示并排差异,这正是原帖作者所要求的。图形用户界面工具在通过ssh连接到远程服务器时不太有用。 - Petr
1
有趣的观点,虽然我个人认为我从未需要在SSH时使用git。DVCS的一个好处是分布式部分:至少在我的环境中,本地克隆任何我想要探索的repo从来不是什么麻烦事。 - Matt Ball
1
至少在我的配置中,“git difftool”与“vimdiff”并不总是正确地对齐两个文件/缓冲区。 - tim-phillips
1
很好,那么在答案列表下面:O 我使用 git difftool -y 来防止 tkdiff 提示。 - gawkface
相关:在Windows和Linux中将Meld设置为您的git difftool:https://dev59.com/jmUq5IYBdhLWcg3wEcRZ#48979939 - Gabriel Staples
显示剩余3条评论

100
虽然 Git 有内部的 diff 实现,但你也可以设置外部工具来代替。有两种不同的指定外部 diff 工具的方法:
  1. 设置 GIT_EXTERNAL_DIFFGIT_DIFF_OPTS 环境变量。
  2. 通过 git config 配置外部 diff 工具。

ymattw 的答案也很漂亮,使用了 ydiff

请参阅:

在执行 git diff 时,Git 检查上述环境变量和它的 .gitconfig 文件。默认情况下,Git 将以下七个参数传递给 diff 程序:

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

你通常只需要使用old-file和new-file参数。当然,大多数差异工具只接受两个文件名作为参数。这意味着你需要编写一个小的包装脚本,将Git提供给脚本的参数传递给你选择的外部git程序。
假设你将包装脚本放在~/scripts/my_diff.sh下:
#!/bin/bash
# un-comment one diff tool you'd like to use

# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5" 

# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"

# using Meld 
/usr/bin/meld "$2" "$5"

# using VIM
# /usr/bin/vim -d "$2" "$5"

接下来,您需要将该脚本设为可执行:

chmod a+x ~/scripts/my_diff.sh

您需要告诉Git如何以及在哪里找到您的自定义差异包装脚本。您有三种选择:(我更喜欢编辑.gitconfig文件)

  1. Using GIT_EXTERNAL_DIFF, GIT_DIFF_OPTS

    e.g. in your .bashrc or .bash_profile file you can set:

     GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh
     export GIT_EXTERNAL_DIFF
    
  2. Using git config

    use "git config" to define where your wrapper script can be found:

     git config --global diff.external ~/scripts/my_diff.sh
    
  3. Editing your ~/.gitconfig file

    you can edit your ~/.gitconfig file to add these lines:

     [diff]
       external = ~/scripts/my_diff.sh
    

注意:

与安装自定义差异工具类似,您也可以安装自定义合并工具,这可以是一个视觉化合并工具,以更好地帮助可视化合并。(参见progit.org页面)

参见: http://fredpalma.com/518/visual-diff-and-merge-tool/https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration


1
这是否保留了git终端的颜色? - Sridhar Sarnobat
4
很棒,但它会为每个文件启动一个新的查看器。有没有办法在“meld”中创建一个合并差异? - HRJ
2
@Tilo 我在使用vim时遇到了错误,提示为im: Warning: Output is not to a terminal。 - dead programmer
meld 版本能否配置为进行目录差异比较,以便我可以选择要查看差异的文件?目前它会为每个文件运行单独的 meld 命令,我必须退出 meld 才能查看下一个文件。我更希望 meld 显示出像在 Mercurial 中使用 meld 时一样的更改文件目录列表。 - kasperd
我不想将这个答案投下去。但是ymattw的答案非常容易实现。 - user1357713

93
你也可以尝试使用git diff --word-diff。这不完全是并排显示,但某种程度上更好,因此你可能更喜欢它而非实际需求的并排显示。

22
这是最简单的方法。更好的是 git diff --word-diff=color,可以显示不同单词的颜色差异。 - Rolf
@Rolf,“--word-diff=color” 给我一个无效选项错误。它是在哪个版本中引入的? - Holloway
@Trengot 我使用的是2012年02月发布的git 1.7.9版本。 - Rolf
6
这里默认安装的版本是1.7.1。可以解释一下它和其他版本的区别。git diff --color-words命令确实可用。 - Holloway
8
是的,对于现代的 Git 版本来说,使用 git diff --color-words 是正确的方法。 - VasiliNovikov
有点更好,不是很诗意,但准确! - Bamaco

60

ydiff

曾被称为cdiff,这个工具可以展示并排增量带有颜色的差异。

不要使用git diff,请使用以下命令:

ydiff -s -w0

这将以并排显示模式启动ydiff,以显示每个具有差异的文件。

安装方式:

python3 -m pip install --user ydiff

-或-

brew install ydiff

要使用git log,您可以使用:

ydiff -ls -w0

-w0会自动检测终端宽度。详情及演示请参见ydiffGitHub存储库页面

在Git 2.18.0、ydiff 1.1中测试通过。


@RyneEverett:你能解释一下如何使用 icdiff 做与 git diff | cdiff -s 等效的操作吗? - einpoklum
1
只需从 git/svn/hg 工作区运行 ydiff -s,无需进行管道操作。 - ymattw
1
如果你想通过Git的历史记录限制特定文件的差异,请cd <git repo>,然后运行ydiff -ls <path/to/file> - slm
我使用pip进行了安装,但是在控制台上输入ydiff命令时报错:未发现该命令,因为它安装在~/.local/bin/ydiff路径下。 - rubo77

33

你可以使用 sdiff 进行并排比较两个文本的差异,具体方法如下:

$ git difftool -y -x sdiff  HEAD^ | less

其中HEAD^是一个示例,您应该将其替换为要与之进行比较的内容。

我在这里找到了解决方案(链接),还提供了其他一些建议。但是,这个答案简明清晰地回答了提问者的问题。

有关参数的说明,请参见git-difftool手册


根据评论,您可以编写以下可执行脚本,创建一个方便的git sdiff命令:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

将其保存为/usr/bin/git-sdiff并对其进行chmod +x操作。然后你就可以这样做:

$ git sdiff HEAD^

额外提示

如评论所建议,您可以使用icdiff以带颜色的输出执行sdiff相同的操作:

$ more /usr/bin/git-sdiff
#!/bin/sh
git difftool -y -x "icdiff --cols $(tput cols)" "${@}" | less --raw-control-chars

15

在Unix系统中,只需结合使用内置的gitdiff命令:

git show HEAD:path/to/file | diff -y - path/to/file

当然,您可以将 HEAD 替换为任何其他 git 引用,并且您可能希望向 diff 命令添加类似 -W 170 的内容。

这假设您只是将目录内容与过去的提交进行比较。在两个提交之间进行比较会更加复杂。如果您的 shell 是 bash,则可以使用“进程替换”:

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

其中REF1REF2是git引用——标签、分支或哈希值。


谢谢,你的命令 'git show HEAD:path/to/file' 是我需要的,让我想出了自己的解决方案,'vimdfiff <(git show HEAD:path/to/file) path/to/file'。虽然有些细节还没有完全对齐,但这是我目前最好的解决方案。 - talexb

12
我最近实现了一个可以实现这个功能的工具:https://github.com/banga/git-split-diffs
以下是使用方法:
npm install -g git-split-diffs

git config --global core.pager "git-split-diffs --color | less -RFX"

以下是在终端中查看该内容的方式(使用默认主题):

并排对比的预览图

如您所见,它还支持语法高亮和在行内突出显示已更改的单词。


哇,这个工具太棒了。感谢你的辛勤付出,让我们拥有这么棒的东西! - alexzander
但是它有点慢,加载一个文件需要2秒钟。 - alexzander
在 https://github.com/banga/git-split-diffs#performance 上有一些关于性能的注释,但如果您发现有不同的情况,请提交一个问题。谢谢! - Shrey
1
太好了!谢谢你!当我运行 git diff --staged 时非常有效。 - 1Mojojojo1

9
如果您想在不涉及GitHub的情况下在浏览器中查看并排差异,您可能会喜欢 git webdiff,它是 git diff 的即插即用替代品。
$ pip install webdiff
$ git webdiff

这比传统的GUI差异工具(如tkdiff)有许多优势,因为它可以提供语法高亮和图像差异显示。
这里阅读更多相关信息。

9
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

那么,简单地说:
git diff

1
`meld .' 也可以!它会在一个合并的窗口中显示所有更改。 - HRJ
@HRJ,这个完美运作!如此简单实用 :) - waldyrious
meld 在使用 XQartz-X-Display-Redirect 时也可以很好地在 Debian 到 macOS 的环境下工作。 - Fusca Software

8

我使用colordiff工具。

在Mac OS X上,可以通过以下方式进行安装:

$ sudo port install colordiff

在Linux上,根据你的发行版,可能需要执行apt get install colordiff或类似的命令来安装colordiff。然后:
$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

或者创建别名。
$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

然后您就可以使用它了。

$ git diffy HEAD^ HEAD

我把它称为“diffy”,因为在Unix中,diff -y是显示并排差异的命令。 Colordiff 还添加了颜色,更加美观。 在选项-ydw中,y代表并排差异,w表示忽略空格,d表示生成最小差异(通常情况下,使用 diff 命令可以得到更好的结果)。

添加 -y 以跳过 启动 'colordiff' [Y/n]: 提示。 - Beni Cherniavsky-Paskin
你确定是 git alias diffy "difftool --extcmd=\"colordiff -ydw\"" 吗?难道不应该是 git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\"" 吗? - nonopolarity
请更正为apt install colordiffapt-get install colordiffapt get install colordiff无法工作。 - Fusca Software

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