git-gc-"git-gc"和"git-repack-ad"之间有什么区别吗;



git gcgit repack -ad; git prune之间有什么区别吗
如果是,git gc将执行哪些附加步骤(反之亦然)
在空间优化和安全方面,哪个更好?

git gcgit repack -ad; git prune之间有什么区别吗?

不同之处在于,默认情况下,git gc对需要哪些内务管理任务非常保守。例如,除非存储库中松散对象的数量超过某个阈值(可通过gc.auto变量进行配置),否则它不会运行git repack。此外,git gc将运行比git repackgit prune更多的任务。

如果是,git gc将执行哪些附加步骤(反之亦然)?

根据文档,git gc运行:

  • git-prune
  • git-reflog
  • git-repack
  • git-rerere

更具体地说,通过查看gc.c的源代码(第338-343行)1,我们可以看到它最多调用以下命令:

  • pack-refs --all --prune
  • reflog expire --all
  • repack -d -l
  • prune --expire
  • worktree prune --expire
  • rerere gc

根据包的数量(第121-126行),它可以运行带有-A选项的repack(第203-212行):

* If there are too many loose objects, but not too many
* packs, we run "repack -d -l". If there are too many packs,
* we run "repack -A -d -l".  Otherwise we tell the caller
* there is no need.
if (too_many_packs())
add_repack_all_option();
else if (!too_many_loose_objects())
return 0;

注意need_for_gc函数的第211-212行,如果存储库中没有足够的松散对象,则gc根本不会运行。

这在文件中得到了进一步的澄清:

如果有太多松散的物体或太多存储库中的许多包。如果松散物体的数量超过gc.auto配置变量的值,然后全部松动使用CCD_ 30将对象组合成单个包。将gc.auto的值设置为0将禁用松散物体。

如果包数超过gc.autoPackLimit的值,则现有包(用.keep文件标记的包除外)通过使用CCD_ 36的CCD_。

正如您所看到的,git gc努力根据存储库的状态做正确的事情。

在空间优化和安全方面,哪个更好?

通常,运行git gc --auto更好,因为它将尽可能少地完成保持存储库良好状态所需的工作——安全且不浪费太多资源。

但是,请记住,垃圾收集可能已经在某些命令之后自动触发,除非通过将gc.auto配置变量设置为0来禁用此行为。

来自文件:

--auto
使用此选项,git gc检查是否需要任何内务管理;否则,它将退出而不执行任何工作。一些git命令在执行以下操作后运行git gc --auto创建许多松散的对象。

因此,对于大多数存储库,您不需要经常显式运行git gc,因为它已经由您负责了。


1.截至2016年8月8日提交a0a1831

git help gc包含一些提示。。。

可选配置变量gc.rererresolved指示您之前解决的冲突合并记录的保存时间。

可选配置变量gc.reereresolutiond指示您尚未解决的冲突合并记录的保存时间。

我相信,如果你只做git repack -ad; git prune,这些就不会完成。

注意,git prunegit gc运行,前者已与Git 2.22(2019年第二季度)一起进化

"CCD_ 49";已经被教导在可能的情况下利用可达性位图。

请参阅Jeff King(peff)的提交cc80c95、提交c2bf473、提交fde67d6、提交d55a30b(2019年2月14日)
(由Junio C Hamano合并——gitster——于2019年3月7日提交f7213a3)

prune:使用位图进行可达性遍历

修剪通常必须遍历整个提交图,以便查看哪些对象是可访问的
这正是可达性位图想要解决的问题,所以让我们使用它们(当然,如果它们可用的话)。

请参阅此处的可达性位图。

以下是git.git:上的时间

Test                            HEAD^             HEAD
------------------------------------------------------------------------
5304.6: prune with bitmaps      3.65(3.56+0.09)   1.01(0.92+0.08) -72.3%

在linux.git:上

Test                            HEAD^               HEAD
--------------------------------------------------------------------------
5304.6: prune with bitmaps      35.05(34.79+0.23)   3.00(2.78+0.21) -91.4%

测试显示了一个非常优化的情况,因为我们刚刚重新打包,应该可以很好地覆盖位图中的所有引用
但是这实际上是非常现实的:通常情况下,prune是通过"CCD_ 53";正确的重新包装后

实现注意事项:更改实际上是在reachable.c中,因此它将通过";CCD_ 55";,同样
不过,这些并不是定期执行的(正常的"git gc"不使用--stale-fix),所以它们并不值得测量。回归调用方的可能性很低,因为从调用方的角度来看,位图的使用是完全透明的。

和:

参见Jeff King提交的fe6f2b0(2019年4月18日)(peff)
(由Junio C Hamano合并——gitster——于2019年5月8日提交d1311be)

修剪:延迟执行可达性遍历

;CCD_ 60";就是进行完全可达性步行,然后,对于每一个松散的物体,看看我们是否在散步中找到了它
但如果我们没有任何松散的物品,我们就不需要做昂贵的步行第一名。

这个补丁将步行推迟到我们第一次需要看到它后果

注意,这实际上是更一般的优化的特定情况,也就是说,我们只能穿越足够远的距离来找到下面的物体考虑(即,当我们找到遍历时停止它,然后继续再次被问及下一个对象等)
在某些情况下,这可以使我们不必走完全程。但实际上,使用我们的遍历代码有点棘手,如果你有一个无法访问的对象,你无论如何都需要进行一次完整的遍历(如果运行git-repack后确实留下了任何对象,你通常会这样做)。

因此,在实践中,这种懒散的全步行负载抓住了一个简单但常见的情况(即,您刚刚通过git-gc重新打包,没有什么是不可访问的)。

perf脚本相当做作,但它确实展示了改进:

Test                            HEAD^             HEAD
-------------------------------------------------------------------------
5304.4: prune with no objects   3.66(3.60+0.05)   0.00(0.00+0.00) -100.0%

如果我们不小心回归了这个优化,就会让我们知道。

还要注意,我们需要特别注意prune_shallow(),它依赖于我们已经执行了遍历
因此,此优化只能用于非浅层存储库。由于这很容易出错,并且不在现有测试的范围内,所以让我们添加一个额外的测试t5304明确涵盖了这种情况。

prune:使用位图进行可达性遍历

修剪通常必须遍历整个提交图,以便查看哪些对象是可访问的
这正是可达性位图想要解决的问题,所以让我们使用它们(当然,如果它们可用的话)。

以下是git.git:上的时间

Test                            HEAD^             HEAD
------------------------------------------------------------------------
5304.6: prune with bitmaps      3.65(3.56+0.09)   1.01(0.92+0.08) -72.3%

linux.git:

Test                            HEAD^               HEAD
--------------------------------------------------------------------------
5304.6: prune with bitmaps      35.05(34.79+0.23)   3.00(2.78+0.21) -91.4%

测试显示了一个非常优化的情况,因为我们刚刚重新打包并位图应该能很好地覆盖所有引用
但这实际上是非常现实的:通常情况下,prune是通过"CCD_ 67";正确的重新包装后。

关于实现的几个注意事项:

  • 变化实际上是在reachable.c中,因此它将通过";CCD_ 69";,同样
    不过,这些并不是定期执行的(正常的"git gc"不使用--stale-fix),所以它们并不值得测量
    回归调用方的可能性很低,因为位图的使用从调用方的角度来看是完全透明的。

  • 位图情况实际上可以在不创建";CCD_ 72";,相反,调用方可以在位图结果中查找每个对象id。然而,这在运行时将是一个微不足道的改进,并且会使调用程序变得更加复杂
    他们必须分别处理位图和非位图情况,在git-prune的情况下,我们还必须调整prune_shallow(),它依赖于我们的SEEN标志。

  • 因为我们确实创建了真实的对象结构,所以我们通过一些扭曲来创建正确类型的结构
    这不是严格必要的(lookup_unknown_object()就足够了),但使用正确的类型会更节省内存,因为我们已经知道它们了。


当可达性位图生效时(自Git 2.222019以来);不要丢失最近创建的对象和从它们可到达的对象";保护我们免受比赛影响的安全被错误地禁用:Git 2.32(2021年第二季度)已经纠正了这一点。

参见Jeff King(peff)的提交2ba582b,提交1e951c6(2021年4月28日)
(由Junio C Hamano合并——gitster——提交6e08cbd,2021年5月7日)

prune:保存从具有位图的最近对象可访问的内容

报告人:David Emett
签字人:Jeff King

我们将修剪到期传递给mark_reachable_objects(),它不仅会遍历可到达的对象,还会将任何最近的对象视为可达性提示;有关详细信息,请参见d3038d2("prune:保持对象可从最近的对象访问",2014-10-15,Git v2.2.0-rc0-merge)。

然而,这与fde67d6中添加的位图代码路径交互不良("prune:使用位图进行可达性遍历",2019-02-13,Git v2.22.0-rc0-merge在第2批中列出)
如果我们命中位图优化路径,我们会立即返回以避免常规遍历,意外跳过"也穿过最近的";密码

相反,我们应该对位图与常规遍历进行if-else,然后使用"if";最近的";无论在哪种情况下,遍历
这会将"rev_info"重新用于位图,然后进行常规遍历,但这应该可以正常工作(位图代码以常规方式清除挂起的数组,就像常规遍历一样)。

相关内容

  • 没有找到相关文章

最新更新