これで、同じ「巨大な」ファイルがサーバー上の両方の開発者のフォークに存在します。ハードリンクは自動的に作成されません
実際、Git 2.20 では、デルタ アイランドにより、この問題は解消される可能性があります。 、あるフォークに存在するオブジェクトが、同じフォークされたリポジトリに表示されない別のオブジェクトに対してデルタにならないようにする、デルタ計算を行う新しい方法 .
Christian Couder (chriscool
) による commit fe0ac2f、commit 108f530、commit f64ba53 (2018 年 8 月 16 日) を参照してください。 )。
支援者:Jeff King (peff
)、およびデュイ グエン (pclouds
)。
commit 9eb0986、commit 16d75fa、commit 28b8a73、commit c8d521f (2018 年 8 月 16 日) by Jeff King (peff
) を参照してください。 )。
支援者:Jeff King (peff
)、およびデュイ グエン (pclouds
)。
delta-islands.{c,h}
を追加
ユーザーが既存のリポジトリを「フォーク」できるようにするホスティング プロバイダーは、それらのフォークができるだけ多くのディスク領域を共有することを望んでいます。
代替は、すべてのフォークからのすべてのオブジェクトを一意の中央リポジトリに保持する既存のソリューションですが、これにはいくつかの欠点があります。
特に中央リポジトリをパックする場合、異なるフォークからのオブジェクト間にデルタが作成されます。
これにより、Git が別のフォークからオブジェクトを送信することを避けるために、多くのオブジェクトの新しいデルタを計算する必要があるため、フォークのクローン作成またはフェッチが非常に遅くなり、CPU の負荷が大幅に高くなる可能性があります。
非効率性は主に、オブジェクトが同じフォークに存在しない別のオブジェクトに対して差分化されるときに発生するため、オブジェクトを同じフォークに現れるセットに分割し、「デルタ アイランド」を定義します。
デルタ基地を見つけるとき、同じ島の外にあるオブジェクトをその基地と見なすことはできません。
したがって、「デルタ アイランド」は、異なるフォークからのオブジェクト間のデルタを持たずに、異なるフォークからのオブジェクトを同じリポジトリとパックファイルに保存する方法です。
このパッチは、"delta-islands.{c,h}
でデルタ アイランド メカニズムを実装します。 "、しかしまだそれを利用していません。
'struct object_entry
にいくつかの新しいフィールドが追加されました ' in "pack-objects.h
Documentation/git-pack-objects.txt
を参照 :デルタ島:
デルタ諸島
可能であれば、pack-objects
オンザフライで新しいデルタを検索する必要がないように、既存のオンディスク デルタを再利用しようとします。これは、フェッチを提供するための重要な最適化です。これは、サーバーがほとんどのオブジェクトの膨張をまったく回避し、ディスクから直接バイトを送信できることを意味するためです。
この最適化は、オブジェクトが、受信者が持っていない (まだ送信していない) ベースに対するデルタとして格納されている場合には機能しません。その場合、サーバーはデルタを「壊し」、CPU コストが高い新しいデルタを見つける必要があります。したがって、ディスク上のデルタ関係にあるオブジェクトのセットが、クライアントがフェッチするものと一致することがパフォーマンスにとって重要です。
通常のリポジトリでは、これは自動的に機能する傾向があります。
オブジェクトはほとんどの場合、ブランチとタグから到達可能であり、それがクライアントがフェッチするものです。サーバーで見つかったデルタは、クライアントが持っている、または持つ予定のオブジェクト間にある可能性があります。
しかし、一部のリポジトリ設定では、複数の関連しているが個別の ref ヒントのグループがあり、クライアントはそれらのグループを個別に取得する傾向があります。
たとえば、単一の共有オブジェクト ストアでリポジトリの複数の「フォーク」をホストし、クライアントがそれらを GIT_NAMESPACE を介して個別のリポジトリとして、または代替メカニズムを使用して個別のリポジトリとして表示できるとします。
素朴なリパックは、オブジェクトの最適なデルタが別のフォークでのみ見られるベースに対してあることを発見するかもしれません。
しかし、クライアントがフェッチするとき、ベース オブジェクトがないため、その場で新しいデルタを見つける必要があります。
refs/heads/
以外に多くの参照がある場合、同様の状況が存在する可能性があります と refs/tags/
関連するオブジェクトを指す (例:refs/pull
または refs/changes
一部のホスティング プロバイダーで使用されます)。デフォルトでは、クライアントはヘッドとタグのみをフェッチし、それらの他のグループでのみ見つかったオブジェクトに対するデルタはそのまま送信できません。
デルタ諸島は、参照を個別の「島」にグループ化できるようにすることで、この問題を解決します .
Pack-objects は、どのオブジェクトがどの島から到達可能かを計算し、オブジェクト A
からデルタを作成することを拒否します A
のすべてに存在しない塩基に対して の島々。これにより、パックがわずかに大きくなります (デルタの機会を逃すため) が、1 つの島のフェッチで、島の境界を越えるためにその場でデルタを再計算する必要がないことが保証されます。
ただし、副作用:一部のコマンドはより冗長でした。 Git 2.23 (2019 年第 3 四半期) ではこれが修正されています。
Jeff King (peff
) による commit bdbdf42 (2019 年 6 月 20 日) を参照してください。 )。
delta-islands
:progress
を尊重 フラグ
デルタ島コードは常に「Marked %d islands
」を出力します "、たとえ --no-progress
で進行が抑制されていたとしても または stderr を非 tty に送信します。
progress
を渡しましょう load_delta_islands()
へのブール値 .
resolve_tree_islands()
のプログレス メーターに対して既に同じことを行っています。 .
私はこれを行うことにしました:
shared-objects-database.git/
foo.git/
objects/info/alternate (will have ../../shared-objects-database.git/objects)
bar.git/
objects/info/alternate (will have ../../shared-objects-database.git/objects)
baz.git/
objects/info/alternate (will have ../../shared-objects-database.git/objects)
すべてのフォークは、objects/info/alternates ファイルにエントリを持ち、オブジェクトのデータベース リポジトリへの相対パスを提供します。
同じ名前のリポジトリを持つ異なるユーザーのオブジェクトと参照を保存できるため、オブジェクト データベースをリポジトリにすることが重要です。
手順:
<オール>git init --bare shared-object-database.git
フォークへのプッシュがあるたびに (ポストレシーブ経由で)、または cronjob を実行して、次のコード行を実行します
for r in list-of-forks
do
(cd "$r" &&git push ../shared-objects-database.git "refs/:refs/remotes/$r/ " &&echo ../../shared-objects-database.git/objects>objects/info/alternates# 保存するたびに「太い」オブジェクトを代替オブジェクトに追加します)完了
次に、次の "git gc" で、代替に既に存在するフォーク内のすべてのオブジェクトが削除されます。
git repack -adl
もオプションです!
このようにしてスペースを節約し、サーバー上のそれぞれのフォークで同じデータをプッシュする 2 人のユーザーがオブジェクトを共有できるようにします。
gc.pruneExpire
を設定する必要があります never
までの変数 共有オブジェクト データベース内。安全のために!
オブジェクトをときどきプルーニングするには、すべてのフォークをリモートとして共有、フェッチ、およびプルーニングに追加します。 Git が残りを行います!
(やっと自分に合った解決策を見つけました! (本番環境ではテストされていません! :p この投稿のおかげです。)