我已经关闭了git恼人的自动重新打包功能(我想大多数git用户在使用git时都知道“重新打包以获得最佳性能”的消息),而是用cronjob调用“git gc”。
但是我不确定这是否足够,我是否应该在“git gc”之前或之后运行“git repack”。
“git repack”和“git gc”的联机帮助页没有提到两者之间的任何联系,而“git repack”的联机帮助页实际上包含了这样一句话:
相反,松散的不可访问对象将在下一次git gc调用时根据正常的过期规则被删除。
这意味着“git gc”并不能满足所有的内务处理任务,还需要“git repack”。这是正确的吗?git应该使用什么内务处理命令?
2条答案
按热度按时间ie3xauqp1#
git repack
只是重新打包对象。git gc
重新打包它们并丢弃旧的无法访问的对象。要验证您是否可以在
git gc
之前和之后执行类似find .git/objects
的操作:之前,你应该看到所有的新对象作为单独的文件。之后,应该只有一个大的包文件。要了解详细信息,您还可以查看代码:在builtin/gc. c中,准备并执行repack命令。
6ss1mwsb2#
2022年更新(8年后)
git gc
将确实运行repack
。但不是你通常的重装。一个新的
git repack --cruft
,产生cruft包。在Git 2.37(Q3 2022)中,引入了一种将无法访问的对象打包成“cruft pack"的机制,而不是将它们以松散的形式弹出以便稍后回收。
用以下方式启动所述机构:
请参见: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可能会导致无法访问的对象无法被完全删除。
在下列情况下可能会发生这种情况:
.mtime
文件反映了松散对象的实际mtime,但cruft包的mtime是“now”。重复此过程将导致无法访问的对象由于重复将对象的mtimes重置为当前时间而无法被修剪。
如果您要在混合版本环境中GC存储库,请考虑在使用
git repack
与git gc
时忽略--cruft
选项,并在所有编写器都理解cruft包之前不设置gc.cruftPacks
配置.备选方案
该设计的显著替代方案包括:
在mtime数据的位置上,选择了一个绑定到包的新辅助文件,以避免使
.idx
复杂化。如果.idx
曾经获得对可选数据块的支持,则将.mtimes
合并到.idx
本身可能是有意义的。在多个cruft包中存储不可达对象(例如,在每次重新打包操作期间创建一个新的cruft包,其中只包含尚未存储在较早cruft包中的不可达对象)的构造要复杂得多,因此在此不进行讨论。当前实现的明显缺点是必须从头重写整个cruft包。
还有:
第1011章:有条件地避免修剪对象
签署人:泰勒·布劳
通过新的选择加入标志从
git gc
(man)公开新的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是否应该成为默认值。
为了确定这样做是否安全,让我们鼓励更多的用户尝试一下。
已经设置了
feature.experimental=true
的用户已经自愿尝试新的和可能破坏性的配置更改,所以让我们对这组用户尝试这个新的默认设置。git config
现在在其手册页中包括:gc.cruftPacks=true
可减少垃圾收集期间无法访问的对象使用的磁盘空间,从而防止松散对象爆炸。Example:
这里不应该生成任何包文件,因为最后两次提交不再可访问。