git gc –ggressive vs git repack
我正在寻找方法来减lessgit回购大小。 大多数时候,一个好的search指向了我。 我也读过这不是首选的方法。
为什么? 如果我正在运行gc --aggressive
我应该知道gc --aggressive
什么?
$ git repack -a -d --depth=250 --window=250
build议超过gc --aggressive
。 为什么? 如何repack
减less回购大小? 另外,我不太清楚两个标志; – 深度和 – 窗口。
我应该selectgc
还是repack
? 我应该什么时候使用gc
& repack
?
现在没有什么区别: git gc --aggressive
按照Linus在2007年提出的build议进行操作; 见下文。 从版本2.11(2016年第四季度)开始,git默认为50的深度。大小为250的窗口很好,因为它扫描每个对象的较大部分,但深度为250是不好的,因为它使每个链都指向非常深的旧对象,这会减慢所有将来的git操作,使磁盘使用率稍微降低。
历史背景
Linusbuild议(见下面的完整邮件列表文章)使用git gc --aggressive
只有当你有,“一个非常糟糕的包”或“真正可怕的坏三angular洲”,但“几乎总是在其他情况下,这实际上是一件非常糟糕的事情。“结果甚至可能让你的存储库比你开始时更糟!
在他input“一个漫长的历史”之后,他build议这样做的命令是
git repack -a -d -f --depth=250 --window=250
但是这里假设你已经从你的版本库历史logging中删除了不需要的gunk ,并且你已经按照清单缩小了git filter-branch
文档中find的版本库。
git-filter-branch可以用来摆脱文件的一个子集,通常使用
--index-filter
和--subdirectory-filter
。 人们期望得到的存储库比原来的要小,但是你需要多一些步骤才能使它变小,因为Git在你告诉它之前尽量不要丢失你的对象。 首先确保:
如果一个blob在其整个生命周期中移动,你真的删除了所有的文件名称。
git log --name-only --follow --all -- filename
可以帮助你find重命名。你真的过滤了所有的参考:使用
--tag-name-filter cat -- --all
当调用git filter-branch
。然后有两种方法可以获得较小的存储库。 更安全的方法是克隆,保持原来的原样。
- 用
git clone file:///path/to/repo
克隆它git clone file:///path/to/repo
。 克隆将不会有被删除的对象。 请参阅git-clone。 (请注意,使用纯path进行克隆只是硬链接一切!)如果你真的不想克隆它,无论出于什么原因,请检查以下几点(按此顺序)。 这是一个非常具有破坏性的方法,所以做一个备份或者回去克隆它。 你被警告了。
删除由git-filter-branch备份的原始参考:说
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
使用
git reflog expire --expire=now --all
过期所有的git reflog expire --expire=now --all
。垃圾收集所有未被引用的对象与
git gc --prune=now
(或者如果你的git gc
不够新来支持--prune
参数,请使用git repack -ad; git prune
--prune
git repack -ad; git prune
而不是git repack -ad; git prune
)。
Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST) From: Linus Torvalds <torvalds at linux-foundation dot org> To: Daniel Berlin <dberlin at dberlin dot org> cc: David Miller <davem at davemloft dot net>, ismail at pardus dot org dot tr, gcc at gcc dot gnu dot org, git at vger dot kernel dot org Subject: Re: Git and GCC In-Reply-To: <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com> Message-ID: <alpine.LFD.0.9999.0712052132450.13796@woody.linux-foundation.org> References: <4aca3dc20712051947t5fbbb383ua1727c652eb25d7e@mail.gmail.com> <20071205.202047.58135920.davem@davemloft.net> <4aca3dc20712052032n521c344cla07a5df1f2c26cb8@mail.gmail.com> <20071205.204848.227521641.davem@davemloft.net> <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
2007年12月6日星期四,丹尼尔柏林写道:
其实,事实certificate,
git-gc --aggressive
做文件打包的时候会做这个愚蠢的事情,无论你是否从SVNgit-gc --aggressive
转换而来。绝对。
git --aggressive
大多是愚蠢的。 对于“我知道我有一个非常糟糕的包装,我想扔掉我所做的所有不好的包装决定”的情况下,这真的只是有用的。为了解释这一点,值得说明的是(你可能已经意识到了这一点,但是让我通读一下基础知识),git三angular链是如何工作的,以及它们与大多数其他系统如此不同。
在其他供应链pipe理中,三angular洲链通常是固定的。 它可能是“向前”或“向后”,并且在您使用存储库时可能会有所变化,但通常它是对单个文件(表示为某种单一的SCM实体)的一系列更改。 在CVS中,它显然是
*,v
文件,而其他很多系统都是非常相似的。Git也可以做三angular链,但它更“松散”。它没有固定的实体。 Deltas是针对git认为是一个很好的三angular洲候选人的任何随机的其他版本(具有各种相当成功的启发式)而产生的,并且绝对没有严格的分组规则。
这通常是一件非常好的事情。 这对于各种概念上的原因是有好处的( 比如 ,git内部从来不需要关心整个修订链 – 它根本不用考虑delta),但是它也很好,因为摆脱不灵活的delta规则意味着这个git没有任何问题,把两个文件合并在一起,例如 – 没有任何任意的
*,v
“版本文件”,它们有一些隐藏的含义。这也意味着select三angular洲是一个更开放的问题。 如果将delta链限制为只有一个文件,那么对于如何处理delta错误,你确实没有多lessselect,但是在git中,它确实可能是一个完全不同的问题。
而这正是命名的
--aggressive
虽然git一般会试图重复使用delta信息(因为这是一个好主意,并且不会浪费CPU时间重新find我们之前find的所有好的delta) ,有时你想说“让我们从头开始,用一个空白的石板,忽略所有以前的三angular洲信息,并尝试产生一个新的一套增量”。所谓的
--aggressive
并不是真正的侵略性,而是浪费CPU时间来重新做出我们之前做过的决定!有时候这是件好事。 一些import工具尤其可能会产生非常糟糕的三angular洲。 例如,任何使用
git fast-import
东西,可能都没有太多的三angular布局,所以可能值得说“我想从一个干净的石板开始”。但是在其他情况下,几乎总是这样做实际上是一件非常糟糕的事情。 这会浪费CPU时间,特别是如果你之前在delta的时候已经做得很好,最终的结果是不会重复使用你已经find的所有好的 delta,所以你最终会得到一个很好的结果更坏的结果呢!
我会给Junio发一个补丁来删除
git gc --aggressive
文档。 它可能是有用的,但它通常是有用的,只有当你非常深入地了解它在做什么,并且文档不能帮助你做到这一点。一般来说,做增量
git gc
是正确的方法,而且比git gc --aggressive
更好。 它将重新使用旧的三angular洲,当那些旧的三angular洲不能被find(首先做增量GC的原因!)它将会创build新的。另一方面,“长期涉入历史的最初导入”是一个值得花费大量时间寻找真正好的三angular洲的值得肯定的事实。 然后,每一个用户(只要他们不使用
git gc --aggressive
撤销它!)将获得这个一次性事件的优势。 特别是对于历史悠久的大项目,可能值得做一些额外的工作,告诉delta寻找代码狂放。所以相当于
git gc --aggressive
–git gc --aggressive
– 但是做得很好 – 就是做一夜之间的事情git repack -a -d --depth=250 --window=250
那里深度的东西只是三angular洲链的深度(使它们延续旧的历史 – 这是值得的空间开销),而窗口的事情是多大的对象窗口,我们希望每个三angular洲候选人扫描。
在这里,你可能想添加
-f
标志(这是“drop all old deltas”,因为你现在确实试图确定这个标志实际上find了合适的候选者。然后这将需要永远和一天( 即 “一夜之间”)。 但最终的结果是,从该存储库下游的每个人都将得到更好的包,而不必自己花费任何精力。
Linus
我应该什么时候使用gc&repack?
正如我在“ Git垃圾收集似乎并没有完全发挥作用 ”中所提到的那样, git gc --aggressive
本身是不够的,甚至是不够的。
最有效的组合是joingit repack
,而且git prune
:
git gc git repack -Ad # kills in-pack garbage git prune # kills loose garbage
注意:Git 2.11(2016年第四季度)将默认的gc攻击深度设置为50
参见Jeff King( peff
)的 commit 07e7dbf (2016年8月11日) 。
(由Junio C gitster
合并- gitster
-于2016年9月21日的第gitster
提交 )
gc
:默认攻击深度为50“
git gc --aggressive
”用于限制delta链长度为250,这对于获得额外的空间节省来说太深了,并且对于运行时性能是不利的。
限制已经减less到50。总结是:当前的默认值250不会节省太多的空间,并且会花费CPU。 这不是一个好的折衷。
git-gc
的“--aggressive
”标志做了三件事情:
- 使用“
-f
”扔掉现有的增量,并从头开始重新计算- 使用“–window = 250”看起来更难
- 使用“–depth = 250”来制造更长的三angular链
项目(1)和(2)是“积极”重新包装的良好匹配。
他们要求重新包装做更多的计算工作,希望得到更好的包装。 您在重新包装期间支付费用,其他操作只能看到收益。第(3)项不太清楚。
允许更长的链条意味着更less的三angular洲的限制,这意味着可能find更好的,并节省一些空间。
但是这也意味着进入三angular洲的运作必须跟随更长的链条,这会影响他们的performance。
所以这是一个折衷,并不清楚权衡甚至是一个很好的。
(请参阅提交研究 )
您可以看到,随着我们减less深度,常规操作的CPU节省将会提高。
但是我们也可以看到,随着深度的增加,节省的空间并不大。 在10到50之间节省5-10%可能值得CPU折衷。 节省1%,从50到100,或另外0.5%,从100到250可能不是。
说到CPU保存,“ git repack
”学会接受--threads=<n>
选项并将其传递给pack-objects。
见Junio C gitster
( gitster
)的 提交40bcf31 (2017年4月26日) 。
(由Junio C gitster
合并- gitster
-在2017年5月29日的第gitster
提交 )
重新包装:接受
--threads=<n>
并将其传递给pack-objects
我们已经这样做了--window=<n>
和--depth=<n>
; 这将有助于当用户想要强制 – --threads=1
进行可重复testing而不受multithreading的影响。
git gc --aggressive
的问题是,选项名称和文档是误导性的。
正如Linus自己在这封邮件中解释的那样 , git gc --aggressive
基本上是这样做的:
虽然git通常会尝试重新使用delta信息(因为这是一个好主意,而且不会浪费CPU时间重新find我们之前find的所有好的delta),有时候你想说“让我们从头开始,空白石板,并忽略所有以前的增量信息,并尝试生成一组新的增量“。
通常不需要在git中重新计算deltas,因为git决定这些deltas非常灵活。 只有当你知道你真的很差的三angular洲时才有意义。 正如Linus解释的那样,主要使用git fast-import
属于这个类别。
大多数情况下,git在确定有用的变化量方面做得相当不错,使用git gc --aggressive
会给你带来潜在的更糟糕的变化,而浪费大量的CPU时间。
Linus结束他的邮件,得出的结论是git repack
--depth
了一个大的--depth
和--window
在大部分时间是更好的select; 特别是在你导入了一个大型的项目,并希望确保gitfind好的增量。
所以相当于
git gc --aggressive
–git gc --aggressive
– 但是做得很好 – 就是做一夜之间的事情
git repack -a -d --depth=250 --window=250
那里深度的东西只是三angular洲链的深度(使它们延续旧的历史 – 这是值得的空间开销),而窗口的事情是多大的对象窗口,我们希望每个三angular洲候选人扫描。
在这里,你可能想添加
-f
标志(这是“drop all old deltas”,因为你现在确实试图确定这个标志实际上find了合适的候选者。