设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.49.1 → 2.52.0 无更改
-
2.49.0
2025-03-14
- 2.48.1 → 2.48.2 无更改
-
2.48.0
2025-01-10
- 2.43.1 → 2.47.3 无更改
-
2.43.0
2023-11-20
- 2.38.1 → 2.42.4 无更改
-
2.38.0
2022-10-02
- 2.36.1 → 2.37.7 无更改
-
2.36.0
2022-04-18
- 2.33.1 → 2.35.8 无更改
-
2.33.0
2021-08-16
- 2.29.1 → 2.32.7 无更改
-
2.29.0
2020-10-19
- 2.25.1 → 2.28.1 无更改
-
2.25.0
2020-01-13
- 2.24.1 → 2.24.4 无更改
-
2.24.0
2019-11-04
- 2.21.1 → 2.23.4 无更改
-
2.21.0
2019-02-24
- 2.19.1 → 2.20.5 无更改
-
2.19.0
2018-09-10
- 2.17.0 → 2.18.5 无更改
-
2.16.6
2019-12-06
“部分克隆”功能是 Git 的一种性能优化,它允许 Git 在没有完整仓库副本的情况下运行。这项工作的目标是让 Git 更好地处理超大型仓库。
在克隆和获取操作期间,Git 会下载仓库的完整内容和历史记录。这包括仓库生命周期中的所有提交、树和 blob。对于超大型仓库,克隆可能需要数小时(或数天)并占用 100+GiB 的磁盘空间。
在这些仓库中,用户常常不需要很多 blob 和树,例如:
-
树中位于用户工作区域之外的文件。例如,在一个每个提交中包含 50 万个目录和 350 万个文件的仓库中,如果用户只需要源代码树的一个狭窄“锥形”区域,我们可以避免下载许多对象。
-
大型二进制资产。例如,在一个仓库中,如果大型构建工件被签入到树中,我们可以避免下载这些不可合并二进制资产的所有先前版本,而只下载实际引用的版本。
部分克隆允许我们在克隆和获取操作期间 **提前** 避免下载这些不需要的对象,从而减少下载时间和磁盘使用量。缺失的对象可以在稍后按需“按需获取”。
能够稍后提供缺失对象的远程仓库称为 promisor 远程仓库,因为它承诺在请求时发送对象。最初 Git 只支持一个 promisor 远程仓库,即用户从中克隆的 origin 远程仓库,并且该远程仓库配置在“extensions.partialClone”配置选项中。后来实现了对多个 promisor 远程仓库的支持。
使用部分克隆要求用户在线,并且 origin 远程仓库或其他 promisor 远程仓库可用于按需获取缺失的对象。这可能对用户有问题,也可能没有。例如,如果用户可以停留在预先选择的源代码树子集中,他们可能不会遇到任何缺失的对象。或者,如果用户知道他们将离线,他们可以尝试预先获取各种对象。
非目标
部分克隆是一种限制 **在给定提交范围** 内下载的 blob 和树数量的机制——因此,它独立于也不旨在与现有的 DAG 级机制冲突,例如限制请求的提交集(即浅克隆、单分支或获取 引用规范)。
设计概述
部分克隆逻辑上由以下部分组成:
-
一种客户端向服务器描述不需要或不希望的对象的方式。
-
一种服务器从发送给客户端的 packfile 中省略这些不希望的对象的方式。
-
一种客户端优雅地处理缺失对象(以前由服务器省略)的方式。
-
一种客户端按需回填缺失对象的方式。
设计细节
-
一个名为“filter”的新 pack-protocol 功能被添加到 fetch-pack 和 upload-pack 的协商中。
这使用了现有的功能发现机制。请参阅 gitprotocol-pack[5] 中的“filter”。
-
客户端向 clone 和 fetch 传递一个“filter-spec”,该 spec 会传递给服务器,以在 packfile 构建期间请求过滤。
有各种可用的过滤器来适应不同的情况。请参阅 Documentation/rev-list-options.adoc 中的“--filter=<filter-spec>”。
-
在服务器端,pack-objects 在创建“filtered”packfile 时应用所请求的 filter-spec。
这些 filtered packfile 在传统意义上是 **不完整的**,因为它们可能包含引用 packfile 中未包含的对象,而客户端尚没有这些对象的对象。例如,filtered packfile 可能包含引用缺失 blob 的树或标签,或者引用缺失树的提交。
-
在客户端,这些不完整的 packfile 被标记为“promisor packfiles”,并被不同命令以不同方式处理。
-
在客户端,将一个仓库扩展添加到本地配置中,以防止旧版本的 git 由于无法处理的缺失对象而 mid-operation 失败。请参阅
extensions.partialClone在 git-config[1] 中。
处理缺失对象
-
由于部分克隆或获取,或者由于仓库损坏,对象可能缺失。为了区分这些情况,本地仓库将从 promisor 远程仓库获得的此类 filtered packfile 特别标记为“promisor packfiles”。
这些 promisor packfile 由一个具有任意内容的“<name>.promisor”文件(类似于“<name>.keep”文件)组成,除了它们的“<name>.pack”和“<name>.idx”文件。
-
本地仓库将“promisor 对象”视为一个对象,它(尽其所能)知道 promisor 远程仓库承诺拥有它,要么是因为本地仓库在其 promisor packfile 中拥有该对象,要么是因为另一个 promisor 对象引用了它。
当 Git 遇到一个缺失的对象时,Git 可以判断它是否是一个 promisor 对象并适当地处理它。如果不是,Git 可以报告损坏。
这意味着客户端无需显式维护一个昂贵的、需要修改的缺失对象列表。[a]
-
由于几乎所有 Git 代码当前都期望任何引用的对象都存在于本地,并且我们不想迫使每个命令首先执行一次 dry-run,因此添加了一个回退机制,允许 Git 尝试从 promisor 远程仓库动态获取缺失的对象。
当正常的对象查找无法找到对象时,Git 会调用 promisor_remote_get_direct() 来尝试从 promisor 远程仓库获取对象,然后重试对象查找。这允许对象在没有复杂预测算法的情况下被“容错加载”。
出于效率原因,不检查缺失的对象是否确实是 promisor 对象。
动态对象获取通常很慢,因为对象是逐个获取的。
-
checkout(以及任何使用unpack-trees的其他命令)已被教导一次性预取所有必需的缺失 blob。 -
rev-list已被教导打印缺失的对象。这可以被其他命令用于批量预取对象。例如,“git log -p A..B”可能希望首先执行类似“git rev-list --objects --quiet --missing=print A..B”的操作,然后批量预取这些对象。
-
fsck已更新为完全了解 promisor 对象。 -
GC 中的
repack已更新为完全不触碰 promisor packfile,并且只 repack 其他对象。 -
全局变量“fetch_if_missing”用于控制对象查找是否会尝试动态获取缺失的对象或报告错误。
我们对这个全局变量不满意,并希望删除它,但这需要对对象代码进行大量重构,以传递一个额外的标志。
获取缺失对象
-
对象的获取是通过调用“git fetch”子进程来完成的。
-
本地仓库发送一个包含所有请求对象哈希的请求,并且不执行任何 packfile 协商。然后它会收到一个 packfile。
-
由于我们正在重用现有的获取机制,获取当前会获取请求对象所引用的所有对象,即使它们不是必需的。
-
使用
--refetch进行获取将从远程仓库请求一个完整的新的 filtered packfile,该 packfile 可用于更改过滤器而无需动态获取缺失的对象。
使用多个 promisor 远程仓库
可以配置和使用多个 promisor 远程仓库。
这允许用户例如拥有多个地理位置靠近的缓存服务器来获取缺失的 blob,同时继续从中央服务器进行过滤的 git-fetch 命令。
在获取对象时,promisor 远程仓库会一个接一个地尝试,直到所有对象都被获取。
被视为“promisor”远程仓库的远程仓库是由以下配置变量指定的:
-
extensions.partialClone=<name> -
remote.<name>.promisor=true -
remote.<name>.partialCloneFilter=...
只能使用 extensions.partialClone 配置变量配置一个 promisor 远程仓库。此 promisor 远程仓库将在获取对象时作为最后一个被尝试的。
我们决定将其作为我们尝试的最后一个,因为使用多个 promisor 远程仓库的用户很可能是因为其他 promisor 远程仓库在某些方面(例如,它们更近或对某些对象更快)比 origin 更好,而 origin 可能是 extensions.partialClone 指定的远程仓库。
这个理由不是很充分,但必须做出一个选择,而且无论如何,长期计划应该是使顺序某种程度上完全可配置。
但目前,其他 promisor 远程仓库将按照它们在配置文件中出现的顺序进行尝试。
当前限制
-
除了它们在配置文件中出现的顺序之外,无法指定尝试 promisor 远程仓库的顺序。
也无法指定在从一个远程仓库获取时使用的顺序,以及在从另一个远程仓库获取时使用的不同顺序。
-
无法仅将特定对象推送到 promisor 远程仓库。
无法按照特定顺序同时推送到多个 promisor 远程仓库。
-
动态对象获取只会向 promisor 远程仓库请求缺失的对象。我们假设 promisor 远程仓库对仓库有完整的视图,并且可以满足所有此类请求。
-
Repack 本质上将 promisor 和非 promisor packfile 视为 2 个不同的分区,并且不混合它们。
-
动态对象获取会 **为每个项目** 调用一次 fetch-pack,因为大多数算法会遇到一个缺失的对象,并在继续工作之前需要解决它。如果需要许多对象,这可能会产生显著的开销 — 以及多次身份验证请求。
-
动态对象获取目前使用现有的 pack protocol V0,这意味着每个对象都通过 fetch-pack 请求。服务器将在建立连接时发送完整的 info/refs 集。如果存在大量引用,这可能会产生显著的开销。
未来工作
-
改进指定 promisor 远程仓库尝试顺序的方法。
例如,这可以允许明确指定类似:“当从这个远程仓库获取时,我希望按此顺序使用这些 promisor 远程仓库,但是,当推送到或从那个远程仓库获取时,我希望按那个顺序使用那些 promisor 远程仓库。”
-
允许推送到 promisor 远程仓库。
用户可能希望使用多个 promisor 远程仓库进行三角形工作流,每个仓库对仓库都有不完整的视图。
-
允许基于非路径名的过滤器使用 packfile 位图(如果存在)。这只是在初始实现期间的疏忽。
-
研究使用一个长期运行的进程来动态获取一系列对象,如 [5,6] 中所述,以减少进程启动和开销成本。
如果 pack protocol V2 允许该长期运行的进程通过一个长期运行的连接进行一系列请求,那将是很好的。
-
研究 pack protocol V2 以避免每次与服务器连接时广播 info/refs 来动态获取缺失的对象。
-
研究处理 loose promisor 对象的需求。
promisor packfile 中的对象允许引用可以从服务器动态获取的缺失对象。我们曾假设 loose 对象仅在本地创建,因此不应引用缺失的对象。如果,例如,我们动态获取一个缺失的树并将其存储为 loose 对象而不是单个对象 packfile,我们可能需要重新审视这个假设。
这并不一定意味着我们需要将 loose 对象标记为 promisor;放宽对象查找或 is-promisor 函数可能就足够了。
非任务
-
每次出现“按需加载 blob”的主题时,似乎总有人建议允许服务器“猜测”并发送可能与请求对象相关的附加对象。
实际上还没有进行任何这方面的工作;我们只是记录这是一个常见的建议。我们不确定它将如何工作,也没有计划进行这项工作。
服务器发送比请求更多的对象是有效的(即使是对于动态对象获取),但我们不基于此进行构建。
脚注
[a] 昂贵的、需要修改的缺失对象列表:在部分克隆设计的早期,我们讨论了对单个缺失对象列表的需求。这本质上是一个 OID 的排序线性列表,这些 OID 在克隆或后续获取期间被服务器省略。
此文件需要在每次对象查找时加载到内存中。在每次显式的“git fetch”命令 **以及** 任何动态对象获取时,它都需要被读取、更新和重写(类似于 .git/index)。
如果存在许多缺失的对象,读取、更新和写入此文件的成本可能会为每个命令增加显著的开销。例如,如果存在 1 亿个缺失的 blob,此文件在磁盘上至少会是 2GiB。
使用“promisor”概念,我们根据引用它的 packfile 的类型 **推断** 一个缺失的对象。
相关链接
[0] https://crbug.com/git/2 Bug#2:部分克隆
[1] https://lore.kernel.org/git/20170113155253.1644-1-benpeart@microsoft.com/
主题:[RFC] 添加对按需下载 blob 的支持
日期:2017 年 1 月 13 日星期五 10:52:53 -0500
[2] https://lore.kernel.org/git/cover.1506714999.git.jonathantanmy@google.com/
主题:[PATCH 00/18] 部分克隆(从克隆到懒加载获取,共 18 个补丁)
日期:2017 年 9 月 29 日星期五 13:11:36 -0700
[3] https://lore.kernel.org/git/20170426221346.25337-1-jonathantanmy@google.com/
主题:Git 仓库缺失 blob 支持提案
日期:2017 年 4 月 26 日星期三 15:13:46 -0700
[4] https://lore.kernel.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/
主题:[PATCH 00/10] RFC 部分克隆和获取
日期:2017 年 3 月 8 日星期三 18:50:29 +0000
[5] https://lore.kernel.org/git/20170505152802.6724-1-benpeart@microsoft.com/
主题:[PATCH v7 00/10] 将 filter 过程代码重构为可重用模块
日期:2017 年 5 月 5 日星期五 11:27:52 -0400
[6] https://lore.kernel.org/git/20170714132651.170708-1-benpeart@microsoft.com/
主题:[RFC/PATCH v2 0/1] 添加对按需下载 blob 的支持
日期:2017 年 7 月 14 日星期五 09:26:50 -0400