
...私たちはGardenscapesを開発しました。それはまだWindowsの下で古いGardenscapesの痕跡を持っていました。それはMatch-3でさえありませんでしたが、隠されたオブジェクトでした。そして、誰もゲームが到達する高さを想像することさえできませんでした。
そしてある日...
すべてが始まった経緯
リポジトリにアクセスすると、次のメッセージが表示されました。
「このリポジトリは無効になっています。このリポジトリへのアクセスは、利用規約に違反して、リソースを過度に使用したため、GitHubスタッフによって無効にされました。このリポジトリへのアクセスを復元するには、サポートにお問い合わせください。リポジトリのサイズを小さくする方法について詳しくは、こちらをご覧ください。」
ご想像のとおり、gitリポジトリをホストするためにgithubを使用しています。そのため、突然、戦争を宣言することなく、githubは許可された最大サイズを超えたためにリポジトリをブロックしました。彼らのウェブサイト上の正確な数字は与えられていません。ロック時の.gitフォルダーのサイズは約25GBでした。(注2020:制限が高くなり、githubサイトはリポジトリのサイズが100 GBを超えてはならないことを明示的に示しています)。
どうやってこんなに大きなリポジトリを作ることができたのでしょうか?理由は明らかです。バイナリファイルを格納します。これを行うことは推奨されないとどこにでも書かれていますが、私たちにとってははるかに簡単です。追加の労力をかけずに、ゲームをリポジトリからすぐに起動する必要があります。したがって、グラフィックスやその他のゲームリソースをリポジトリにコミットします。
しかし、これはそれほど悪くはありません。このストーリー全体から学んだ重要な教訓は
歴史のために戦う
したがって、誰にとっても何も機能しません。私たちはチームに、彼らは1日地元で働く必要があるが、あまり一生懸命に努力しなければならないだろうと言いました。そして彼らは何をすべきかを考え始めました。新しいリポジトリが必要であることは明らかですが、そこで何をコミットするのでしょうか。簡単な方法は、すべてのブランチの現在の状態です。しかし、変更の履歴が失われ、みんなのお気に入りのgit blameコマンドが壊れて、すべてが暴走するので、私たちはそれをあまり好きではありませんでした。したがって、これを行うことにしました。バイナリファイルの履歴を消去し、テキストファイルの履歴を保持します。

手順1.バイナリの履歴を削除します
リポジトリの完全なローカルコピーがありました。私たちが最初に見つけたのは、優れたBFGRepo-Cleanerユーティリティでした。とてもシンプルでありながらとても速く、タイトルもいいです。
実行シナリオの例:
java -jar bfg.jar bfg --delete-files *.{pvrtc,webp,png,jpeg,fla,swl,swf,pbi,bin,mask,ods,ogv,ogg,ttf,mp4} path_to_repository
パラメータには、思いつく可能性のあるバイナリファイルのすべての拡張子が含まれています。世界中のすべてのコミットから、これらの拡張子を持つファイルに関する情報が削除されます。ユーティリティはスマートで、ファイルの履歴を削除すると、最新バージョンが残ります。さらに、この最新バージョンは、ブランチの最新のコミットに含まれます。exeファイルとdllファイルの履歴も削除したかったのですが、ユーティリティでエラーが発生しました。どうやら、何らかの理由で、*。exeの形式での処理は禁止されています。さらに、gardenscapes.exeなどのファイルを明示的に指定すると、すべてが機能します。(注2020:バグはすでに修正されている可能性があります)。
手順2.リポジトリを圧縮する
最初のステップの後、リポジトリのサイズはまだ大きいです。この理由は、gitの動作方法です。ファイルへのリンクのみを削除しましたが、ファイル自体は残りました。
ファイルを物理的に削除するには、gitgcコマンドを実行する必要があります。
git reflog expire --expire=now --all
そしてより:
git gc --prune=now --aggressive
これは、ユーティリティの作成者が推奨する一連のコマンドです。ここでgcは本当に長い時間がかかります。さらに、デフォルトのリポジトリ設定では、gitクライアントには操作を完了するのに十分なメモリがなく、タンバリンで踊る必要があります。(注2020:当時は32ビットバージョンのgitがありました。おそらく、これらの問題は64ビットバージョンではなくなりました)。
ステップ3.新しいリポジトリへのコミットの書き込み
これは、クエストの最も興味深い部分であることが判明しました。
以下の内容を理解するには、gitがどのように機能するかを理解する必要があります。あなたは私たちのブログを含む多くの場所でgitについてもっと読むことができます:
したがって、ローカルには非常に多くのコミットがあります。これらのコミットは正しいです。つまり、バイナリの履歴はありません。git pushを実行するだけで十分であり、すべてが正常に機能するようです。しかし、違います!
コマンドgitpush -umasterを実行するだけの場合、次にgitはサーバーにデータをアップロードするプロセスを元気に開始しますが、約2GBのエラーでクラッシュします。これは、一度にそれほど多くのコミットをアップロードできないことを意味します。象を少しずつ食べます。2,000のコミットがおそらく2GBに収まると考えました。その場合、リポジトリの合計サイズは約20,000コミットで、master-v101-v102-v103の4つのブランチに分散されました。(注2020:ええ、若者!それ以来、すべてがはるかに深刻になっています。このリポジトリにはすでに100,000を超えるコミットがあり、数十のリリースブランチがあります。同時に、Githubの制限に適合しています)
まず、ブランチでのコミットの数を考慮します。ヘルプコマンド:
git rev-list --count <branch-name>
たとえば、マスターブランチには約10,000のコミットがあります。これで、gitpushコマンドの拡張構文を使用できます。
git push -u origin HEAD~8000:refs/origin/master
HEAD〜8000 :refs / origin / masterはいわゆるrefspecです。左側には、HEADから8,000離れたコミット、つまり約2,000のコミットまでコミットする必要があると書かれています。そして右側は、それらをリモートマスターブランチにプッシュする必要があるということです。ここでは、refs / origin / masterブランチへのフルパスが必要です。
その後、マスターブランチはまだ存在せず、たとえば、gitfetchはそれをダウンロードできなくなります。これは驚くべきことではありません-結局のところ、彼女のHEADを指すコミットはまだ存在していません。それでも、コマンドgit push HEAD〜8000:refs / origin / masterを繰り返した後、これらのコミットはすでにサーバー上にあるという答えが表示されたため、作業は結局完了しました。
次に、プロセスが明確で、残りの作業をスクリプトに割り当てることができると考えました。最後のコミットは、すべてのバイナリが含まれるため、非常に大きくなります。したがって、念のため、最後の10個のコミットは個別に入力されます。スクリプトは次のようになりました。
git push origin HEAD~6000:refs/origin/master
git push origin HEAD~5000:refs/origin/master
git push origin HEAD~4000:refs/origin/master
git push origin HEAD~3000:refs/origin/master
git push origin HEAD~2000:refs/origin/master
git push origin HEAD~1000:refs/origin/master
git push origin HEAD~10:refs/origin/master
git push origin master
git checkout v101
git push -u origin HEAD~1000:refs/origin/v101
git push origin HEAD~10:refs/origin/v101
git push origin v101
git checkout v102
… ..
つまり、すべてのブランチを一貫してサーバーに書き込み、プッシュごとに2,000コミットし、最後の10コミットを個別に書き込みます。
この全体の話には多くの時間がかかり、時計は夜12時近くに表示されました。それで、私たちはスクリプトを一晩作業するために残し、Cthulhuに適切な祈りを述べ(注2020:当時はまだ比較的人気がありました)、家に帰りました。
最終。ハッピーエンド
午前中、githubサイトでリポジトリを開いた後、スクリプトが正常に機能し、すべてのコミットとブランチが適切に配置されていることを確認しました。
その結果、リポジトリ(.gitフォルダ)のサイズが25GBから7.5GBに削減されました。同時に、すべての重要なコミット履歴(バイナリを除くすべて)が保持されます。ゲームデザイナーはいつもより多くのお茶を飲みました。プログラマーは忘れられない経験をしました。そして、実行可能ファイルをリポジトリにコミットする必要がないように、彼らはそれをどのように行うかを緊急に考え始めましたが、それを使用すると便利です。