git commit
以提交您暂存的更改通常很快,因为实际上暂存更改已经完成了大部分工作。创建提交只是将索引(也称为“暂存区”)转换为非常轻量级的提交对象,其中包含有关您提交的元数据和一些树对象,这些树对象包含存储库的结构。git add
时,所有文件中的数据都会添加到git的数据库中。该文件的数据随后存储在暂存区中,以便在运行git commit
时,有关该文件的所有信息已经在索引中。因此,代价最高的部分在运行git add
时得到了摊销。git add .
这样的命令来暂存所有更改的文件,它只需要stat
文件以找出它是否更改,如果没有更改,则可以忽略它。derrickstolee
)合并。gitster
--在提交 92b1ea6中合并,2019年7月19日)
commit-graph
: 记录提交图链
现在的文档包括:
通常情况下,存储库以接近恒定的速度增长(每天的提交数)。 随着时间的推移,通过获取操作添加的提交数量要比完整历史记录中的提交数量小得多。
通过创建“链式”提交图,我们可以在不重写整个提交历史的情况下快速写入新的提交数据 ——至少大部分时间是这样的。
提交图链使用多个文件,并且我们使用固定的命名约定来组织这些文件。
每个提交图文件的名称为 $OBJDIR/info/commit-graphs/graph-{hash}.graph
,其中的 {hash}
是该文件底部存储的十六进制哈希值(该哈希值是该哈希之前的文件内容的哈希)。
对于一条提交图链,一个纯文本文件位于 $OBJDIR/info/commit-graphs/commit-graph-chain
,按从“最低”到“最高”的顺序包含这些文件的哈希值。
例如,如果 commit-graph-chain
文件包含以下行:
{hash0}
{hash1}
{hash2}
那么提交图链看起来如下所示:
+-----------------------+
| graph-{hash2}.graph |
+-----------------------+
|
+-----------------------+
| |
| graph-{hash1}.graph |
| |
+-----------------------+
|
+-----------------------+
| |
| |
| |
| graph-{hash0}.graph |
| |
| |
| |
+-----------------------+
X0
为 graph-{hash0}.graph
中的提交数目,X1
为 graph-{hash1}.graph
中的提交数目,以及X2
为 graph-{hash2}.graph
中的提交数目。如果一个提交在 graph-{hash2}.graph
中出现在位置 i
,则我们将其解释为位于位置 (X0 + X1 + i)
的提交,并且这将被用作它的“图位置”。
graph-{hash2}.graph
中的提交使用这些位置来引用它们的父提交,而父提交可能位于 graph-{hash1}.graph
或 graph-{hash0}.graph
中。
我们可以通过检查它在区间 [0, X0)
、[X0, X0 + X1)
、[X0 + X1, X0 + X1 + X2)
中的包含情况来导航到位于任意位置 j
的提交。
git commit-grah
有一个新的write
命令选项:--split
。
commit-graph
: 在内置命令中添加--split
选项
而且相同的文档还补充道:在'
git commit-graph write
'子命令中添加一个新的"--split
"选项。
该选项允许可选行为,即写入一个commit-graph链。当前行为将添加一个包含任何不在现有commit-graph或commit-graph链中的提交的tip commit-graph。
以后的更改将允许合并链条并过期过时的文件。添加一个新的测试脚本(
t5324-split-commit-graph.sh
),演示了这个行为。
--split
选项,将提交图作为多个存储在<dir>/info/commit-graphs
目录下的提交图文件链。如果未指定--size-multiple=<X>
,则令X
等于2。如果新的tip文件有N
个提交,而之前的tip文件有M
个提交,并且X
乘以N
大于M
,则将两个文件合并为一个文件。
如果使用--max-commits=<M>
指定了正整数M
,并且新的tip文件将有超过M
个提交,则将新的tip与之前的tip合并。
最后,如果未指定--expire-time=<datetime>
,则将datetime
设为当前时间。在写入拆分的提交图后,删除所有修改时间早于datetime
的未使用的提交图。
这将有助于处理分叉:
commit-graph
:允许跨交替链
在像分叉网络这样的环境中,拥有一个跨越基础仓库和分叉仓库的提交图链是很有帮助的。
分叉通常是大型仓库上的一小部分数据,但有时分叉可能要大得多。
例如,git-for-windows/git
的提交数量几乎是 git/git 的两倍,因为它在每个主要版本更新时都会变基其提交。
文档 现在包括:
在具有备用存储库的情况下,我们会从本地对象目录开始查找“commit-graph-chain”文件,然后再查找每个备用存储库。跨多个对象目录的链
graph-{hash}
文件可能不再是链的一部分。重要的是要及时从磁盘中删除这些文件。commit-graph-chain
文件之前读取它,但在删除graph-{hash}
文件后仍然查找它们。$OBJDIR/info/commit-graphs/
目录下修改时间早于给定过期窗口的graph-{hash}
文件。git commit-graph write
" 学会了以不同的方式写出分割文件。gitster
)提交。ttaylorr
)提交。gitster
--合并于commit 6a1c17d,2020年5月1日)
builtin/commit-graph.c
:引入拆分策略“no-merge”签名作者:Taylor Blau
以前,可以通过传递'在之前的提交中,我们为支持不同的拆分策略打下了基础。在这个提交中,我们引入了第一个拆分策略:“'
no-merge
'”。传递“
--split=no-merge
”对于希望写入新的增量提交图但又不想花费精力压缩增量链路的调用者来说非常有用(*1)。
--size-multiple=0
'来实现这一点,但自从63020f175f("commit-graph
: prefer default size_mult
when given zero",2020-01-02,Git v2.25.0-rc2 -- merge)之后,情况已经改变。--split=no-merge
'时,提交图机制将永远不会压缩现有链,并且它将始终写入新的增量。"git fsck --no-progress
"(man) still spewed noise from the commit-graph subsystem, which has been corrected with Git 2.42 (Q3 2023).
查看 提交 9281cd0, 提交 7248857, 提交 f5facaa, 提交 eb319d6, 提交 39bdd30, 提交 eda206f (2023年7月7日) 由 Taylor Blau (ttaylorr
) 进行。
(由 Junio C Hamano -- gitster
-- 合并于 提交 6016ee0, 2023年7月18日)
commit-graph.c
:在verify
期间避免重复的进度输出When
git commit-graph
(man) verify was taught how to verify commit-graph chains in 3da4b60 ("commit-graph
: verify chains with--shallow
mode", 2019-06-18, Git v2.23.0-rc0 -- merge listed in batch #6), it produced one line of progress per layer of the commit-graph chain.$ git.compile commit-graph verify Verifying commits in commit graph: 100% (4356/4356), done. Verifying commits in commit graph: 100% (131912/131912), done.
This could be somewhat confusing to users, who may wonder why there are multiple occurrences of "Verifying commits in commit graph".
There are likely good arguments on whether or not there should be one line of progress output per commit-graph layer.
On the one hand, the existing output shows us verifying each individual layer of the chain.
But on the other hand, the fact that a commit-graph may be stored among multiple layers is an implementation detail that the caller need not be aware of.Clarify this by showing a single progress meter regardless of the number of layers in the commit-graph chain.
After this patch, the output reflects the logical contents of a commit-graph chain, instead of showing one line of output per commit-graph layer:$ git.compile commit-graph verify Verifying commits in commit graph: 100% (136268/136268), done.