我通常通过“ git diff commit ^!”检查提交的内容。但是,当我将其应用于初始提交时,之后会看到来自不同提交的更改混合,而我认为它应该是提交的初始副本。有人可以帮助我从语义上理解它吗?
顺便说一句,我知道如何显示来自stackoverflow question 40883798的init commit有很好的答案。
答案 0 :(得分:1)
我通常通过“ git diff commit ^!”检查提交的内容。
(为什么?通常的命令是git show <commit>
。)
但是,当我将其应用于初始提交时,我看到了[有用的东西]
找到任何修订语法的(简短)说明的地方是the gitrevisons documentation,它说明了^!
后缀:
r1 ^!表示法包括提交 r1 ,但不包括其所有父代。 就其本身而言,此表示法表示单个提交 r1 。
不幸的是,这个解释太短了。在这种情况下,提供对git rev-parse
的修订更为有用:
$ git rev-parse HEAD
b5101f929789889c2e536d915698f58d5c5c6b7a
$ git rev-parse HEAD^1
a562a119833b7202d5c9b9069d1abb40c1f9b59a
从这两个输出中,我们可以看到HEAD
代表哈希ID b5101f929789889c2e536d915698f58d5c5c6b7a
,其第一个父节点是a562a119833b7202d5c9b9069d1abb40c1f9b59a
。这是我们需要理解的:
$ git rev-parse HEAD^!
b5101f929789889c2e536d915698f58d5c5c6b7a
^a562a119833b7202d5c9b9069d1abb40c1f9b59a
实际上,这里的输出表示:
b5101f929789889c2e536d915698f58d5c5c6b7a
开始... a562a119833b7202d5c9b9069d1abb40c1f9b59a
。(哈希ID前面的^
表示“不是”:提交B,但不提交A。)
将此与以下内容进行比较:
$ git rev-parse HEAD^..HEAD
b5101f929789889c2e536d915698f58d5c5c6b7a
^a562a119833b7202d5c9b9069d1abb40c1f9b59a
输出相同!
这对git diff
的含义有些棘手和微妙,因为我们在这里谈论的是git rev-parse
,而不是git diff
。但事实上,当你运行:
git diff <something>
Git内部将<something>
交给git rev-parse
。因此,如果您输入:
git diff HEAD^..HEAD
git diff
在内部将整个字符串HEAD^..HEAD
移交给git rev-parse
的内部版本,并获得“停止于”和“开始于” ID。如果您输入:
git diff HEAD^!
git diff
在内部将整个字符串HEAD^!
移交给git rev-parse
的内部版本,并获得与 same “相同于”和“起始于”的ID。
将提交哈希用于具有一个父对象的任何提交时,情况也是如此:后缀^!
会为父哈希生成一个“ not”,为哈希生成一个“ use”。
但是,当您找到一个 root 提交时-在我的Git的Git存储库中,有很多东西,所以我只用第一个:
$ git rev-list --max-parents=0 HEAD | head -1
0ca71b3737cbb26fbf037aa15b3f58735785e6e3
-当我们给带有{-{1}}的后缀为 this 的哈希ID时,我们得到:
git rev-parse
也就是说,$ git rev-parse 0ca71b3737cbb26fbf037aa15b3f58735785e6e3^!
0ca71b3737cbb26fbf037aa15b3f58735785e6e3
对提交表示是,对所有提交的父母都拒绝了,但是没有父母,所以它什么都不说!
如果将 this 馈送到git rev-parse
(只是一个提交哈希),git diff
命令会认为:啊,您想将给定的提交与任何提交进行比较在您的工作树中。那就是你得到的差异。
请注意,git diff
后缀会为提交的所有 all 父母产生“ not”。对于合并提交,至少有两个(通常正好是两个)父母:
^!
所以:
$ git show -s a562a11983
commit a562a119833b7202d5c9b9069d1abb40c1f9b59a
Merge: 7fa92ba40a ad6f028f06
Author: Junio C Hamano ...
当您给$ $ git rev-parse a562a11983^!
a562a119833b7202d5c9b9069d1abb40c1f9b59a
^7fa92ba40abbe4236226e7d91e664bbeab8c43f2
^ad6f028f067673cadadbc2219fcb0bb864300a6c
的修订说明符扩展到三个或更多提交时,有时会做一些不同的事情。但是,在这种特定情况下,它只是将提交本身与第一个父对象进行比较。默认情况下,git diff
命令将生成一个 combined diff ,在这种情况下,它根本不显示任何内容,因为组合的diff旨在向您显示合并可能存在冲突的地方。
答案 1 :(得分:0)
当您运行git diff并通过提交时,git将显示当前工作树中与该提交相关的更改
git diff [] [-] [……]此表格用于查看 相对于命名的,您在工作树中所做的更改。 您可以使用HEAD将其与最新提交或分支进行比较 与另一个分支的尖端进行比较的名称。
插入符(^
)是对该提交的第一父级的引用。您可以类似的方式引用第二个(^2
,第三个(^3
),依此类推。
通过运行git diff <firstCommit>^
,您在语义上要求“给我当前工作目录与第一次提交的父级第一父级之间的更改”。第一次提交的父级不存在,因此在语义上没有意义。
在git 2.17.1中运行这样的命令会产生错误:
$> git diff 9f3f6c8e4b1dea1de25febbb8248a6c430966236^
$> fatal: ambiguous argument '9f3f6c8e4b1dea1de25febbb8248a6c430966236^': unknown revision or path not in the working tree.