Git 为什么一系列提交的文件列表与同一范围内每次提交的文件列表的聚合不同?
请注意:Git 为什么一系列提交的文件列表与同一范围内每次提交的文件列表的聚合不同?,git,Git,请注意: C:\xyz\tip [master ≡]> git log --format="%h" b00bf1df0..81317ea59 81317ea59 b7d9617fc C:\xyz\tip [master ≡]> $files1 = git diff-tree --no-commit-id --name-only -r b7d9617fc C:\xyz\tip [master ≡]> $files2 = git diff-tree --no-commit-id -
C:\xyz\tip [master ≡]> git log --format="%h" b00bf1df0..81317ea59
81317ea59
b7d9617fc
C:\xyz\tip [master ≡]> $files1 = git diff-tree --no-commit-id --name-only -r b7d9617fc
C:\xyz\tip [master ≡]> $files2 = git diff-tree --no-commit-id --name-only -r 81317ea59
C:\xyz\tip [master ≡]> $files3 = git diff-tree --no-commit-id --name-only -r b00bf1df0..81317ea59
C:\xyz\tip [master ≡]> $files1.Length
17
C:\xyz\tip [master ≡]> $files2.Length
0
C:\xyz\tip [master ≡]> $files3.Length
43
C:\xyz\tip [master ≡]>
因此,提交范围b00bf1df0..81317ea59
只返回两次提交-81317ea59
和b7d9617fc
接下来,我将分别获取这两个提交中的文件列表,然后将整个范围作为一个文件
b7d9617fc
)中的第一次提交产生17个文件(files1.Length
)81317ea59
)中的第二次提交产生0个文件(files2.Length
),这是正常的,因为它是一次合并提交b00bf1df0..81317ea59
它突然变成43个文件(files3.Length
)。请注意,files1
中的所有文件都包含在files3
中,但在files3
中还有很多81317ea59
是一个合并,git diff tree 81317ea59
(带有附加选项)确实不显示任何文件,因为它什么也不做,但是git diff tree b00bf1df0..81317ea59
意味着git diff tree b00bf1df0 81317ea59
,它比较通过以下方式找到的树:
git rev-parse b00bf1df0^{tree}
连同以下各项:
git rev-parse 81317ea59^{tree}
这正好是两个特定的树,所以Git比较了它们
像b00bf1df0..81317ea59
这样的参数意味着对某些Git命令的提交范围(比如Git log
),但绝不意味着对任何Git diff
命令的提交范围,因为Git的diff不能处理范围
运行git-diff-tree-m-r 81317ea59
或(我认为更好)git-show-m 81317ea59会很有帮助。-m
标志使Git分别显示从合并到其每个父级的实际差异。在这里省略--no commit id
选项很重要,这样在使用git diff tree
时,您就可以看到从一个父级到下一个父级的转换
长的
这些差异并不像你想象的那样
(我不确定您使用的是什么shell,因此我将在不使用变量赋值的情况下表示这些shell。)
设置
让我们从一开始,关于参数,有这样的说法:
git diff树[--stdin
][-m
][-s
][-v
][--无提交id
][--pretty
]
[-t
][-r
][-c
|--cc
][--root
][
]
[
][..
]
前两次运行的变量只有一个
参数,因此我们继续阅读以找到:
描述
比较通过两个树对象找到的blob的内容和模式
如果只给定一个,则将提交与其父级进行比较(请参见下面的--stdin)
请注意,git diff tree可以使用封装在提交对象中的树
--name only
和-r
选项在后面描述为将输出限制为发现不同的文件名,并递归到子树中。文档未能解释极其重要的事实,即b00bf1df0..81317ea59
被解释为您编写了b00bf1df0 81317ea59
,即这是git diff tree
的两棵树形式
文档确实很糟糕地解释了第三项,这也是至关重要的,但却深藏在手册页面中。让我们来看一下最后两个选项:
-c
此标志更改了合并提交的显示方式(这意味着只有在命令被给定或--stdin
时,此标志才有用)。它同时显示每个父级与合并结果之间的差异,而不是一次显示一个父级与一个结果之间的成对差异(这是-m
选项所做的)。此外,它只列出从所有父级修改的文件
--cc
此标志更改合并提交修补程序的显示方式,类似于-c
选项。它暗示了-c
和-p
选项,并通过省略父对象中内容只有两个变体且合并结果不经修改地拾取其中一个的无趣大块来进一步压缩修补程序输出。当所有的大块头都不感兴趣时,提交本身和提交日志消息不会显示,就像在任何其他“空差异”情况下一样
这没有提到在没有选项的情况下,当给定一个实际上是提交ID的树ish
参数时,查看合并提交的默认方法是完全忽略提交。这是git-log
和git-diff-tree
的默认差异行为,尽管git-log
至少会首先打印日志消息
(这是“遇到合并提交时不执行任何操作”对于git diff--raw
,行为也是如此,但对于普通的git diff
,或者git show
;这些默认为-c
样式组合的diff。从文档来看,git diff文件
也默认不显示合并,尽管我不确定在什么情况下git diff文件
w我们甚至可以看到合并,因为它比较了索引和工作树。确实,索引可以取消合并,这与diff处理合并的方式类似:每个文件的三个合并槽提供基本和分支提示版本。可能这就是本文所指的。)
差异
您提到commit81317ea59
是一个合并(至少有两个父级)。据推测,提交b7d9617fc
不是合并,而b00bf1df0
是另一个可能或可能的提交
git diff-tree --no-commit-id --name-only -r b7d9617fc
git diff --name-only b7d9617fc^ b7d9617fc
git diff-tree --no-commit-id --name-only -r 81317ea59
git diff-tree --no-commit-id --name-only -r b00bf1df0..81317ea59
git diff --name-only b00bf1df0 81317ea59