Maintaining a Git Repository

このページの内容

Maintenance of your Git repository typically involves reducing a repository's size.  If you imported from another version control system, you may need to clean up unnecessary files after the import.  This page focuses on removing large files from a Git repo and contains the following topics:

Be very careful...

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.

Keep in mind that maintenance can be disruptive to repository users. It is a good idea to communicate repository maintenance with your team or repository followers. Make sure everyone has checked in their code and have agreed to cease development during maintenance.

Understanding file removal from Git history

Recall that cloning a repository clones the entire history — including every version of every source code file.  If a user commits a huge file, such as a JAR, every clone thereafter includes this file. Even if a user ends up removing the file from the project with a subsequent commit, the file still exists in the repository history.  To remove this file from your repository you must:

  • プロジェクトの現在のファイルツリーからファイルを削除する
  • リポジトリ履歴からファイルを削除する - Git 履歴を書き換え、履歴を含むすべてのコミットをファイルから削除する
  • 古いコミット履歴を参照する reflog 履歴をすべて削除する
  • リポジトリをリパックし、git gc を使用して、現在は使用していないデータをガーベジコレクトする

Git 「GC」(ガベージ コレクション)は、どのブランチやタグも実際に使用せず、何らの参照もしていないすべてのデータをリポジトリから削除します。ガベージ コレクションを有効にするには、不要ファイルを含むリポジトリ履歴をすべて書き換えて、不要ファイルを参照しないようにする必要があります。これで git gc は現在使用されていないデータを破棄できるようになります。

リポジトリの履歴書き換えは慎重を要する作業です。というのは、すべてのコミットがその親に依存し、どんな小さな変更であっても、以降のすべてのコミットのコミット ID を変更するためです。この作業用に 2 つの自動化ツールが利用できます。

  1. BFG Repo Cleaner - 処理が速く、シンプルで使いやすい。Java 6 以上が必要です。
  2. git filter-branch - 強力ではあるが、設定が難しく、規模の大きいリポジトリの場合、処理が遅い。 コア Git スイートの一部です。

BFG を使用するにしても、filter-branch を使用するにしても、履歴を書き換えたあと、古い履歴をポイントする reflog エントリーを削除し、最終的にはガベージ コレクタを実行して、古いデータを削除する必要があります。 

BFG による履歴の書き換え

BFG は大規模ファイルやパスワードなど、不要なデータを Git リポジトリから削除することを目的とする特別のツールで、(現在のコミットに含まれない)サイズの大きい履歴を簡単に削除する「--strip-blobs-bigger-than」フラグを備えています。

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

(BFG により最新のコンテンツが保護されているため、最新 のコミットに含まれない) サイズが 100MB 以上のファイルは Git リポジトリの履歴から削除されます。必要であれば、ファイル名による指定も可能です。

$ java -jar bfg.jar --delete-files *.mp4

BFG は git filter-branch より 10 倍~ 1000 倍速く、一般的にずっと使いやすいツールです。詳細については、詳しい使用方法使用例を確認してください。

git filter-branch による履歴書き換え(代替方法)

The filter-branch command rewrites a Git repo's revision history, just like the BFG, but the process is slower and more manual. If you don't know where the big file is, your first step will be to find it:

手作業によってリポジトリ内の大規模ファイルを確認する

Antony Stubbs はこの作業を効率的に実行する BASH スクリプトを書きました。 このスクリプトはパックファイルの内容を調べ、大規模ファイルを一覧表示します。ファイルの削除を開始する前に、次の操作を行い、このスクリプトを入手してインストールします。

  1. ローカル システムにスクリプトをダウンロードします。
  2. Git リポジトリにアクセス可能な、既知の場所にスクリプトを置きます。
  3. スクリプトを実行可能にします。

    $ chmod 777 git_find_big.sh
  4. ローカルシステムにリポジトリのクローンを作成します。
  5. リポジトリのルート ディレクトリに移動します。
  6. Git ガベージコレクタを手動で実行します。

    git gc --auto
  7. .git フォルダーのサイズを調べます。

    $ du -hs .git/objects
    45M	.git/objects 

    あとで参照するために、このサイズを書きとめます。

  8. 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 ファイルです。圧縮サイズ欄が最も重要です。aui-dependencies.jarは 169KB に圧縮されますが、emojis.jar は 580KB にしか圧縮されません。emojis.jar が削除の候補です。

filter-branch を実行する

You can pass this command a filter for rewriting the Git index.  For example, a filter can remove a file from every indexed commit.  The syntax for this is the following:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch pathname' commitHASH

The --index-filter option modifies a repo's staging (or index). The --cached option removes a file from the index not the disk.  This is faster as you don't have to checkout each revision before running the filter.  The --ignore-unmatch option in git rm prevents the command from failing if the pathname it is trying to remove isn't there.  By specifying a commit HASH, you remove the pathname from every commit starting with the HASH on up.  To remove from the start, leave this off or you can specify HEAD.  

大規模ファイルが別々のブランチにある場合は、ファイルごとに名前を指定して削除する必要があります。すべてのファイルが 1 つのブランチ内にある場合は、ブランチ自体を削除します。

Option 1: Delete files by name

以下の手順により、大規模ファイルを削除します。

  1. Run the following command to remove the first large file you identified:

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
  2. 残りの大規模ファイルごとに、手順 1 を繰り返します。
  3. リポジトリ内の参照を更新します。filter-branch は、refs/original/ 以下に名前空間を指定して、オリジナル参照のバックアップを作成します。 正しくファイルが削除されたことを確認できたら、次のコマンドを実行して、バックアップされた参照を削除することにより、大規模オブジェクトがガベージ コレクトされます。

    $ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

Option 2: Delete just the branch

すべての大規模ファイルが 1 つのブランチ内にある場合は、ブランチを削除するだけですみます。ブランチの削除により、すべての参照が自動的に削除されます。

  1. ブランチを削除します。

    $ git branch -D PROJ567bugfix
  2. 削除したブランチからの無効な reflog 参照のすべてを削除します。

    $ git reflog expire --expire=now PROJ567bugfix

不要データのガベージ コレクト

  1. (1 つのブランチのみを明示して作業している場合を除き)現在削除ずみのデータからの無効な reflog 参照をすべて削除します。

    $ git reflog expire --expire=now --all
  2. ガベージコレクタを実行し、古いオブジェクトを削除して、リポジトリをリパックします。

    $ git gc --prune=now
  3. すべての変更を Bitbucket リポジトリにプッシュバックします。

    $ git push --all --force
  4. タグもすべてカレントであることを確認します。

    $ git push --tags --force

 

 

最終更新日 2017 年 1 月 18 日

この翻訳に満足しましたか?

はい
いいえ
この記事についてのフィードバックを送信する

お探しの情報が見つかりませんか?

コミュニティへの質問

Powered by Confluence and Scroll Viewport.