如何区分提交与其父级

Posted

技术标签:

【中文标题】如何区分提交与其父级【英文标题】:How to diff a commit with its parent 【发布时间】:2010-09-30 23:37:34 【问题描述】:

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

git diff 15dc8^..15dc8

如果您只提供单个提交 ID git diff 15dc8,它会区分针对 HEAD 的提交。

【问题讨论】:

最酷的事情是它可以与“git difftool”一起使用,使用工具来显示差异。 作为参考,其他问题的答案说明了如何设置 bash 驱动的别名来简化上述操作:***.com/questions/3321492/… 【参考方案1】:

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

【讨论】:

太糟糕了,它不能使用 difftool :( @orip 您始终可以将 GIT_EXTERNAL_DIFF 设置为与您的 difftool 执行相同操作的脚本。 我更喜欢 JakubNarebski 的回答,因为那里给出的提交表达式可以在许多情况下工作:***.com/a/449128/992887 如果没有显示差异,可能没有实际更改,例如合并提交 @PTWithy:问题是,“是否有更短的命令来获取特定提交的差异?”,这个问题回答了。【参考方案2】:

如果你知道有多远,你可以试试这样的:

# 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

见this page for details。

【讨论】:

HEAD^2 不是祖父母,如果 HEAD^1 是爸爸,那么 HEAD^2 是妈妈。使用 HEAD~2 作为爸爸的爸爸。【参考方案3】:

用途:

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,表示提交的父级(15dc8^)和提交(15dc8)的区别。

注意git-rev-parse(1) 手册页中的描述谈到了修订范围,它也需要在合并中起作用提交,有多个父母。那么r1^! 就是“r1 --not r1^@”即“r1 ^r1^1 ^r1^2 ...


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

【讨论】:

这应该是公认的答案,它更整洁。然而,git-rev-parse 提取的最后一句话相当令人困惑——似乎它的意思是“从这个提交的父级到这个提交的范围”。 @RichVel:这有点令人困惑,因为它还试图描述提交有多个父级(是合并提交)的情况。 r1^!然后也可以按预期工作。 @JakubNarębski:好点子,也许您可​​以编辑您的答案来总结您对单亲和多亲案例的理解 - 单独的陈述可​​能更容易理解。 @JakubNarębski:是的,好多了!我现在一直使用这个快捷方式 - 谢谢。 ^! 父简写符号在正常提交时与 difftool 一起正常工作,但对于合并提交,差异是相反的。为什么会这样?【参考方案4】:

作为mipadi points out,您可以使用git show $COMMIT,但这也会显示一些标头和提交消息。如果你想要一个直接的差异,请使用git show --pretty=format:%b $COMMIT

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

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

这使我能够使用git sd $COMMIT显示差异

【讨论】:

这个别名可以包含--color,这样更容易阅读:sd = show --color --pretty=format:%b @RichVel 确实!很好的一点。如果您在 git 中默认启用了颜色,那么您将不需要此开关。这就是我通常所做的。【参考方案5】:

这使用了别名,所以它不能准确回答你的问题,但我发现这些对于做你想做的事情很有用......

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"

【讨论】:

【参考方案6】:
git diff 15dc8 15dce~1

~1 表示“父母”,~2 表示“祖父母”等。

【讨论】:

【参考方案7】:

Paul's solution 做了我希望的事。

$ git diff HEAD^1

此外,添加 hobs mentioned 之类的别名也很有用。如果您将以下内容放在 ~/.gitconfig 文件的 [alias] 部分,那么您可以使用简写来查看 head 和 previous 之间的差异。

[alias]
    diff-last = diff HEAD^1

然后运行 ​​$ git diff-last 会得到你的结果。请注意,这还将包括您尚未提交的任何更改以及提交之间的差异。如果您想忽略您尚未提交的更改,那么您可以使用 diff 直接将 HEAD 与其父级进行比较:

$ git diff HEAD^1 HEAD

【讨论】:

【参考方案8】:

如果您使用Z shell 并设置了extendedglob 选项,则许多提到的示例(例如git diff 15dc8^!git diff 15dc8^..15dc8)都不起作用。您可以通过以下三种方式之一进行修复:

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

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

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

【讨论】:

以上是关于如何区分提交与其父级的主要内容,如果未能解决你的问题,请参考以下文章

如何区分本地未提交的更改和来源

使用 xcode,我如何区分文件的工作副本和存储库中的最新提交?

行内元素与块级元素的区分

如何区分 GitHub 中的两个分支?

到底如何区分什么是架构框架模式和平台 ?

如何使用两个提交按钮,并区分使用哪个提交表单? [复制]