名称

gitpacking - 与 Git 中的打包相关的高级概念

概要

gitpacking

描述

本文档旨在描述与 Git 打包相关的一些高级概念。

许多概念目前分散在各种 Git 命令的手册页面中,包括 git-pack-objects[1]git-repack[1] 以及其他命令,以及 gitformat-pack[5]Documentation/technical 树的一部分。

Git 打包的许多方面未在本文档中介绍,而是位于上述区域中。 随着时间的推移,这些分散的片段可能会合并到本文档中。

伪合并位图

注意
伪合并位图被认为是实验性功能,因此配置和许多想法可能会发生变化。

背景

当我们有一个或多个遍历起点的磁盘存储位图时,可达性位图最有效。 因此,Git 喜欢存储引用顶端提交的位图,因为遍历往往从这些点开始。

但是,如果您有大量的引用,则为每个引用顶端存储位图是不可行的。 这会占用空间,并且仅仅将所有这些位图进行 OR 运算的成本很高。

我们可以处理这个问题的一种方法是创建代表引用的位图。 当遍历询问整个组时,我们可以使用这个单个位图,而不是单独考虑每个引用。 因为这些位图代表对象集,这些对象集可以通过假设合并所有提交来访问,所以我们称它们为伪合并位图。

概述

“伪合并位图”用于指代一对位图,如下所示

提交位图

位图中设置的位描述了伪合并的“合并”位图(如下所示)中包含的提交集。

合并位图

位图中设置的位描述了伪合并的“提交”位图(如上所示)中提交集的可达性闭包。 对于与提交位图中描述的父级集相同的 octopus 合并,将生成相同的位图。

当给定伪合并的所有提交都列在遍历的任何一侧时,无论是直接(通过显式请求它们作为 HAVESWANTS 的一部分)还是间接(通过在填充遍历期间遇到它们),伪合并位图都可以加速位图遍历。

用例

例如,假设存在一个具有大量提交的伪合并位图,所有这些提交都列在某些位图遍历查询的 WANTS 部分中。 启用伪合并位图后,位图机制可以快速确定存在满足查询任一侧所需对象子集的伪合并。 然后,我们可以膨胀 EWAH 压缩的位图,并将其 OR 到结果位图中。 相比之下,如果没有伪合并位图,我们将不得不重复解压缩和 OR 运算步骤,可能要对大量的单独位图进行操作,这可能会花费更多时间。

当存在以下某种组合时,伪合并的另一个好处就会显现出来:(a) 大量的引用,(b) 位图覆盖率差,以及 (c) 深度嵌套的树,使得填充遍历相对昂贵。 例如,假设有足够多的标签,无法单独对每个标签进行位图处理。 如果没有伪合并位图,计算例如 git rev-list --use-bitmap-index --count --objects --tags 的结果可能需要大量的填充遍历。 但是,当大量这些标签存储在伪合并位图中时,位图机制可以利用我们只关心从所有这些标签可访问的对象的并集这一事实,并更快地回答查询。

配置

根据两个标准,引用顶端被分组到不同的伪合并组中。 引用名称与一个或多个定义的伪合并模式匹配,并且可以选择匹配该模式中的一个或多个捕获组,这些捕获组进一步划分该组。

在一个组中,提交可能被认为是“稳定的”或“不稳定的”,具体取决于它们的年龄。 这些可以通过分别设置 bitmapPseudoMerge.<name>.stableThresholdbitmapPseudoMerge.<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>.sampleRatebitmapPseudoMerge.<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

确定未位图化的提交(在引用顶端中)中选择包含在不稳定伪合并位图中的比例。 必须介于 01 之间(包括 01)。 默认为 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)/"

假设您正在一个 fork 网络存储库中工作,每个 fork 由一些数字 ID 指定,并且其引用位于网络中的 refs/virtual/NNN/ 中(其中 NNN 是对应于某个 fork 的数字 ID)。在这种情况下,您可以编写类似以下内容

[bitmapPseudoMerge "all"]
	pattern = "refs/virtual/([0-9]+)/(heads|tags)/"
	threshold = now
	stableThreshold = never
	sampleRate = 100
	maxMerges = 64

这将生成像 "1234-heads" 和 "5678-tags" 这样的伪合并组标识符(分别用于 fork "1234" 中的分支和远程 "5678" 中的标签)。

GIT

属于 git[1] 套件的一部分

scroll-to-top