设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.46.1 → 2.50.1 无更改
-
2.46.0
2024-07-29
描述
本文档旨在描述与 Git 打包相关的一些高级概念。
许多概念目前分散在各种 Git 命令的手册页中,包括 git-pack-objects[1]、git-repack[1] 等,以及 gitformat-pack[5] 和 Documentation/technical
树的一部分。
Git 中打包的许多方面未在本文档中涵盖,而是存在于上述区域。随着时间的推移,这些分散的内容可能会合并到本文档中。
伪合并位图
注意
|
伪合并位图被视为实验性功能,因此配置和许多概念可能会发生变化。 |
背景
当有磁盘上存储的位图用于遍历的一个或多个起点时,可达性位图效率最高。因此,Git 更倾向于为引用尖端的提交存储位图,因为遍历通常从这些点开始。
但是,如果引用数量很大,为*每个*引用尖端存储位图是不可行的。这会占用空间,并且仅仅将所有这些位图进行 OR 运算也代价高昂。
解决这个问题的一种方法是创建表示引用*组*的位图。当遍历查询整个组时,我们可以使用这个单一的位图,而不是单独考虑每个引用。因为这些位图代表了所有提交的假设合并中可达的对象集合,所以我们称之为伪合并位图。
概述
“伪合并位图”用于指代一对位图,如下所示
当给定伪合并的所有提交都列在遍历的任一侧时,伪合并位图可以加速位图遍历,无论是直接(通过在 HAVES
或 WANTS
中明确请求它们)还是间接(在填充遍历期间遇到它们)。
用例
例如,假设存在一个包含大量提交的伪合并位图,所有这些提交都列在某个位图遍历查询的 WANTS
部分中。当启用伪合并位图时,位图机制可以快速确定存在一个伪合并,它满足查询任一侧所需对象的一个子集。然后,我们可以解压缩 EWAH 压缩位图,并将其 OR
运算到结果位图中。相比之下,如果没有伪合并位图,我们将不得不对可能大量单独的位图重复解压缩和 OR
运算步骤,这可能会花费更多的时间。
伪合并的另一个好处出现在 (a) 大量引用,(b) 位图覆盖率差,以及 (c) 深层嵌套树相结合,使得填充遍历相对昂贵的情况。例如,假设有足够多的标签,单独为每个标签生成位图是不可行的。如果没有伪合并位图,计算诸如 git
rev-list
--use-bitmap-index
--count
--objects
--tags
的结果可能需要大量的填充遍历。但是,当大量这些标签一起存储在伪合并位图中时,位图机制可以利用我们只关心所有这些标签可达对象的并集这一事实,从而更快地回答查询。
配置
引用尖端根据两个标准分组到不同的伪合并组中。引用名称匹配一个或多个已定义的伪合并模式,并且可选地匹配该模式内的一个或多个捕获组,这些捕获组进一步划分了该组。
在一个组内,提交可以根据其年龄被视为“稳定”或“不稳定”。这些通过分别设置 bitmapPseudoMerge.
<name>.stableThreshold
和 bitmapPseudoMerge.
<name>.threshold
配置值进行调整。
所有稳定提交都分组为大小相等的伪合并(bitmapPseudoMerge.
<name>.stableSize
)。如果 stableSize
配置设置为例如 100,则早于 stableThreshold
值的前 100 个提交(按提交者日期排序)将形成一个组,接下来的 100 个提交将形成另一个组,依此类推。
在不稳定提交中,伪合并机制将尝试将较旧的提交组合成大组,而不是将较新的提交显示在较小的组中。这是基于以下启发式方法:指向较旧提交的引用比指向较新提交的引用更不容易被修改以指向不同的提交。
组的大小由幂律衰减函数确定,衰减参数大致对应于 f
(n
) =
C*n^
(-k/100
) 函数中的“k”,其中 f
(n
) 描述了第 n
个伪合并组的大小。采样率控制符合条件的提交中有多少百分比被视为候选。阈值参数表示最小年龄(以避免将太新的提交包含在伪合并组中,从而降低其有效性)。“maxMerges”参数设置了单个组中伪合并提交数量的上限
“稳定”相关参数控制“稳定”伪合并组,这些组由固定数量的提交组成,这些提交早于配置的“稳定阈值”值,并且可以按年龄顺序以“stableSize”的块进行分组。
伪合并的具体配置如下
注意
|
bitmapPseudoMerge.* 中的配置选项被认为是实验性的,将来可能会更改或完全删除。有关伪合并位图功能的更多信息,请参阅 gitpacking[7] 的“伪合并位图”部分。 |
- bitmapPseudoMerge.<name>.pattern
-
用于匹配引用名称的正则表达式。由匹配此模式(并满足以下条件,如
bitmapPseudoMerge.
<name>.sampleRate
和bitmapPseudoMerge.
<name>.threshold
)的引用指向的提交将被考虑包含在伪合并位图中。提交被分组到伪合并组中,其依据是是否有任何指向给定提交的引用匹配该模式,该模式是一个扩展正则表达式。
在伪合并组内,提交可以根据模式中的捕获组进一步分组到子组中。这些子分组是通过将正则表达式中的任何捕获组用一个 *-* 连字符连接起来形成的。
例如,如果模式是
refs/tags/
,那么所有标签(如果它们满足以下条件)都将被视为同一伪合并组的候选。但是,如果模式是refs/remotes/
([0-9
])+/tags/
,那么来自不同远程的标签将根据远程编号分组到不同的伪合并组中。 - bitmapPseudoMerge.<name>.decay
-
确定连续伪合并位图组大小减小的速率。必须是非负数。此参数可以被视为函数
f
(n
)=
C
*
n^-k
中的k
,其中f
(n
) 是第 `n` 个组的大小。将衰减率设置为
0
将导致所有组大小相同。将衰减率设置为1
将导致第n
个组的大小是初始组的1/n
。衰减率越高,连续组收缩的速度越快。默认值为1
。如果所有组大小相同,则包含较新提交的组可能比早期组使用频率更低,因为指向较新提交的引用比指向旧提交的引用更有可能被更频繁地更新。
- bitmapPseudoMerge.<name>.sampleRate
-
确定未位图化提交(在引用尖端中)中被选中包含在不稳定伪合并位图中的比例。必须在
0
到1
之间(包含)。默认值为1
。 - bitmapPseudoMerge.<name>.threshold
-
确定未位图化提交(如上所述,在引用尖端中)的最小年龄,这些提交是包含在不稳定伪合并位图中的候选。默认值为
1.week.ago
。 - bitmapPseudoMerge.<name>.maxMerges
-
确定提交可以分布到的伪合并提交的最大数量。
对于其模式不包含任何捕获组的伪合并组,此设置适用于所有匹配正则表达式的提交。对于具有一个或多个捕获组的模式,此设置适用于每个不同的捕获组。
例如,如果您的捕获组是
refs/tags/
,那么此设置会将所有标签分布到最多maxMerges
个伪合并提交中。但是,如果您的捕获组是例如refs/remotes/
([0-9
]+
)/tags/
,那么此设置将单独应用于每个远程的标签集。必须是非负数。默认值为 64。
- bitmapPseudoMerge.<name>.stableThreshold
-
确定提交(如上所述,在引用尖端中,但即使已通过位图覆盖,稳定提交仍被视为候选)的最小年龄,这些提交是稳定伪合并位图的候选。默认值为
1.month.ago
。将此阈值设置为较小的值(例如,1.week.ago)将导致生成更多稳定组(这会产生一次性生成成本),但这些组可能会随着时间而过时。使用较大的值会带来相反的代价(更少的稳定组,但更有用)。
- bitmapPseudoMerge.<name>.stableSize
-
确定稳定伪合并位图的大小(以提交数量计)。默认值为
512
。
示例
假设您有一个包含大量引用的仓库,并且您希望有一个最基本的伪合并位图配置,以增强 refs/
命名空间的位图覆盖率。您可以从以下配置开始
[bitmapPseudoMerge "all"] pattern = "refs/" threshold = now stableThreshold = never sampleRate = 100 maxMerges = 64
这将为所有引用创建伪合并位图,无论其年龄如何,并将它们分组到 64 个伪合并提交中。
如果您想在生成伪合并提交时将标签与分支分开,您可以改为使用捕获组定义模式,如下所示
[bitmapPseudoMerge "all"] pattern = "refs/(heads/tags)/"
相反,假设您正在一个分叉网络仓库中工作,每个分叉由某个数字 ID 指定,并且其引用位于网络中的 refs/virtual/NNN/
(其中 NNN
是与某个分叉对应的数字 ID)。在这种情况下,您可以改为编写类似以下内容
[bitmapPseudoMerge "all"] pattern = "refs/virtual/([0-9]+)/(heads|tags)/" threshold = now stableThreshold = never sampleRate = 100 maxMerges = 64
这将生成类似“1234-heads”和“5678-tags”的伪合并组标识符(分别对应分叉“1234”中的分支和远程“5678”中的标签)。