如何与父提交进行比较?


460

除了编写别名或脚本之外,是否还有更短的命令来获取特定提交的差异?

git diff 15dc8^..15dc8

如果仅提供单个提交ID git diff 15dc8,则它将与HEAD进行比较。


最酷的事情是它将与“ git difftool”一起使用,并使用工具来显示差异。
orip

作为参考,该另一个问题的答案说明了如何设置以bash为动力的别名以简化上述操作:stackoverflow.com/questions/3321492/…–
Nick

Answers:


641

使用git show $COMMIT。它会向您显示该提交的日志消息,以及该特定提交的差异。


45
太糟糕了,它不能使用difftool :(
orip

1
@orip,您始终可以将GIT_EXTERNAL_DIFF设置为与difftool具有相同功能的脚本。
slacy 2012年

7
我更喜欢JakubNarebski的回答,因为那里给出的提交表达式将在许多情况下起作用:stackoverflow.com/a/449128/992887
RichVel

1
如果未显示差异,则可能没有实际更改,例如合并提交
Devin G Rhode

6
@PTWithy:问题是,“是否有一个较短的命令来获取特定提交的diff?”,这个问题可以回答。
mipadi 2014年

439

采用:

git diff 15dc8^!

如以下git-rev-parse(1)手册页(或现代git gitrevisions(7)手册页)所述:

还存在两个其他快捷方式来命名由提交及其父提交构成的集合。r1 ^ @表示r1的所有父代。r1 ^!包括提交r1,但不包括其所有父项。

这意味着您可以在git中任何需要修订的地方15dc8^!用作简写15dc8^..15dc8。对于diff命令,git diff 15dc8^..15dc8其理解为git diff 15dc8^ 15dc8,这意味着commit(15dc8^)的父对象与commit()之间的区别15dc8

注意git-rev-parse(1)联机帮助页中的描述涉及修订范围,在修订范围中,修订范围还需要与多个父级一起进行合并提交。然后r1^!r1 --not r1^@“即r1 ^r1^1 ^r1^2 ...


另外,您可以git show COMMIT用来获取提交描述和提交的差异。如果只需要差异,则可以使用git diff-tree -p COMMIT


7
这应该是公认的答案,它更加整洁。但是,git-rev-parse提取的最后一句话相当令人困惑-似乎意味着“从此提交的父对象到此提交的范围”。
RichVel

1
@RichVel:这有点令人困惑,因为它也试图描述提交具有多个父级(合并提交)的情况。r1 ^!然后按预期工作。
JakubNarębski2013年

@JakubNarębski:好点,也许您可​​以编辑答案以总结对单亲和多亲案件的理解-每个案件的单独陈述可能更容易理解。
RichVel

1
@JakubNarębski:是的,要好得多!我现在一直在使用此快捷方式-谢谢。
RichVel 2013年

1
^!对于普通提交,父速记符号可以与difftool一起正常使用,但对于合并提交,diff则相反。为什么这样?
嬉皮

56

如果您知道有多远,可以尝试以下方法:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

先前的提交工作如下:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

您可以通过多种方式指定提交:

# Great grandparent
git show HEAD~3

有关详细信息,请参见此页面


2
HEAD ^ 2不是祖父母,如果HEAD ^ 1是爸爸,那么HEAD ^ 2是妈妈。将HEAD〜2用作爸爸的爸爸。
Binarian

11

正如@mipadi指出的那样,您可以使用git show $COMMIT,但这也显示了一些标题和提交消息。如果您想直接进行比较,请使用git show --pretty=format:%b $COMMIT

这显然不是很短的手,所以我将这个别名保存在我的.gitconfig中

    [alias]
      sd = show --pretty=format:%b

这使我可以git sd $COMMIT用来显示diff


1
此别名可以包括--color,这使它更易于阅读:sd = show --color --pretty = format:%b
RichVel 2013年

@RichVel确实!很好的一点。如果您默认在git中启用了颜色,则不需要此开关。那就是我通常所做的。
奥伊斯坦Steimler

5

如果您使用的是zsh并设置了选项,则上述示例中的许多示例(例如git diff 15dc8^!,或git diff 15dc8^..15dc8)都无法使用extendedglob。您可以通过以下三种方式之一修复它:

  1. unsetopt extendedglob (和/或将其从.zshrc中删除)

  2. setopt NO_NOMATCH (和/或在.zshrc中设置)

  3. 逃脱插入符号并每次都用反斜杠敲击,例如 git diff 15dc8\^\!



2

Paul的上述解决方案实现了我希望的那样。

$ git diff HEAD^1

另外,添加别名(如提到的滚刀)很有用,如果将以下内容放在〜/ .gitconfig文件的[alias]部分中,则可以使用简写形式查看head和previous之间的差异。

[alias]
    diff-last = diff HEAD^1

然后运行$ git diff-last将获得您的结果。请注意,这还将包括您尚未提交的所有更改以及提交之间的差异。如果要忽略尚未提交的更改,则可以使用diff直接比较HEAD和它的父项:

$ git diff HEAD^1 HEAD

0

使用别名,因此无法完全回答您的问题,但是我发现这些别名对您执行预期的工作很有用...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
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.