在git clone和git push过程中,什么会被“克隆”和“推送”

t40tm48m  于 2022-11-27  发布在  Git
关注(0)|答案(3)|浏览(163)

当我运行命令(如

git push

git push origin master

我的回购协议看起来

B--C--D <- master
     /
    A--E--F <- foo-branch

而起源看起来就像

A <- master

push包括提交E和F吗?我知道通常它不包括foo-branch,但是所有的提交仍然会被push吗?
同样,当我这样做的时候

git clone <some-remote-repo>

我知道我通常会得到一个分支(看起来通常是master),但是我是否也有其他分支的提交的本地副本,即使我没有得到指向它们头部的指针?

b4qexyjb

b4qexyjb1#

部分取决于交通:git有“哑传输”(比如使用http一次传输一个对象)和“智能传输”(使用git://ssh://协议,其中两个git相互协商,然后--假设接收方表示没问题--发送方构建一个“瘦包”)。
它还部分依赖于命令:例如,如果你要求一个“浅”克隆,或者一个分支,你通常会得到比“普通”克隆少的结果。而且,当你运行git push时,你可以选择哪些特定的提交ID,如果有的话,你最初会传递给远程仓库,以及你希望它们使用什么分支名称。
不过,现在让我们先忽略浅分支和单分支克隆。
给出以下示例:

B--C--D  <- master
 /
A--E--F    <- foo-branch

git push origin master之间的关系(其refspec可能等同于master:master,即您尚未配置异常推送),其中您的远程origin当前已提交A(对于A它具有什么分支标签并不重要,只要它 * 具有 * A)并且假设智能协议,握手和传输协议开始时大致如下:

(your git) "what options do your support? I have thin-packs etc"
(their git) "I have thin-packs and ofs-delta and so on"
(your git) "ok, send me all your refs and their SHA-1s"
(their git) "refs/heads/master is <SHA-1 of A>"
(their git) "that's all I have"

此时,你的git知道了需要什么样的 commits 才能把所有的提交提交到远程:如果你在你的仓库中运行git rev-list master ^A(当然,填写A的实际SHA-1),就会列出这些提交。没有必要排除额外的SHA-1,因为远程origin除了一个分支外什么都没有,它的提示是commit A
其内部工作方式是git push运行git pack-objects(使用--thin),然后它运行git rev-list,将您要求推送的提交ID传递给它,包含排除项(--not或前缀^),用于他们的git发送给你的所有提交ID(在我们的例子中,这只是一个commit-ID A)。请参阅git rev-list的文档,特别注意--objects-edge选项(或者在使用浅层克隆时使用--objects-edge-aggressive)。
因此,git rev-list输出提交D的ID,加上它的树的ID以及该树的所有子树和blob,* 除非 * 它结束(通过取反后的ID,在本例中是排除提交A^A),远程git必须已经拥有它们。然后,它输出提交C的ID及其树,注意,提交A具有与其相关联的源树;并且假设提交C具有 * 相同 * 的树-例如,假设提交CB的还原。在这种情况下,不需要发送C的树:远程 * 必须 * 拥有它,因为远程已提交A
(This对象查找可以通过位图来优化。我记得有一篇github博客文章描述了这些位图的开发,它是一个解决方案,可以解决遍历大量提交图的相当缓慢的过程,以便根据一些分支提示ID来查找哪些对象必须已经在某个远程仓库中。这对他们有很大的帮助,因为智能协议中的获取过程与推送过程是对称的:我们只需交换发送和接收角色。)
在任何情况下,git rev-list的输出都会提供给git pack-objects --thin。这提供了所有要获取的对象ID(提交D,如果需要的话,提交它的树,以及任何需要的子树和blob;提交C和所需对象;提交B和所需对象),以及明确 not 要获取的ID:提交A及其对象,如果在A之前有提交,则提交那些对象及其对象。pack-objects步骤创建一个delta压缩包,其中“take these objects”对象相对于“don 't take these other objects”对象进行压缩。
举一个超级简化的例子,假设A的树包含一个10 MB的文件,其最后一行是“The end”。假设B的树包含一个几乎相同的文件,只是去掉了“The end”。Git可以将这个文件压缩成指令“start with blob,then remove the last line”。这些指令的长度远小于10 MB,并且允许在“精简包”中使用。
这个“thin pack”是通过网络电话连接(或任何连接两个git示例的数据线)发送的,接收方会将它“加厚”成普通的git pack(普通pack不允许对不在包中的对象进行增量压缩)。
好吧,这是相当长的,但它归结为:你的git不会发送F(因为你没有要求它这样做),也不会发送E(因为你没有发送F),也不会查看这两个提交所附带的两棵树。
如果你运行git clone而不运行--single-branch,你的克隆操作会像往常一样通过调用remote来启动,并获得一个remote的 all 引用列表(就像push!一样)。

From git://git.kernel.org/pub/scm/git/git.git
aa826b651ae3012d1039453b36ed6f1eab939ef9    HEAD
fdca2bed90a7991f2a3afc6a463e45acb03487ac    refs/heads/maint
aa826b651ae3012d1039453b36ed6f1eab939ef9    refs/heads/master
595b96af80404335de2a8c292cee81ed3da24d29    refs/heads/next
60feb01a0d7c7d54849c233d2824880c57ff9e94    refs/heads/pu
7af04ad560ab8edb07b498d442780a6a794162b0    refs/heads/todo
d5aef6e4d58cfe1549adef5b436f3ace984e8c86    refs/tags/gitgui-0.10.0
3d654be48f65545c4d3e35f5d3bbed5489820930    refs/tags/gitgui-0.10.0^{}

[数百人被剪掉]

然后你的git会向遥控器请求几乎所有的东西。(在这种情况下,"差不多"是不必要的,但是如果他们给你的是refs/而不是heads/tags/,你可能就得不到这些了。你还可以控制你的git带来什么标签。这里的细节有点混乱,但是在大多数普通的仓库中,克隆将带来所有标签。)
你这样说是在错误的假设上犯了错:
我知道我通常会得到一个分支(似乎通常是master分支),但是我是否也有其他分支的提交的本地副本,即使我没有得到指向它们头部的指针?
你的git请求并得到了它们的所有分支,但是你的git也 * 重命名了 * 它们,它们都被重命名为refs/remotes/命名空间,以remote的名字命名(通常是origin,但是-o <name>--origin <name>会改变这种情况)。它们的refs/heads/master变成了你的refs/remotes/origin/master;他们的refs/heads/maint变成了你的refs/remotes/origin/maint;和/或其他信息。
您将看到所有这些(略略),它告诉git branch显示远程跟踪分支。(再一次,"remote-tracking branches"就是全名以refs/remotes/开头的分支。来自特定远程的git fetch通过存储库中的fetch =指令更新相应的远程跟踪分支。s配置条目。)
如果运行git branchgit status,您看到的master实际上是在clone中的最后一步创建的。它实际上并不运行git checkout--它直接内置了相同的代码--但本质上,作为克隆的最后一步操作,它运行的是某个分支名称的git checkout *branch-or-sha1*(或者,作为最后的尝试,一个原始的SHA-1给出一个"分离的HEAD")。

  • 作为参数提供给git clone的值,或者
  • 远程git的HEAD所指向的分支,如果你的分支能够解决这个问题,或者它是在协议协商过程中提供的。1

如果这些都失败了--假设您没有指示clone进程 * not * 执行校验--git clone将从远程数据库获取的原始SHA-1作为远程数据库的HEAD进行校验(在上面的ls-remote输出示例中,这是aa826b651ae3012d1039453b36ed6f1eab939ef9)。
1请注意,HEAD看起来是一个原始的SHA-1。很长一段时间以来,git中有一个bug,如果这个SHA-1对应于至少 * 两个 * 分支名称,git clone就不知道要检查哪个分支。git的人可以添加一个选项,通过这个选项一个git可以告诉另一个git "HEAD指向分支X"。所以现在,即使导入的HEAD与多个导入的refs/heads/*名称匹配,git也可以告诉使用哪一个。

dgtucam1

dgtucam12#

内部的工作方式是git push运行git pack-objects(带有--thin),git pack-objects随后运行git rev-list,并向其传递您要求推送的提交ID
此对象查找可通过位图进行优化。
Git 2.4.7(2015年第三季度)之后就没有了
参见Jeff King ( peff )commit c8a70d3(2015年7月1日)。
(2015年7月10日,由Junio C Hamano -- gitster --合并至commit ace6325
第1011章:修剪提交时禁用--use-bitmap-index
签署人:杰夫·金
可达性位图没有足够的信息来告诉我们哪些提交可能改变了路径"foo",所以当前的代码会产生错误的答案:

git rev-list --use-bitmap-index --count HEAD -- foo

(it默认忽略"foo"限制器)。相反,我们应该退回到普通遍历(退回而不是抱怨是可以的,因为--use-bitmap-index是一个纯粹的优化,可能因为其他原因而不起作用,比如仓库中没有位图)。
这一点在Git 2.26(Q1 2020)中已经提到:对象可达性位图机制和部分克隆机制没有准备好一起工作,因为部分克隆使用的一些对象过滤标准本质上依赖于对象遍历,但位图机制是一种绕过对象遍历的优化。
然而,在某些情况下,他们可以一起工作,他们被教导了这些。
参见Junio C Hamano ( gitster )commit 20a5fd8(2020年2月18日)。
请参阅commit 3ab3185commit 84243dacommit 4f3bd56commit cc4aa28commit 2aaeb9acommit 6663ae0commit 4eb707ecommit ea047a8commit 608d9c9commit 55cb10fcommit 792f811commit d90fe06(2020年2月14日),以及commit e03f928commit acac50dcommit 551cf8b(2020年2月13日),均由Jeff King ( peff )提供。
(由Junio C Hamano -- gitster --合并至commit 0df82d9,2020年3月2日)
我的天啊!拒绝使用pathspecs进行位图遍历
签署人:杰夫·金
rev-list已经拒绝使用具有路径规范限制的位图,因为c8a70d3509("rev-list:删除提交时禁用--使用位图索引",2015 - 07 - 01,Git v2.5.0-rc2--merge).
但这不仅对rev-list是正确的,而且对任何调用prepare_bitmap_walk()的人也是正确的;代码不适合处理这个案子
我们从来没有注意到,因为唯一的其他调用者永远不会通过路径规范限制器。
但是无论如何,我们还是把检查推进到prepare_bitmap_walk()中,这是一个更合理的位置,因为调用者不需要知道细节(而且必须准备好回到常规遍历,因为存储库中可能没有位图)。
这也会让我们为_is_处理这个案例的一天做好准备,但这是不太可能的。例如,我们可以使用位图来生成一组提交,然后对每个提交进行diff,看看它是否与路径规范匹配。
这将比实际遍历提交的简单遍历稍快。
但是您可能会做得更好,利用更新的commit-graph特性,使遍历提交变得非常便宜。
在Git 2.27(Q2 2020)中,带有对象过滤器"--filter=tree:0"的对象遍历现在可以利用压缩位图。
2010年5月10日,第12届全国人民代表大会常务委员会第30次会议通过《中华人民共和国国籍法》。
2010年5月4日,《中国日报》第35期(2010年5月4日)。
(2020年5月13日,由Junio C Hamano -- gitster --commit 69ae8ff中合并)
我的天啊!使对象过滤函数通用
签署人:泰勒·布劳
在("pack-bitmap:实现BLOB_NONE过滤",2020 - 02 - 14,Git v2.26.0-rc0--mergebatch #8中列出),为" LOFC_BLOB_NONE "过滤器添加了对位图的过滤支持。
在未来,我们希望增加对过滤器的支持,这些过滤器的行为就好像它们排除了某种类型的对象,例如,深度为0的树深度过滤器。
为此,请使一些用于过滤的函数更具通用性,如"find_tip_blobs"和"filter_bitmap_blob_none",以便它们可以处理任意对象类型。
为此,创建"find_tip_objects"和"filter_bitmap_exclude_type",并根据它们重新定义上述函数。
使用Git 2.32(Q2 2021),优化"rev-list--use-bitmap-index --objects(man)角格,使用负标签作为停止点。
它参与描述在git clonegit push期间"克隆"和"推送"了什么内容,此时请注意标记:
参见commit 540cdc1(2021年3月22日),作者Patrick Steinhardt ( pks-t )
(由Junio C Hamano -- gitster --合并于commit 58840e6,2021年4月7日)

  • -避免遍历不感兴趣标记所引用的对象
    签署人:帕特里克·斯坦哈特ps@pks.im.
    当准备位图遍历时,我们首先通过迭代挂起对象集来建立拥有和想要对象集:如果一个对象被标记为不感兴趣,那么它就被声明为我们已经拥有的对象,否则就被声明为我们想要的对象。
    这两个集合然后被用来计算我们需要获得哪些传递性引用对象。
    这里的一个特例是标记对象:当一个标签被请求时,我们将它解析为它的第一个非标签对象,并将解析后的对象以及标签本身添加到have或want集合中。
    假设uninteresting-property总是传播到被引用的对象,很明显,如果标记是不感兴趣的,那么它的子对象也是不感兴趣的,反之亦然。

但是我们无法传播该标志,这实际上意味着被引用的对象将始终是有趣的,除非它们已经被显式标记为不感兴趣。
这种贴错标签不会影响正确性:我们现在在“wants”集合中具有它,并且假定我们稍后对“wants”和“haves”集合的位图进行AND NOT运算,则很明显结果必须相同。
B,我们现在开始不必要地遍历标记的引用对象,以防它是不感兴趣的,即使我们知道每个引用对象无论如何都是不感兴趣的。
在最坏的情况下,这可能导致完全的图遍历,只是为了确定我们不关心任何对象。
通过将UNINTERESTING标志传播到标记对象的指针对象来修复此问题,并将带有负修订的基准添加到p5310。
通过linux.git测试,这显示了一些不错的性能优势:

Test                                                          HEAD~                  HEAD
---------------------------------------------------------------------------------------------------------------
5310.3: repack to disk                                        193.18(181.46+16.42)   194.61(183.41+15.83) +0.7%
5310.4: simulated clone                                       25.93(24.88+1.05)      25.81(24.73+1.08) -0.5%
5310.5: simulated fetch                                       2.64(5.30+0.69)        2.59(5.16+0.65) -1.9%
5310.6: pack to file (bitmap)                                 58.75(57.56+6.30)      58.29(57.61+5.73) -0.8%
5310.7: rev-list (commits)                                    1.45(1.18+0.26)        1.46(1.22+0.24) +0.7%
5310.8: rev-list (objects)                                    15.35(14.22+1.13)      15.30(14.23+1.07) -0.3%
5310.9: rev-list with tag negated via --not --all (objects)   22.49(20.93+1.56)      0.11(0.09+0.01) -99.5%
5310.10: rev-list with negative tag (objects)                 0.61(0.44+0.16)        0.51(0.35+0.16) -16.4%
5310.11: rev-list count with blob:none                        12.15(11.19+0.96)      12.18(11.19+0.99) +0.2%
5310.12: rev-list count with blob:limit=1k                    17.77(15.71+2.06)      17.75(15.63+2.12) -0.1%
5310.13: rev-list count with tree:0                           1.69(1.31+0.38)        1.68(1.28+0.39) -0.6%
5310.14: simulated partial clone                              20.14(19.15+0.98)      19.98(18.93+1.05) -0.8%
5310.16: clone (partial bitmap)                               12.78(13.89+1.07)      12.72(13.99+1.01) -0.5%
5310.17: pack to file (partial bitmap)                        42.07(45.44+2.72)      41.44(44.66+2.80) -1.5%
5310.18: rev-list with tree filter (partial bitmap)           0.44(0.29+0.15)        0.46(0.32+0.14) +4.5%

虽然大多数性能指标评测可能都在噪声范围内,但新添加的5310.9和5310.10性能指标评测的表现始终更好。
在Git 2.32(Q2 2021)中,添加了一个配置变量,强制某些引用的提示被赋予可达性位图。
请参见Taylor Blau ( ttaylorr )commit 3f267a1commit 483fa7fcommit dff5e49(2021年3月31日)。
(2021年4月13日由Junio C Hamano -- gitster --合并至commit 0623669
第1011章:初始提交
签署人:泰勒·布劳
添加一个新的“位图”测试工具,该工具可用于列出已接收位图的提交。
理论上,确定的测试器可以运行“git rev-list --test-bitmap <commit>”(man)来检查“<commit>”是否接收到位图,因为当“--test-bitmap”找不到所请求的提交时,它以非零代码退出。
但这是一个值得依赖的可疑行为,因为可以说'git rev-list'可以继续它的对象遍历,而位图覆盖了它之外的提交。
这将用于测试“pack.preferBitmapTips”的行为
还有:

  • -尊重'打包首选位图提示'
    建议人:杰夫·金
    签署人:泰勒·布劳
    当用位图写新包时,有时指示一些引用前缀是方便的,这些引用前缀在选择哪些提交接收位图时应该接收优先级。
    一个真正有动机的调用者可以通过设置'pack.islandCore'来实现这一点(因为核心岛中的所有提交都被类似地标记为首选),但这要求调用者选择使用delta岛,他们可能想也可能不想这样做.
    引入新的多值配置“pack.preferBitmapTips”,以允许调用方指定引用前缀列表。
    所有前缀包含在'pack.preferBitmapTips'中的引用将把它们的提示标记为“首选”,就像提交被标记为首选以供'pack.islandCore'选择一样。
    动词“prefer“的选择是有意的:在对象上标记NEEDS_BITMAP标志 * 不 * 保证该对象将接收位图。
    它只是保证该提交将比同一窗口中的任何 * 其他 * 提交收到一个位图,间隔为bitmap_writer_select_commits()
    这个补丁增加的测试也反映了这个怪癖。
    它只测试在更改'pack.preferBitmapTips'的值以包含位图后是否为位图选择了提交(默认情况下不接收位图)。
    其他提交可能会丢失其位图,这是选择过程工作方式的副产品((bitmap_writer_select_commits()在看到带有NEEDS_BITMAP标志的提交后忽略窗口的剩余部分)。
    此配置将有助于为多包位图选择重要的引用,因为它们不遵守相同的pack.islandCore配置。
    (They可以,但这样做可能会混淆,因为受delta岛配置影响的是包,而不是位图)。
    例如,在一个fork网络仓库(一个将给定仓库的所有fork都列为远程仓库的仓库)中,将pack.preferBitmapTips设置为'refs/remotes/<root>/heads'和'refs/remotes/<root>/tags'是很有用的,其中'<root>'是一个不透明的标识符,引用位于fork链的基础上的仓库.
    git config现在在其手册页中包括:

pack.preferBitmapTips的第一个字符

当选择哪些提交将接收位图时,在“选择窗口”中的任何其他提交中,首选任何引用顶端的提交,该提交是此配置的任何值的后缀。
请注意,将此配置设置为refs/foo并不意味着必须选择refs/foo/barrefs/foo/baz顶端的提交。这是因为提交是从一系列可变长度的窗口中为位图选择的。
如果在窗口中看到任何引用(此配置的任何值的后缀)顶端的提交,则会立即优先于该窗口中的任何其他提交。
使用Git 2.33(Q3 2021),在构建可达性位图时避免重复工作。
参见commit aa9ad6f(2021年6月14日),作者Jeff King ( peff )
(由Junio C Hamano -- gitster --合并至commit 1ef488e,2021年7月8日)

  • -不要递归到位图中已有的树
    签署人:杰夫·金
    如果一个对象已经在我们正在构建的可达性位图中被提及,那么根据定义,它可以到达的所有对象都是如此。

当我们看到提交已经在位图中时,我们有一个优化来停止遍历提交,但是我们没有对树做同样的操作。
通常不可避免地要递归到树中,因为位图还没有覆盖提交(因为大多数提交通常都有唯一的顶层树)。
但它们通常有与其他提交共享的子树(即提交_didn 't_touch的所有子树)。
并且这些提交中的一些(及其树)可能被位图覆盖。
通常这不是什么大问题,因为在整个遍历过程中,我们总共只访问这些子树一次。
但是如果你有大量的非位图提交,并且你的树很大,那么你可能会毫无理由地打开很多子树。
我们可以在这里对提交使用同样的优化:当我们要打开一个树时,看看它是否在位图中(要么是我们正在构建的,要么是"看到的"位图,当做一个集差时,它覆盖了位图的不感兴趣的一面)。
这一点非常有效,因为我们会在访问任何树之前访问所有提交。
所以即使在这样的历史中:

A -- B

如果"A"在磁盘上有一个位图,但"B"没有,那么在查看B的树之前,我们已经对A的结果进行了OR运算(因此我们实际上只查看B所接触的树)。
对于大多数存储库,p5310产生的时序并不引人注目。
任何改进都在噪声范围内(测试7中的+3.1%肯定是噪声,因为我们没有递归到树中,因此新代码甚至没有运行)。
git.git的结果同样没有意义。
但这里有一些来自其他真实世界的数据库(不公开)。
这棵树的大小和linux.git差不多,但是有大约16k的refs(所以位图覆盖面不够完整):

Test                         HEAD^               HEAD
-------------------------------------------------------------------------
5310.4: simulated clone      38.34(39.86+0.74)   33.95(35.53+0.76) -11.5%
5310.5: simulated fetch      2.29(6.31+0.35)     2.20(5.97+0.41) -3.9%
5310.7: rev-list (commits)   0.99(0.86+0.13)     0.96(0.85+0.11) -3.0%
5310.8: rev-list (objects)   11.32(11.04+0.27)   6.59(6.37+0.21) -41.8%

下面是另一个非常大的树(约340k个条目)和相当多的引用(约10k):

Test                         HEAD^               HEAD
-------------------------------------------------------------------------
5310.3: simulated clone      53.83(54.71+1.54)   39.77(40.76+1.50) -26.1%
5310.4: simulated fetch      19.91(20.11+0.56)   19.79(19.98+0.67) -0.6%
5310.6: rev-list (commits)   0.54(0.44+0.11)     0.51(0.43+0.07) -5.6%
5310.7: rev-list (objects)   24.32(23.59+0.73)   9.85(9.49+0.36) -59.5%

此修补程序在这些较大的情况下提供了实质性的改进,但在较小的情况下有一些缺点(与实际的树遍历相比,位图检查的成本相当小)。
还是Git 2.33:with Git 2.33(Q3 2021)修正了重新打包和使用压缩位图之间的竞争。
参见Jeff King ( peff )commit dc1daac(2021年7月23日)。
(由Junio C Hamano -- gitster --合并于commit 9bcdaab,2021年8月2日)

  • -打开位图时检查包的有效性
    签署人:杰夫·金
    当pack-objects向其要打包的对象列表中添加一个条目时,它可能会标记打包文件和包含该文件的偏移量,稍后我们可以使用它来逐字输出对象。
    如果在我们运行时删除了包文件(例如,被另一个运行"git repack"(man)的进程删除),如果无法打开包文件,我们可能会在use_pack()中死亡。
    我们在4c08018("pack-objects:保护免受消失的包",2011 - 10 - 14,Git v1.7.8-rc0--merge),方法是确保我们可以在将包记录为源之前打开它。
    这会检测到一个在生成打包列表时已经消失的包,因为我们保持包的文件描述符(或一个mmap窗口)打开,这意味着我们可以稍后访问它(除非超过core. packedgitlimit)。
    稍后添加的位图代码不会这样做;它会将条目添加到packlist,而不检查packfile是否仍然有效,因此容易受到此竞争的攻击。
    它需要与4c08018相同的处理。
    但是,与其只在一个位置添加它,不如在打开位图时简单地打开并检查包文件。
    从技术上讲,您可以使用. bitmap,而无需查看. pack文件(例如,如果您只是打印对象列表而不访问它们),但尽早这样做要简单得多。
    这涵盖了包的所有后续直接使用(由于缓存的描述符),而不必直接检查每个包。
    例如,在pack-objects中,我们需要保护packlist条目,但我们也可以作为reuse_partial_pack_from_bitmap()特性的一部分直接访问包。
    此修补程序涵盖了这两种情况。
kr98yfug

kr98yfug3#

previous answer(Git 2.4.7,2015年第三季度,直到Git 2.33,2021年第三季度)展示了位图(store reachability information about the set of objects in a packfile, or a multi-pack index (MIDX)的结构)是如何演变的。
Git 2.37也是如此:
然而,多包索引代码并没有保护包文件(它将依赖于)在使用中被删除,这一点已经在Git 2.37(Q3 2022)中得到了纠正。
参见Taylor Blau ( ttaylorr )commit 4090511commit 5045759commit 58a6abbcommit 44f9fd6(2022年5月24日)。
(2022年6月3日由Junio C Hamano -- gitster --合并至commit 0916804
第1011章:打开MIDX位图时检查首选包的有效性
签署人:泰勒·布劳
当pack-objects向其打包列表中添加一个条目时,它会标记包含该对象的打包文件和偏移量,我们稍后可能会在逐字重用过程中使用这些对象(参见write_reused_pack_verbatim())。
如果所讨论的包文件在后台被删除(例如,由于并发的git repackman)),我们将由于调用use_pack()而导致die(),除非我们在包本身上有一个打开的文件描述符。
(“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“2011-10-14,Git v1.7.8-rc 0--merge)通过在将其记录为有效源以供重用之前提前打开包来解决这个问题。
4c08018的处理方式意味着我们可以容忍消失的包,因为它确保了我们在任何包上总是有一个打开的文件描述符,我们将其标记为可重用的有效源。
这使得竞争只在我们需要关闭一个打开的包的文件描述符(c.f.,packfile.c::get_max_fd_limit()的调用者)* 和 * 该包被删除时发生,在这种情况下,我们将抱怨一个包无法访问和die()
压缩位图代码也执行此操作,因为在dc1daac(“pack-bitmap:打开位图时检查包的有效性”,2021-07-23,Git v2.33.0-rc 0--merge)它也容易受到相同的竞争。
MIDX位图代码不执行此操作,因此容易受到相同争用的攻击。
对负责打开多包位图的首选包的例程应用与dc1daac相同的处理,以结束此竞争。
此修补程序专门处理“首选”包(参见Documentation/technical/pack-format.txt中的“多包索引反向索引”部分),因为包对象依赖于在reuse_partial_packfile_from_bitmap()中逐字重复使用该包的确切块。
因此,如果无法加载该包,位图的实用性将大大降低。
dc1daac类似,我们可以在reuse_partial_packfile_from_bitmap()中添加此检查,因为可以使用MIDX .bitmap而无需打开它的任何包。
但是,尽早进行检查会更简单,因为它涵盖了首选包的所有直接用途。
请注意,早期执行此检查需要我们也早期调用prepare_midx_pack(),因此将该循环的相关部分从load_reverse_index()移动到open_midx_bitmap_1()
注意:另请参阅Git 2.38(Q3 2022)的新设置git -c push.useBitmaps=false push,以禁用git push的打包。
Git 2.39(Q4 2022)确保在使用后释放与三角洲岛相关的结构。
2022年11月17日,第1120期,第1121期。
(2022年11月23日,由Junio C Hamano -- gitster --commit a655f28中合并)
第1001章:使用后的自由岛相关数据
签署人:黄家辉
合著者:埃瓦·阿恩菲约德·比贾马森
签署人:泰勒·布劳
在我的用例中,涉及到www.example.com上的771个Linux岛kernel.org,这将减少大约25 MB的内存使用。
其中大部分来自free_remote_islands,,因为free_config_regexes只节省了大约40 k。
此内存在内存密集型压缩过程的早期保存,使其可用于长过程的剩余部分。

相关问题