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

时间:2011-10-06 03:10:01

标签: git git-diff code-visualization

当我输入“git diff”时,我想看到一个并排的差异,就像“diff -y”一样,或者喜欢在像“kdiff3”这样的交互式差异工具中显示差异。怎么办呢?

18 个答案:

答案 0 :(得分:116)

尝试git difftool

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

更新以添加示例用法:

以下是指向git difftool的另一个stackoverflow的链接:How do I view 'git diff' output with my preferred diff tool/ viewer?

对于较新版本的gitdifftool命令支持许多开箱即用的外部差异工具。例如,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

答案 1 :(得分:80)

虽然Git有diff的内部实现,但您可以设置外部工具。

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

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

    另见:

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

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

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

    您通常只需要旧文件和新文件参数。当然,大多数diff工具只使用两个文件名作为参数。这意味着你需要编写一个小的包装器脚本,它接受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. 使用GIT_EXTERNAL_DIFFGIT_DIFF_OPTS

      e.g。在.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
      
    4. 注意:

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

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

答案 2 :(得分:37)

您也可以尝试git diff --word-diff。 它不是完全并排,但不知何故更好,所以你可能更喜欢它与你真正的并排需求。

答案 3 :(得分:30)

<强> ydiff

以前称为cdiff,此工具可以显示并排增量丰富多彩差异。

不要执行git diff,而是执行:

ydiff -s

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

安装时:

python3 -m pip install --user ydiff

对于git log,您可以使用:

ydiff -ls

有关详情和演示,请参阅ydiff GitHub repository page

在Git 2.18.0中测试,ydiff 1.1。

答案 4 :(得分:10)

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

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

其中HEAD^是一个示例,您应该将其替换为您想要反对的任何内容。

我找到了这个解决方案here,其中还有其他一些建议。然而,这一个答案是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^

答案 5 :(得分:7)

如果您希望在不涉及GitHub的情况下在浏览器中查看并排差异,您可能会喜欢git webdiffgit diff的替代品:

$ pip install webdiff
$ git webdiff

tkdiff等传统GUI差异工具相比,它提供了许多优势,因为它可以为您提供语法高亮显示和显示图像差异。

详细了解here

答案 6 :(得分:6)

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

然后简单地说:

git diff

答案 7 :(得分:6)

我使用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中的并排差异。 Colordiff还添加了更好的颜色。 在选项-ydw中,y用于并排,w用于忽略空格,d用于生成最小差异(通常你得到一个更好的结果作为差异

答案 8 :(得分:4)

对于unix,仅合并git和内置diff

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

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

这假设您只是将目录内容与过去的提交进行比较。两次提交之间的比较更复杂。如果你的shell是bash,你可以使用&#34;进程替换&#34;:

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

其中REF1REF2是git引用 - 标记,分支或哈希。

答案 9 :(得分:3)

我个人非常喜欢icdiff

如果您使用HomeBrew 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

我使用它:package com.anarsoft.mit; import java.util.concurrent.atomic.AtomicInteger; public class Test_Response_Unit_Manager implements Runnable { private final AtomicInteger threadCount = new AtomicInteger(); public void test() throws Exception { for(int i = 0; i < 2 ;i++) { Thread thread = new Thread(this, "Thread " + i); this.threadCount.incrementAndGet(); thread.start(); } while( this.threadCount.get() > 0 ) { Thread.sleep(1000); } Thread.sleep(10 * 1000); } public void run() { exec(); threadCount.decrementAndGet(); } protected void exec() { Response_Unit_Manager.Add_Response_Unit(new Response_Unit(Thread.currentThread().getId())); } public static void main(String[] args) throws Exception { (new Test_Response_Unit_Manager()).test(); } }

答案 10 :(得分:2)

这是一种方法。如果管道较少,则xterm宽度设置为80,这不是很热。但是,如果你继续执行命令,例如COLS = 210,您可以使用扩展的xterm。

r'^subscribe/'  # Shouldn't have the slash or should be optional

答案 11 :(得分:2)

其他几个人已经提到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 alias,因为git show仅通过参数支持外部diff工具。

&#39;#&#39;在diff外部命令结束时很重要。 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并排进行差异化。如果需要,您可以使用cdiff python源代码进行高级用户自定义。

答案 12 :(得分:1)

当我在寻找一种使用git内置方式来定位差异的快速方法时,这个问题就出现了。我的解决方案标准:

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

我找到this answer来获取git中的颜色。

为了获得并排差异而不是行差异,我使用以下参数调整了mb14这个问题的优秀answer

$ 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选项与颜色设置一起提供了有用的可见性,以便在浏览具有较小线条变化的大文件时获得与标准线差异相比的彩色化并排源代码体验。

答案 13 :(得分: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

答案 14 :(得分:0)

我最近实现了一个完全可以做到这一点的工具:https://github.com/banga/git-split-diffs

使用方法如下:

npm install -g git-split-diffs

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

这就是它在您的终端中的外观(使用默认主题):

Preview of side by side diffs

如您所见,它还支持语法高亮和高亮行内更改的单词

答案 15 :(得分:0)

如果您使用的是Mac,GitUp http://gitup.co/是一个不错的选择。

答案 16 :(得分:0)

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

使用捆绑的命令行启动器,您可以通过简单的idea some/path

将IDEA带到任何地方

version control view diff view

答案 17 :(得分:0)

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

为此命名&#39; git-scriptname&#39; (并使其可执行并将其放入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