如何区分提交与其父级
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】:用途:
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 一起正常工作,但对于合并提交,差异是相反的。为什么会这样?【参考方案3】:
如果你知道多远,你可以试试这样的:
# 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 作为爸爸的爸爸。【参考方案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】:如果您使用Z shell 并设置了extendedglob
选项,则许多提到的示例(例如git diff 15dc8^!
或git diff 15dc8^..15dc8
)都不起作用。您可以通过以下三种方式之一进行修复:
unsetopt extendedglob
(和/或将其从 .zshrc 中删除)
setopt NO_NOMATCH
(和/或在 .zshrc 中设置)
每次都用反斜杠转义插入符号并敲击,例如,git diff 15dc8\^\!
【讨论】:
【参考方案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】:这使用了别名,所以它不能准确回答你的问题,但我发现这些对于做你想做的事情很有用......
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"
【讨论】:
以上是关于如何区分提交与其父级的主要内容,如果未能解决你的问题,请参考以下文章