当调用git diff时,提交哈希后面的caret bang (^!)是什么意思?

8

浏览brackets-git的源代码(一款Brackets的git扩展),我发现在调用git diff时,会将^!(caret bang)附加到提交哈希值上。请参见GitCli.js,第754行

function getDiffOfFileFromCommit(hash, file) {
    return git(["diff", "--no-ext-diff", "--no-color", hash + "^!", "--", file]);
}

这在命令行中的翻译如下,以所讨论的文件为例:
$ git diff --no-ext-diff --no-color 1f9ea6e^! -- src/git/GitCli.js

我知道 ^ 代表该提交的父提交。那么 ^! 是什么意思?

4
有关如何引用Git提交的各种方法的完整指南,可以在 git rev-parse 文档中找到。在这种情况下,特别注意的是:"r1^! 包括提交 r1,但不包括其所有父节点。" - Charlie
从测试结果来看,输出与使用提交及其所有父级作为参数调用diff相同。我不知道当git比较多个树时会发生什么(从代码注释中可以看出,这应该是一个错误)。也许它会对父级的合并基础进行一些魔法操作? - knittl
1个回答

7

commit^!是一个范围限定符,表示:这个提交,但不包括其任何父级。 相当于指定:commit ^parent1 ^parent2 ^parentN

对于差异比较,这没有意义(您只能比较两个树) 从测试结果来看,该命令显示父级的合并基础和最后一个父级之间的差异。我认为git将参数类似于范围A...B进行(会显示merge-base A BB之间的差异)(git diff parent1...parent2将产生相同的差异)。不确定在多达八个父级的情况下会发生什么。

尽管如此,我可能是错误的,这些只是我通过使用存储库并查看git代码(builtin/diff.c)得出的假设。


r1^@ 表示 r1 的所有父提交。r1^! 包括提交 r1 但不包括其所有父提交。 - mcls
@maartencls:是的,我知道——请看我的回答的第一句话。使用git diff时,范围并没有太多意义,因为它只能使用端点进行操作。特别是这种范围(提交但不包括其父级)不能保证有确切的两个端点,所以git会感到困惑。 - knittl
@maartencls 很好知道。我一直使用 gitrevisions。希望这两个页面是同步的。 - musiKk
2
@knittl: 对于普通的非合并提交,A^! 等于 A^..A,在 diff 中等价于 "A^ A"。 - Jakub Narębski
@JakubNarębski,谢谢您。您的评论是正确的答案。 - gilly3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接