“git gc”也运行“git repack”吗?

bvk5enib  于 2022-11-20  发布在  Git
关注(0)|答案(2)|浏览(161)

我已经关闭了git恼人的自动重新打包功能(我想大多数git用户在使用git时都知道“重新打包以获得最佳性能”的消息),而是用cronjob调用“git gc”。
但是我不确定这是否足够,我是否应该在“git gc”之前或之后运行“git repack”。
“git repack”和“git gc”的联机帮助页没有提到两者之间的任何联系,而“git repack”的联机帮助页实际上包含了这样一句话:
相反,松散的不可访问对象将在下一次git gc调用时根据正常的过期规则被删除。
这意味着“git gc”并不能满足所有的内务处理任务,还需要“git repack”。这是正确的吗?git应该使用什么内务处理命令?

ie3xauqp

ie3xauqp1#

git repack只是重新打包对象。
git gc重新打包它们并丢弃旧的无法访问的对象。
要验证您是否可以在git gc之前和之后执行类似find .git/objects的操作:之前,你应该看到所有的新对象作为单独的文件。之后,应该只有一个大的包文件。
要了解详细信息,您还可以查看代码:在builtin/gc. c中,准备并执行repack命令。

6ss1mwsb

6ss1mwsb2#

2022年更新(8年后)
git gc将确实运行repack
但不是你通常的重装。一个新的git repack --cruft,产生cruft包
在Git 2.37(Q3 2022)中,引入了一种将无法访问的对象打包成“cruft pack"的机制,而不是将它们以松散的形式弹出以便稍后回收。
用以下方式启动所述机构:

git config --global gc.cruftPacks true

请参见:2022年5月20日,第16集。
(由Junio C Hamano -- gitster --合并至commit a50036d,2022年6月3日)

Documentation/technical:我的天啊!添加cruft-packs.txt

签署人:泰勒·布劳
创建一个技术文档来解释cruft Package 。
它包含问题的简要概述、一些背景、实现的详细信息,以及这里没有考虑的几种替代方法。
technical/cruft-packs现在在其手册页中包括:

克拉夫特背包

cruft packs功能提供了一种替代Git传统的删除不可达对象的机制。本文档概述了Git的修剪机制,以及如何使用cruft packs来完成相同的任务。
背景
为了从仓库中移除无法访问的对象,Git提供了git repack -Ad(参见git repack)。
[quote] [...]前一个包中无法访问的对象变成松散的、未打包的对象,而不是留在旧包中。[...]松散的无法访问的对象将根据正常的过期规则在下一次调用'git gc'时被修剪。
无法访问的对象不会被立即删除,因为这样做可能会与一个即将被删除的对象竞争。相反,这些无法访问的对象会被存储为松散对象,并一直保持这种状态,直到它们超过过期窗口,此时它们会被git prune删除。
Git必须松散地存储这些不可达对象,以便跟踪它们的每个对象的mtime。如果这些不可达对象被写入一个大包,那么刷新该包(因为其中包含的对象被重写)或创建一个新的不可达对象包都将导致包的mtime被更新,其中的对象将永远不会离开过期窗口。
相反,对象被松散地存储,以便跟踪各个对象m次,并避免所有的松散对象被立刻清新化的情况。
当资料档案库包含许多尚未离开宽限期的无法访问的对象时,这可能会导致不希望出现的情况。
.git/objects的碎片中有大的目录会导致存储库的性能下降。
但是,如果有足够多的不可访问对象,这可能会导致inode饥饿,并降低整个系统的性能。
由于我们永远无法打包这些对象,这些存储库通常会占用大量的磁盘空间,因为我们只能对它们进行zlib压缩,而不能将它们存储在增量链中。
克鲁夫特背包
cruft pack通过将每个对象的mtime包含在单独的文件中,并将其放在包含所有松散对象的单个pack旁边,从而消除了以松散状态存储不可访问对象的需要。
cruft pack是由git repack --cruft在生成一个新的pack时写入的。git pack-objects--cruft选项。注意git repack --cruft是一个典型的all-into-one repack,这意味着生成的pack中的所有内容都是可访问的,而其他内容都是不可访问的。
写入后,--cruft选项指示git repack生成另一个包,其中只包含上一步中未打包的对象(相当于将所有无法访问的对象打包在一起)。
其过程如下:
1.枚举每个对象,将(a)不包含在保留包中,并且(b)其mtime在宽限期内的任何对象标记为遍历提示。
1.根据上一步中收集的提示执行可达性遍历,将沿着的每个对象添加到包中。
1.写出包,沿着记录每个对象时间戳的.mtimes文件。
当被指示写cruft包时,该模式由git repack内部调用。关键的是,核心内保持的包的集合正好是将不被重新打包删除的包的集合;换句话说,它们包含存储库的所有可访问对象。
当一个仓库已经有一个cruft包时,git repack --cruft通常只向其中添加对象。
一个例外是当git repack被赋予--cruft-expiration选项时,它允许生成的cruft包忽略过期的对象,而不是等待git gc稍后使这些对象过期。
git gc通常负责删除过期的不可访问对象。

混合版本环境的注意事项

包含cruft包的仓库将继续与任何旧版本的Git一起工作。

不过,请注意,以前版本的Git无法理解.mtimes文件,因此会使用cruft包的mtime作为其中所有对象的mtime。换句话说,不要指望以前的Git版本(cruft包之前的版本)能够解释甚至读取.mtimes文件的内容。
请注意,在同一个仓库中使用不同版本的Git GC可能会导致无法访问的对象无法被完全删除。
在下列情况下可能会发生这种情况:

  • 运行GC的旧版本Git会使用cruft包的mtime来爆炸现有cruft包中的内容。
  • 运行GC的较新版本将这些松散对象收集到一个cruft包中,其中.mtime文件反映了松散对象的实际mtime,但cruft包的mtime是“now”。

重复此过程将导致无法访问的对象由于重复将对象的mtimes重置为当前时间而无法被修剪。
如果您要在混合版本环境中GC存储库,请考虑在使用git repackgit gc时忽略--cruft选项,并在所有编写器都理解cruft包之前不设置gc.cruftPacks配置.

备选方案

该设计的显著替代方案包括:

  • 每个对象的mtime数据的位置,以及
  • 在多个cruft包中存储无法到达的对象。

在mtime数据的位置上,选择了一个绑定到包的新辅助文件,以避免使.idx复杂化。如果.idx曾经获得对可选数据块的支持,则将.mtimes合并到.idx本身可能是有意义的。
在多个cruft包中存储不可达对象(例如,在每次重新打包操作期间创建一个新的cruft包,其中只包含尚未存储在较早cruft包中的不可达对象)的构造要复杂得多,因此在此不进行讨论。当前实现的明显缺点是必须从头重写整个cruft包。
还有:
第1011章:有条件地避免修剪对象
签署人:泰勒·布劳
通过新的选择加入标志从git gcman)公开新的git repack --cruft(man)模式。
当像git gc --cruft(man)一样调用时,git gc将避免将不可访问的对象分解为松散对象,而是创建一个cruft包和.mtimes文件。
git config现在在其手册页中包括:

gc.cruftPacks的第一个字符串

将无法触及的物品存放在 Package 袋中(参见git repack),而不是作为松散的物品。
默认值为false
git config现在在其手册页中包括:
当运行“git gc”时,它将调用“prune --expire 2.weeks.ago”(如果通过gc.cruftPacks--cruft使用cruft包,则调用“repack --cruft --cruft-expiration 2.weeks.ago”)。
使用此配置变量覆盖宽限期。
值“now”可用于禁用此宽限期,并始终立即清理无法访问的对象,或者“never”可用于禁止清理。当'git gc'与另一个进程同时运行时,此功能有助于防止损坏存储库;请参见git gc的“注解”部分。
git gc现在在其手册页中包括:

--cruft的第一个字符串

当过期的无法触及的物品时,将它们单独 Package 在一个 Package 袋中,而不是将松散的物品作为松散的物品储存。
在Git 2.39(Q4 2022)中,对于选择feature.experimental设置的用户,默认启用gc.cruftpacks
2022年10月26日,第一次世界大战爆发。
(2022年11月8日由Taylor Blau -- ttaylorr --合并至commit bdd42e3

  • ----让功能.实验隐含gc.cruftPacks=true
    签署人:艾米丽·谢弗
    签署人:泰勒·布劳
    我们感兴趣的是探索gc.cruftPacks=true是否应该成为默认值。
    为了确定这样做是否安全,让我们鼓励更多的用户尝试一下。
    已经设置了feature.experimental=true的用户已经自愿尝试新的和可能破坏性的配置更改,所以让我们对这组用户尝试这个新的默认设置。
    git config现在在其手册页中包括:
  • gc.cruftPacks=true可减少垃圾收集期间无法访问的对象使用的磁盘空间,从而防止松散对象爆炸。

Example

git reset HEAD~2
git -c gc.cruftPacks=true gc
# or
git gc --cruft

find .git/objects/pack -name "*.mtimes" >mtimes
sed -e 's/\.mtimes$/\.pack/g' mtimes >packs 
while read pack
do
  test_path_is_file "$pack" || return 1
done <packs

这里不应该生成任何包文件,因为最后两次提交不再可访问。

相关问题