今日では違いはありませんgit gc --aggressive
。2007年にLinusが行った提案に従って動作します。下記参照。バージョン2.11(2016年第4四半期)の時点で、gitのデフォルトの深さは50です。サイズ250のウィンドウは、各オブジェクトのより大きなセクションをスキャンするため適切ですが、250の深さは、すべてのチェーンが非常に古いものを参照するため、不適切です。オブジェクト。これにより、今後のすべてのgit操作が遅くなり、ディスク使用量がわずかに少なくなります。
歴史的背景
Linusは、次のようなgit gc --aggressive
場合にのみ使用することを提案しました(完全なメーリングリストの投稿については、以下を参照してください)。悪いパック」または「本当にひどく悪いデルタ」がある「ほとんどの場合、他の場合では、実際には本当に悪いですやるべき事。" その結果、リポジトリを開始したときよりも悪い状態のままになる可能性があります。
「長くて複雑な歴史」をインポートした後、これを適切に行うために彼が提案するコマンドは
git repack -a -d -f --depth=250 --window=250
ただし、これは、リポジトリ履歴から不要なガンクをすでに削除しており、git filter-branch
ドキュメントにあるリポジトリを縮小するためのチェックリストに従っていることを前提としています。
git-filter-branchは、ファイルのサブセットを取り除くために使用できます。通常、--index-filter
と--subdirectory-filter
ます。人々は結果のリポジトリが元のリポジトリよりも小さいことを期待していますが、Gitは指示があるまでオブジェクトを失わないように努力するため、実際にリポジトリを小さくするにはさらにいくつかの手順が必要です。まず、次のことを確認してください。
ブロブがその存続期間にわたって移動された場合、ファイル名のすべてのバリアントを実際に削除しました。git log --name-only --follow --all -- filename
名前の変更を見つけるのに役立ちます。
あなたは本当にすべての参照をフィルタリングしました:--tag-name-filter cat -- --all
を呼び出すときに使用しgit filter-branch
ます。
次に、より小さなリポジトリを取得する2つの方法があります。より安全な方法は、元の状態を維持するクローンを作成することです。
- でクローンし
git clone file:///path/to/repo
ます。クローンには削除されたオブジェクトはありません。git-cloneを参照してください。(プレーンパスでクローンを作成すると、すべてがハードリンクされることに注意してください!)
なんらかの理由で本当にクローンを作成したくない場合は、代わりに次の点を(この順序で)確認してください。これは非常に破壊的なアプローチなので、バックアップを作成するか、クローン作成に戻ります。あなたは警告されました。
git-filter-branchによってバックアップされた元の参照を削除します:say
git for-each-ref --format="%(refname)" refs/original/ |
xargs -n 1 git update-ref -d
すべてのreflogをgit reflog expire --expire=now --all
。で期限切れにします。
ガベージは、で参照されていないすべてのオブジェクトを収集しますgit gc --prune=now
(または、git gc
引数をサポートするのに十分なほど新しくない場合は--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日木曜日、ダニエルベルリンは次のように書いています。
実際、git-gc --aggressive
SVNリポジトリから変換したかどうかに関係なく、ファイルをパックするためにこのばかげたことが行われることがあります。
絶対に。git --aggressive
ほとんど馬鹿です。これは、「本当に持っていることがわかっている」場合にのみ役立ちます。悪いパック自分が行った悪いパッキングの決定をすべて破棄したいます。
これを説明するために、git delta-chainsがどのように機能し、他のほとんどのシステムとどのように異なるかを説明する価値があります(おそらくご存知でしょうが、とにかく基本を説明します)。
他のSCMでは、デルタチェーンは一般的に固定されています。これは「順方向」または「逆方向」であり、リポジトリを操作するにつれて少し進化する可能性がありますが、通常は、ある種の単一のSCMエンティティとして表される単一のファイルへの一連の変更です。CVSでは、それは明らかに*,v
ファイルであり、他の多くのシステムはかなり似たようなことをします。
Gitはデルタチェーンも実行しますが、より「緩く」実行します。固定エンティティはありません。デルタは、gitが(さまざまなかなり成功したヒューリスティックを使用して)優れたデルタ候補であると見なすランダムな他のバージョンに対して生成され、厳密なグループ化ルールはまったくありません。
これは一般的に非常に良いことです。これはさまざまな概念上の理由で優れています(つまり、内部的にgitがリビジョンチェーン全体を気にする必要はありません。デルタに関してはまったく考えていません)が、柔軟性のないデルタルールを取り除くことは意味があるので素晴らしいことでもあります。たとえば、そのgitは、2つのファイルをマージすることにまったく問題はありません*,v
。つまり、隠された意味を持つ任意の「リビジョンファイル」はありません。
また、デルタの選択がはるかに自由形式の質問であることも意味します。デルタチェーンを1つのファイルだけに制限すると、デルタをどうするかについての選択肢は実際には多くありませんが、gitでは、まったく別の問題になる可能性があります。
そして、これが本当にひどい名前の--aggressive
出番です。gitは一般的にデルタ情報を再利用しようとしますが(それは良い考えであり、以前に見つけたすべての良いデルタを再検索するためにCPU時間を無駄にしないため)、時々あなたは「白紙の状態で最初からやり直し、以前のデルタ情報をすべて無視して、新しいデルタのセットを生成してみましょう」と言いたい。
つまり--aggressive
、実際には積極的ではなく、CPU時間を無駄にして、以前に行った決定をやり直すことです。
時にはそれは良いことです。特に一部のインポートツールは、本当にひどく悪いデルタを生成する可能性があります。を使用するものgit fast-import
たとえば、、デルタレイアウトがあまり優れていない可能性が高いため、「白紙の状態から始めたい」と言う価値があるかもしれません。
しかし、ほとんどの場合、他の場合では、それは実際には本当に悪いことです。CPU時間を浪費することになります。特に、以前にデルタ化で実際に優れた仕事をした場合、最終結果では、すでに見つけた優れたデルタをすべて再利用することはできないため、実際には多くの結果になります。悪い結果も!
git gc --aggressive
ドキュメントを削除するためのパッチをJunioに送信します。これは便利な場合がありますが、通常は、それが何をしているのかを非常に深いレベルで本当に理解している場合にのみ役立ちます。そのドキュメントはそれを行うのに役立ちません。
一般に、インクリメンタルgit gc
を実行することは正しいアプローチであり、実行するよりも優れていgit gc --aggressive
ます。古いデルタを再利用し、それらの古いデルタが見つからない場合(そもそもインクリメンタルGCを実行する理由!)、新しいデルタを作成します。
一方、「長くて複雑な歴史の最初のインポート」は、本当に良いデルタを見つけるために多くの時間を費やす価値があるポイントであることは間違いありません。そうすれば、その後のすべてのユーザーは(git gc --aggressive
元に戻すために使用しない限り!)、その1回限りのイベントを利用できます。したがって、特に長い歴史を持つ大規模なプロジェクトの場合は、デルタ検索コードをワイルドにするように指示して、追加の作業を行う価値があります。
したがって、適切にgit gc --aggressive
実行されるのと同等のことは、次のようなことを(一晩で)行うことです
git repack -a -d --depth=250 --window=250
ここで、その深さはデルタチェーンの深さ(古い履歴では長くする-スペースオーバーヘッドの価値があります)であり、ウィンドウは各デルタ候補でスキャンするオブジェクトウィンドウの大きさです。
そして、ここで、-f
フラグを追加することをお勧めします(これは、「古いデルタをすべて削除する」ことです。これは、これが実際に適切な候補を見つけることを実際に確認しようとしているためです。
そして、それは永遠に1日かかるでしょう(つまり、「一晩でやる」こと)。しかし、最終的には、そのリポジトリの下流にいるすべての人が、自分で労力を費やすことなく、はるかに優れたパックを入手できるようになります。
Linus