当我做“ git diff”时,如何获得并排差异?


163

当我输入“ git diff”时,我想看到并排的diff,例如“ diff -y”,或希望在交互式差异工具(如“ kdiff3”)中显示差异。如何才能做到这一点?



注意:您在GitHub上有一个并排的差异
VonC 2014年

Answers:


89

尽管Git具有diff的内部实现,但是您可以设置外部工具。

有两种不同的方法可以指定外部差异工具:

  1. 设置GIT_EXTERNAL_DIFFGIT_DIFF_OPTS环境变量。
  2. 通过配置外部差异工具 git config

也可以看看:

执行时git diff,Git会检查上述环境变量的设置及其.gitconfig文件。

默认情况下,Git将以下七个参数传递给diff程序:

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

通常,您只需要使用旧文件和新文件参数。当然,大多数差异工具仅将两个文件名作为参数。这意味着您需要编写一个小的包装脚本,该脚本接受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如何以及在何处找到您的自定义diff包装器脚本。您有三种选择方法:(我更喜欢编辑.gitconfig文件)

  1. 使用GIT_EXTERNAL_DIFFGIT_DIFF_OPTS

    例如,在您的.bashrc或.bash_profile文件中,您可以设置:

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

    使用“ git config”定义可以在哪里找到包装脚本:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. 编辑~/.gitconfig文件

    您可以编辑~/.gitconfig文件以添加以下行:

    [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

3
很好,但是它为每个文件启动了一个新的查看器。任何建立合并差异的方法,例如meld
HRJ 2013年

2
@Tilo我在vim上收到的错误消息是im:警告:输出未到终端
死掉的程序员

是否可以将meld版本配置为执行目录差异,我可以在其中选择要查看差异的文件?当前,它meld为每个文件运行一个单独的命令,我必须退出meld才能查看下一个文件。我宁愿meld给我看一个目录,列出更改文件的目录,就像meld使用Mercurial 时的行为一样。
卡巴斯德(Kasperd),

163

尝试git difftool

使用git difftool代替git diff。你永远不会回去。

UPDATE添加示例用法:

这是另一个讨论的stackoverflow的链接git difftool如何使用首选的差异工具/查看器查看“ git diff”输出?

对于较新版本的git,该difftool命令支持开箱即用的许多外部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

34
或者,如果您愿意,您可能会回去This message is displayed because 'diff.tool' is not configured.。也许用最少的配置方法来更新答案,以便它在终端中并排显示差异,这是OP要求的?在使用ssh连接的远程服务器上,GUI工具非常没用。
彼得

1
有趣的一点是,尽管我认为我个人不需要在SSH期间使用git。关于DVCS的好处是,分布式部分:至少在我的环境中,本地克隆我想讨论的任何回购源都不会麻烦。
马特·鲍尔

1
至少在我的配置中,git difftoolwith vimdiff并不总是正确地对齐两个文件/缓冲区。
罗默

1
太好了,因此在答案列表下方:OI用于git difftool -y防止tkdiff提示
harshvchawla

相关:git difftool在Windows和Linux中融合:stackoverflow.com/a/48979939/4561887
Gabriel Staples

55

您也可以尝试git diff --word-diff。它不是完全并排的,但是在某种程度上更好,因此您可能更喜欢实际并排的需求。


12
这是最简单的方法。更好的是git diff --word-diff=color
Rolf

@Rolf --word-diff=color给我一个无效的选项错误。它引入了哪个版本?
Holloway 2014年

@Trengot我运行git 1.7.9,从02/2012开始
Rolf

4
@Rolf的默认安装版本为1.7.1。可以解释差异。git diff --color-words确实有效。
Holloway 2014年

4
是的,git diff --color-words是采用现代git版本的方法。
VasiliNovikov

41

ydiff

cdiff该工具以前称为,可以并排显示,增量显示和彩色 diff。

除了执行之外git diff,请执行以下操作:

ydiff -s -w0

ydiff对于不同的文件,这将以并排显示模式启动。

安装方式:

python3 -m pip install --user ydiff

-要么-

brew install ydiff

对于git log,您可以使用:

ydiff -ls -w0

-w0自动检测您的终端宽度。有关详细信息和演示,请参见ydiff GitHub存储库页面

在Git 2.18.0,ydiff 1.1中进行了测试。


@RyneEverett:您能解释一下如何git diff | cdiff -s使用icdiff吗?
einpoklum

只需ydiff -s从git / svn / hg工作区运行,就不必进行管道
插入。– ymattw

如果您想通过Git的历史记录将差异限制为特定文件,cd <git repo>然后运行ydiff -ls <path/to/file>
slm

22

您可以并排diff使用sdiff,如下所示:

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

这里HEAD^有一个示例,您应将其替换为您要比较的任何内容。

我在这里找到此解决方案的地方,还有其他一些建议。但是,这个答案简洁明了是OP的问题。

有关参数的解释,请参见man git-difftool


采纳注释,您可以git sdiff通过编写以下可执行脚本来创建方便的命令:

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

保存它/usr/bin/git-sdiffchmod -x它。然后,您将可以执行以下操作:

$ git sdiff HEAD^

如果/当我想抑制同一行并且只有一个文件时,我通常会执行“ $ git difftool -x'sdiff -s -w 240'”(或任何屏幕宽度)(否则我会执行vimdiff)
HidekiAI

1
@HidekiAI我很难每次都键入终端宽度,所以我改用tput cols了例如:git difftool -x "sdiff -s -w $(tput cols)"
Jaume

它可以突出显示颜色变化吗?现在,我们似乎不得不用眼睛观察实际的变化
极性

用icdiff替换sdiff以获得漂亮的彩色显示。
格雷格

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

然后简单地:

git diff

1
“融化。” 也可以!它在合并的窗口中显示所有更改。
HRJ 2013年

完美的@HRJ!如此简单实用:)
waldyrious

9

如果您希望在不涉及GitHub的情况下在浏览器中查看并排差异,则可以使用git webdiff,它是的替代品git diff

$ pip install webdiff
$ git webdiff

与传统的GUI difftools相比tkdiff,它具有许多优势,例如,它可以为您突出显示语法并显示图像差异。

在此处了解更多信息。


7

我使用colordiff

在Mac OS X上,使用

$ sudo port install colordiff

在Linux上可能apt get install colordiff是这样,取决于发行版。

然后:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

或创建一个别名

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

那你就可以用

$ git diffy HEAD^ HEAD

我称其为“ diffy”,因为它diff -y是unix中的并排diff。Colordiff还添加了更好的颜色。在option中-ydw,和y是并排使用的,w是忽略空格,并且d是产生最小的差异(通常,获得更好的差异结果)


添加-y以跳过Launch 'colordiff' [Y/n]:提示。
Beni Cherniavsky-Paskin 2014年

你确定是git alias diffy "difftool --extcmd=\"colordiff -ydw\""吗?不是git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""吗?
极性

6

对于unix,将just git和内置组合diff

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

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

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

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

哪里REF1REF2git参考-标签,分支或哈希。


谢谢-您的命令'git show HEAD:path / to / file'是我想出自己的解决方案'vimdfiff <(git show HEAD:path / to / file)path / to / file'所需要的。这些位仍然没有正确排列,但这是我现在得到的最佳解决方案。
talexb

5

我个人真的很喜欢icdiff

如果你在Mac OS XHomeBrew,只是做brew install icdiff

为了正确获取文件标签以及其他出色功能,我准备了~/.gitconfig

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

我像这样使用它: git difftool


3

当我在寻找使用git内置方法定位差异的快速方法时,就会出现此问题。我的解决方案标准:

  • 快速启动,需要内置选项
  • 可以轻松处理多种格式,xml,不同的编程语言
  • 快速识别大文本文件中的小代码更改

我找到了这个答案来获得git的颜色。

为了并排diff而不是行diff,我使用以下参数调整了mb14在该问题上的出色答案

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

如果您不喜欢多余的[-或{+,--word-diff=color则可以使用该选项。

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

这有助于与json和xml文本以及Java代码进行适当的比较。

总之--word-diff-regex,与标准行差异相比,这些选项在浏览行变化较小的大文件时具有很好的可视性以及颜色设置,从而获得彩色的并排源代码体验。


3

其他几个人已经提到cdiff用于git并排比较,但是没有人提供完整的实现。

设置cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

编辑〜/ .gitconfig插入以下行:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

cdiff与Diff一起使用时需要关闭分页器,无论如何它本质上是一个分页器,所以很好。不管这些设置如何,Difftool都可以工作。

需要使用show别名,因为git show仅通过参数支持外部diff工具。

diff external命令末尾的“#”很重要。Git的diff命令在diff命令后附加$ @(所有可用的diff变量),但是我们只需要两个文件名。因此,我们用$ 2和$ 5显式地调用了这两个,然后将$ @隐藏在注释后面,否则会使sdiff混淆。导致出现如下错误:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

现在会产生并排差异的Git命令:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Cdiff用法:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

现在,您可以通过git diff和difftool并排使用diff。而且,如果需要,您可以使用cdiff python源代码进行高级用户自定义。


2

这是一种方法。如果通过更少的管道传输,则xterm宽度将设置为80,这并不是很热。但是,如果继续执行命令(例如COLS = 210),则可以使用扩展的xterm。

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}

1
滑稽。我用化名按名字签名,但被忽略了……感谢您外出,Stack Overflow。:(
Thomas Mellman,2016年

2

打开Intellij IDEA,在“版本控制”工具窗口中选择一个或多个提交,浏览更改的文件,然后双击它们以并排检查每个文件的更改。

使用捆绑的命令行启动器,您可以通过任何简单的方法将IDEA升级到任何地方 idea some/path

版本控制视图 差异视图


1

这个线程有很多好的答案。我对此问题的解决方案是编写一个脚本。

将此名称命名为“ git-scriptname”(并使其可执行,并像放置任何脚本一样将其放入您的PATH中),您可以像运行一般git命令一样通过运行它来调用它

$ git scriptname

实际功能只是最后一行。来源:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R

1

这可能是一个有限的解决方案,但是可以在diff没有外部工具的情况下使用系统命令来完成此工作:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • 仅过滤更改行使用的内容--suppress-common-lines(如果您diff支持该选项)。
  • 在这种情况下没有颜色,只有通常的diff标记
  • 可以调整列的宽度--width=term-width; 在Bash中可以将宽度设为$COLUMNStput cols

为了更加方便,也可以将其包装到辅助git-script中,例如:

git diffy the/file/path --from rev1 --to rev2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.