如何在同一分支的两个不同提交之间区分同一文件?


Answers:


1475

git-diff联机帮助页:

git diff [--options] <commit> <commit> [--] [<path>...]

例如,要查看现在和两次提交之间文件“ main.c”的区别,这里有三个等效的命令:

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

43
..是不是真的有必要,但它会使用它(除了在相当老的版本,也许)。如果两个提交相距很远,您也可以使用git loggitk查找要使用的SHA1。gitk在上下文菜单中还具有“选择差异->此”和“差异此->选择”。
卡斯卡贝尔

17
即使在两次提交之间修改了文件名,此方法也可以工作吗?
reubenjohn 2014年

26
那么,“-”的目的是什么
user64141

29
@ user64141 --很有用,例如当您有一个名为的文件时-p。很好地在脚本中使用,仅在实际需要的极少数情况下。
Palec 2014年

13
注意:您需要使用相对于仓库根目录的路径。相对于当前工作目录的路径将不起作用。
凯文·惠勒

280

您还可以比较两个不同版本中的两个不同文件,如下所示:

git diff <revision_1>:<file_1> <revision_2>:<file_2>


25
请注意,如果<file_1><file_2>都位于当前目录中,而不是位于顶级git托管目录中,则必须./在Unix 上前置:<revision_1>:./filename_1
Andre Holzner

7
<revision>:可以省略,因此可以与尚未提交的文件进行比较。
Yaroslav Nikitenko 2015年

2
请注意,在Windows上,必须使用“ /”作为文件路径,而不是“ \”。
np8

87

如果已配置“ difftool”,则可以使用

git difftool revision_1:file_1 revision_2:file_2

示例:将文件的最后一次提交与同一分支上的先前提交进行比较:假设您位于项目根文件夹中

$git difftool HEAD:src/main/java/com.xyz.test/MyApp.java HEAD^:src/main/java/com.xyz.test/MyApp.java

您应该在〜/ .gitconfig或project / .git / config文件中具有以下条目。安装p4merge [这是我首选的差异和合并工具]

[merge]
    tool = p4merge
    keepBackup = false
[diff]
    tool = p4merge
    keepBackup = false
[difftool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
[mergetool]
    keepBackup = false
[difftool]
    keepBackup = false
[mergetool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
    cmd = p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"

50

选中$ git log,复制两个不同提交的SHA-1 ID,然后git diff使用这些ID 运行命令。例如:

$ git diff (sha-id-one) (sha-id-two)

18
如果您需要特定文件的差异,请在命令末尾添加路径。
hBrent

如果两个提交跨越不同的分支,也可以执行“ git pull”来下载完整的树信息。否则,您将收到“致命的:错误的对象”错误。
user238607 '18

4
git diff (sha-id-one) (sha-id-two) -- filename.ext 如果没有文件名,它将列出这两次提交中所有文件的差异。
SherylHohman

40

如果要逐个提交查看两次提交之间文件的所有更改,也可以执行

git log -u $start_commit..$end_commit -- path/to/file


什么是“ $ start_commit”和“ $ end_commit”?他们是字面意义上的吗?如果不是,您能提供一个例子吗?
彼得·莫滕森

这些是包含开始和结束修订的shell变量,它们可以是sha1文字或引用
cxreg

21

这是一个Perl脚本,可以打印出给定文件的Git diff命令,如在Git日志命令中找到的一样。

例如

git log pom.xml | perl gldiff.pl 3 pom.xml

产量:

git diff 5cc287:pom.xml e8e420:pom.xml
git diff 3aa914:pom.xml 7476e1:pom.xml
git diff 422bfd:pom.xml f92ad8:pom.xml

然后可以将其剪切并粘贴到shell窗口会话中,或通过管道传输到/bin/sh

笔记:

  1. 数字(在这种情况下为3)指定要打印的行数
  2. 该文件(在这种情况下为pom.xml)必须在两个地方都同意(您可以将其包装在shell函数中以在两个地方提供相同的文件)或将其作为shell脚本放在二进制目录中

码:

# gldiff.pl
use strict;

my $max  = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file"   unless -f $file;

my $count;
my @lines;

while (<>) {
    chomp;
    next unless s/^commit\s+(.*)//;
    my $commit = $1;
    push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
    if (@lines == 2) {
        printf "git diff %s %s\n", @lines;
        @lines = ();
    }
    last if ++$count >= $max *2;
}

14

如果要使用多个文件进行比较,请使用@mipadi指定的方法:

例如HEAD和之间的差异master,以查找所有.coffee文件:

git diff master..HEAD -- `find your_search_folder/ -name '*.coffee'`

这将递归搜索your_search_folder/所有.coffee文件,并在它们及其master版本之间进行区分。


13

如果您有多个文件或目录,并且想要比较非连续提交,则可以执行以下操作:

进行临时分支(在此示例中为“修订”

git checkout -b revision

倒退到第一个提交目标

git reset --hard <commit_target>

樱桃采摘那些有兴趣的人

git cherry-pick <commit_interested> ...

应用差异

git diff <commit-target>^

当你完成

git branch -D revision

2
感谢您的解决方案。对于我的用例,它工作得很好。我唯一要更新的是,完成操作后,您必须先将其关闭才能删除该分支。
史蒂文·迪克斯

9

这是使用Git令人敬畏的另一种方式...

git difftool HEAD HEAD@{N} /PATH/FILE.ext

我从此答案定义了一个适用于bash的别名:difftool-file = "!git difftool HEAD@{\"$2\"} HEAD \"$1\" #"
blueogive

2

如果要在Windows上进行简单的视觉比较(例如可以在Visual SourceSafeTeam Foundation Server(TFS)中获得),请尝试以下操作:

  • 右键单击“文件资源管理器”中的文件
  • 选择“ Git历史记录”

注意:升级到Windows 10后,我丢失了Git上下文菜单选项。但是,您可以在命令窗口中使用“ gitk”或“ gitk filename”来实现相同的目的。

调用“ Git历史记录”后,将启动Git GUI工具,并在左上方窗格中显示文件的历史记录。选择您要比较的版本之一。然后右键单击第二个版本,然后选择

区别->选择

要么

选择差异->此

颜色编码的差异将显示在左下方的窗格中。


投票者注意:这是一个简单的解决方案,易于实现并解决了OP的问题。它可以在OP明确使用的Windows上运行(请参阅问题中对TFS和VSS的引用)。
资源
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.