Git リポジトリのメンテナンス
Git リポジトリのメンテナンスには一般的に、リポジトリ サイズの縮小が含まれます。他のバージョン管理システムからインポートした場合、インポート後に不要なファイルをクリーンアップする必要がある場合があります。ここでは、Git リポジトリからの大きなファイルの削除について、および、以下のトピックについて説明します。
注意
The procedure and tools on this page use advanced techniques that involve destructive operations. Make sure you read carefully and backup your repository before starting. The easiest way to create a backup is to clone your repository using the --mirror flag, and zip the whole clone. With the backup, if you accidentally corrupt a key element of your repo during maintenance, you can recover.
メンテナンスはリポジトリ ユーザーにとって破壊的になる可能性があることに注意する必要があります。リポジトリをメンテナンスすることについて、ワークスペースのメンバーまたはリポジトリのフォロワーに伝えることをおすすめします。全員がコードをチェックイン済みで、メンテナンス中の開発の一時停止に合意していることを確認してください。
ローカルでサイズを小さくした場合でも、このページで説明されている方法で Git の履歴からファイルを削除しても、Bitbucket Cloud で報告されるリポジトリのサイズが小さくならない場合があることに注意することも重要です。これは、マージされたプル リクエストの差分を保存するために、クローンでは表示されない Git コミットへの追加の参照が Bitbucket Cloud によって保存されるためです。これらの参照を特定して Bitbucket Cloud ストレージから削除するには、当社のサポート チームまでご連絡いただく必要があります。参照を削除すると、過去のプル リクエスト データが削除される可能性があることに注意してください。
Git リポジトリからのファイル削除について理解する
リポジトリをクローンすると、全ソースコード ファイルのすべてのバージョンを含め、履歴全体のクローンが作成されます。ユーザーが JAR など大きいファイルをコミットすると、後から作成するすべてのクローンにこのファイルが含まれます。後のコミットでプロジェクトからこのファイルを削除したとしても、ファイルは依然としてリポジトリ履歴内に存在します。このファイルをリポジトリから削除するには、次の作業が必要です。
プロジェクトの現在のファイルツリーからファイルを削除する
リポジトリ履歴からファイルを削除する - Git 履歴を書き換え、履歴を含むすべてのコミットをファイルから削除する
remove all reflog history that refers to the old commit history
repack the repository, garbage-collecting the now-unused data using git gc
Git 「GC」(ガベージ コレクション)は、どのブランチやタグも実際に使用せず、何らの参照もしていないすべてのデータをリポジトリから削除します。ガベージ コレクションを有効にするには、不要ファイルを含むリポジトリ履歴をすべて書き換えて、不要ファイルを参照しないようにする必要があります。これで git gc は現在使用されていないデータを破棄できるようになります。
リポジトリの履歴書き換えは慎重を要する作業です。というのは、すべてのコミットがその親に依存し、どんな小さな変更であっても、以降のすべてのコミットのコミット ID を変更するためです。この作業用に 2 つの自動化ツールが利用できます。
The BFG Repo Cleaner - fast, simple, easy to use. Require Java 6 or above.
git filter-branch - powerful, tricky to configure, slow on big repositories. Part of the core Git suite.
BFG または filter-branch のいずれを使用した場合も、履歴を書き換えたあとに古い履歴をポイントする reflog エントリを削除し、ガベージ コレクタを実行して古いデータを削除する必要があります。
BFG による履歴の書き換え
The BFG is specifically designed for removing unwanted data like big files or passwords from Git repos, so it has a simple flag that will remove any large historical (not-in-your-current-commit) files: '--strip-blobs-bigger-than'
$ java -jar bfg.jar --strip-blobs-bigger-than 100MAny files over 100MB in size (that aren't in your latest commit - because your latest content is protected by the BFG) will be removed from your Git repository's history. If you'd like to specify files by name, you can do that too:
$ java -jar bfg.jar --delete-files *.mp4The BFG is 10-1000x faster than git filter-branch, and generally much easier to use - check the full usage instructions and examples for more details.
git filter-branch による履歴書き換え(代替方法)
filter-branch コマンドは BFG と同様に Git リポジトリの変更履歴を書き換えますが、処理速度は遅く、手作業も増えます。大規模なファイルの場所がわからない場合、まずそれを見つける必要があります。
手作業によってリポジトリ内の大規模ファイルを確認する
Antony Stubbs has written a BASH script that does this very well. The script examines the contents of your packfile and lists out the large files. Before you begin removing files, do the following to obtain and install this script:
Download the script to your local system.
Git リポジトリにアクセス可能な、既知の場所にスクリプトを置きます。
スクリプトを実行可能にします。
$ chmod 777 git_find_big.shローカルシステムにリポジトリのクローンを作成します。
リポジトリのルート ディレクトリに移動します。
Git ガベージコレクタを手動で実行します。
git gc --auto.git フォルダーのサイズを調べます。
$ du -hs .git/objects 45M .git/objectsあとで参照するために、このサイズを書きとめます。
git_find_big.shスクリプトを実行して、リポジトリ内の大規模なファイルを一覧表示します。$ git_find_big.sh All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file. size pack SHA location 592 580 e3117f48bc305dd1f5ae0df3419a0ce2d9617336 media/img/emojis.jar 550 169 b594a7f59ba7ba9daebb20447a87ea4357874f43 media/js/aui/aui-dependencies.jar 518 514 22f7f9a84905aaec019dae9ea1279a9450277130 media/images/screenshots/issue-tracker-wiki.jar 337 92 1fd8ac97c9fecf74ba6246eacef8288e89b4bff5 media/js/lib/bundle.js 240 239 e0c26d9959bd583e5ef32b6206fc8abe5fea8624 media/img/featuretour/heroshot.pngすべての大規模なファイルが JAR ファイルです。pack サイズ欄が最も重要です。
aui-dependencies.jarは 169 KB に圧縮されていますが、emojis.jarは 580 KB にしか圧縮されていません。emojis.jarが削除の候補です。
filter-branch を実行する
このコマンドに、Git インデックス書き換え用のフィルターを渡すことができます。たとえば、あるフィルターはすべてのインデックス済みコミットからファイルを削除します。このコマンドの構文は次のとおりです。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch pathname' commitHASH
--index-filter オプションは、リポジトリのステージング (またはインデックス) を変更します。--cached オプションは、ディスクではなくインデックスからファイルを削除します。フィルターを実行する前に各リビジョンをチェックアウトする必要がないため、この方が速くなります。git rm の -ignore-unmatch オプションは、削除しようとしている pathname が存在しない場合にコマンドが失敗するのを防ぎます。commit HASH を指定することにより、この HASH 値以上のあらゆるコミットから pathname を削除します。最初から削除するには、この指定をオフにするか、HEAD を指定します。
大規模ファイルが別々のブランチにある場合は、ファイルごとに名前を指定して削除する必要があります。すべてのファイルが 1 つのブランチ内にある場合は、ブランチ自体を削除します。
オプション 1: 名前を指定してファイルを削除する
以下の手順により、大規模ファイルを削除します。
次のコマンドを実行し、特定した最初の大規模ファイルを削除します。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD残りの大規模ファイルごとに、手順 1 を繰り返します。
リポジトリ内の参照を更新します。
filter-branchは、refs/original/以下に名前空間を指定して、オリジナル参照のバックアップを作成します。正しくファイルが削除されたことを確認できたら、次のコマンドを実行して、バックアップされた参照を削除することにより、大規模なオブジェクトのガベージ コレクトを行わせることができます。$ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
オプション 2: ブランチのみを削除する
すべての大規模ファイルが 1 つのブランチ内にある場合は、ブランチを削除するだけですみます。ブランチの削除により、すべての参照が自動的に削除されます。
ブランチを削除します。
$ git branch -D PROJ567bugfix削除したブランチからの無効な reflog 参照のすべてを削除します。
$ git reflog expire --expire=now PROJ567bugfix
不要データのガベージ コレクト
(1 つのブランチのみを明示して作業している場合を除き)現在削除ずみのデータからの無効な reflog 参照をすべて削除します。
$ git reflog expire --expire=now --allガベージコレクタを実行し、古いオブジェクトを削除して、リポジトリをリパックします。
$ git gc --prune=nowすべての変更を Bitbucket リポジトリにプッシュバックします。
$ git push --all --forceタグもすべてカレントであることを確認します。
$ git push --tags --force
この内容はお役に立ちましたか?