Reduce repository size

リポジトリが 2 GB の制限に達してしまいましたか。

深呼吸をしてください。本ページの最初の手順にしたがえば、正常の動作状態に復帰できます。

いったん 2 GB の制限を超えてしまうと、プッシュした コミットの削除または打消ししかできず、新しいコミットはプッシュできません。

1 GB のソフト リミットを超えた場合、またはリポジトリのサイズを縮小したい場合

本ページにたどり着いた理由が、すでに 1 GB のソフト リミットを超えたため、またはコンパクトで効果的なリポジトリを維持したいだけである場合、最初のセクションはとばしてもかまいません。本ページの残りの部分では、以下の内容について説明します。

  • Bitbucket 上のリポジトリのサイズを確認する。
  • Git または Mercurial からファイルを削除すると、リポジトリの履歴にどのような影響を与えるか理解する。
  • 望みの結果を得るの​​に役立つ保守手順を選択し、実行する。

 

 

リポジトリ制限の削除

この手順によって、リポジトリからプッシュ制限を削除できます。ただし、完全に問題を解決するには、この手順を完了したあと、本ページに記載する保守手順のどれかをさらに選択する必要があります。

開始する前に、リポジトリをバックアップしましょう! バックアップを作成する最も簡単な方法は、--mirror フラグを使用してリポジトリをクローンし、クローン全体を圧縮するやり方です。

リポジトリをメンテナンスすることについて、チームまたはリポジトリのフォロワーに伝えます 。履歴を書き換えることになるので、実行しようとしていることを全員に周知してください。チームへの連絡は不可欠であり、それが礼儀です。

次の最初のステップをすべて自分で完了して、Bitbucket にプッシュバックします。

  1. git pull --all コマンドを使用して、Bitbucket からリポジトリの最新バージョンをプルします。
  2. メンテナンス中にファイル損失の可能性があっても回復できるように、リポジトリをローカルでバックアップします。
  3. 端末から  -n 4 を付けて git log コマンドを実行します。-n の後の数字で決まるのは、ローカル履歴の最新のコミットを先頭とするログ内のコミット数です。

    $ git log -n 4 

    このコマンドにより、直近の 4 コミットが次のように表示されます。

    $ git log -n 4
    commit 86833d553529f99aad975539b03edce333bd4108
    Merge: b8b6122 d446c3b
    Author: Dan Stevens [Atlassian] <dstevens@atlassian.com>
    Date:Fri Dec 4 14:09:41 2015 -0800
    
     Merged in dstevens/review2 (pull request #9)
    
    Adding add-on context and connect descriptor pages to the nav and concepts section
    
    commit d446c3bb361339c2c6aedb85b38c20959da8e345
    Author: Daniel Stevens <dstevens@atlassian.com>
    Date:Fri Dec 4 13:52:33 2015 -0800
    
    revising scopes and context section to remove bad definition and provide links to complete scopes section.
    
    commit c78869f36fd93bd7ad82d7bdd86f779ef08d3f11
    Author: Daniel Stevens <dstevens@atlassian.com>
    Date:Wed Dec 2 17:13:41 2015 -0800
    
    changing JSON file to JSON object in introduction
    
    commit c1b0c56b1a7aa69d80581a61c9ac45129efadc4f
    Author: Daniel Stevens <dstevens@atlassian.com>
    Date:Wed Dec 2 16:28:32 2015 -0800
    
    Fixing definition of account context to reflect the truth about when it is visible
  4. git reset --hard HEAD~N を使用して、リポジトリ履歴の HEAD をリセットします。この場合、N は HEAD 位置を戻すコミット数です。次の例では、HEAD が 1 コミット戻され、リポジトリ履歴の最後のコミットにセットされます。

    このように HEAD をリセットし、次のステップで変更を強制的にプッシュすることにより、コミット(複数可)内のすべての変更が完全に削除されます。これは破壊的な操作なので、先​​に進む前に、追加したファイルはすべてバックアップします。

    git reset --hard HEAD~1

  5. Push the change to Bitbucket using git push --force to force push the change.

    git push --force 

    Once you push your changes Bitbucket will automatically run an aggressive git gc (git garbage collection) to rewrite the history and reflect your change. Wait a few moments for the system to run the change. If we haven't removed the limitation after 60 minutes and you want to keep troubleshooting, choose one of the methods on this page and do a more complete maintenance on your repository.

    If you've reduced the repository size locally and made a force push and still have a limitation after 60 minutes, you can contact support to run a git gc on the server for you.

再度リポジトリがハード リミットに達しないようにするため、また、1 GB のソフト リミットを削除するためには、本ページの 1 つ以上の手順を使用して、リポジトリで完全な保守サイクルを実施します。

Bitbucket リポジトリ制限

すべてのユーザーに最善かつ最速のサービスを提供するため、リポジトリを次のサイズに制限しています。

  • ソフト リミット1 GB :この時点で、効果的に動作するリポジトリのサイズ上限に達しつつあることを知らせます。ハード リミットに達しないように保守を実行することが必要な場合があります。 
  • ハード リミット2 GB :これは実質的にリポジトリ サイズのストップサインで、リポジトリのサイズを縮小するまで、実行可能な操作を制限します。

リポジトリが 2 GB の制限を超えた場合

ローカル リポジトリを縮小する手順を実施し、Bitbucket に変更をプッシュした後は、aggressive Git gc を自動的に実行してクリーンアップし、作業の再開を可能にします。

Bitbucket リポジトリのサイズ調査

Bitbucket のリポジトリの相対的なサイズを確認するには、設定をクリックし、開いたリポジトリの詳細ページでサイズ行を探します。

  1. Repository details: Find the repository size on this page.
  2. Settings: Notice this link in the left panel.
  3. Size: Each repository includes a size under its name on this page.

理想的には、リポジトリ サイズを 100 MB と 300 MB の間に維持するのがよいでしょう。例をあげると、Git 自体は 222MB、Mercurial 自体は 64MB、Apacheは 225MB あります。これらのオープンソースのリポジトリは次のサイトで確認できます。 https://bitbucket.org/mirror/

Git リポジトリのサイズをコマンドラインで調べる

コマンドラインを使用して、ローカルシステム上のリポジトリのサイズを調べることができます。

Git の場合、次のコマンドを使用します。

git count-objects -v 

このコマンドにより、次のような結果が返されます。

$ git count-objects -v 
count: 0
size: 0
in-pack: 478
packs: 1
size-pack: 92
prune-packable: 0
garbage: 0

size-pack 値はリポジトリが Bitbucket などのリモート サーバーにプッシュされたときのサイズです。size-pack 値はキロバイト単位です。  したがって、上記の例のリポジトリは 1MB もありません。  

ローカルの Mercurial リポジトリのサイズをコマンドラインで調べる

Mercurial にはリポジトリのサイズを調べる特別のコマンドがありません。bundle コマンドを使用して、リポジトリの圧縮ファイルを生成すると、以下の例に示すように、ファイルのサイズ(約 21.658MB)を確認できます。

$ hg bundle --all my-bundle.hg
2474 changesets found
$ ls -al my-bundle.hg 
-rw-r--r-- 1 manthony staff 21658140 Feb 10 15:03 my-bundle.hg

Git リポジトリでのファイル削除を理解する

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

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

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

 

Please note that rewriting history will change the commits ids. As a result, pull requests that reference such commits whose id has been changed, will lose the info related to those commits, and also any comments.

If you would like to keep the pull request history, we suggest that you push the clean version of your repo to a newly created repo, instead of the existing one.

Git 履歴書き換えのしくみ

リポジトリのクローンにより、すべてのソースコード ファイルのすべてのバージョンを含めて、履歴全体のクローンが作成されます。ユーザーが JAR など規模の大きいファイルをコミットする場合、その後で作成するすべてのクローンにこのファイルが含まれます。その後のコミットでプロジェクトから該当のファイルを削除することになったとしても、ファイルは依然としてリポジトリ履歴内に存在します。 リポジトリと履歴からこのファイルを削除するには、次の作業が必要です。

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

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

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 による履歴書き換え(代替方法)

filter-branch コマンドは、BFG と同様に Git リポジトリの改訂履歴を書き換えますが、処理速度は遅く、手作業が多くなります。大規模ファイルの場所がわからない場合、最初に行う手順は、次の 2 つのオプションのいずれかを使用してファイルを見つけることです。

そのあと、ファイルを一つずつ削除するか、特定のブランチを削除するか決める必要があります。どちらにしても、処理を完了するには、Git ガベージコレクションを実行する必要があります。 

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

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 を実行する

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
  2. 残りの大規模ファイルごとに、手順 1 を繰り返します。

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

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

ブランチそのものの削除

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

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

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

    $ git reflog expire --expire=now branch-name

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

  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

Mercurial のリポジトリを縮小する方法 

Mercurial リポジトリのサイズを縮小するには、定期的なメンテナンスが必要です。他のバージョン管理システムからコードをインポートした場合、インポート後に不要なファイルをクリーンアップする必要があります。ここでは Mercurial リポジトリから大規模ファイルを削除することにより、リポジトリのサイズを縮小する方法について説明します。

リポジトリのサイズを縮小するもう一つの方法は、リポジトリを複数の小さなリポジトリに分割することです。この方法はリポジトリ内のディレクトリごとに実行可能で、ディレクトリごとにサブリポジトリを作成します。リポジトリの分割に関する詳細については、リポジトリの 2 分割 を参照してください。

大規模ファイルを見つける方法

大規模ファイルとは、一般的にサードパーティ製のライブラリ(jar ファイル、dll ファイル)、アプリケーションのコンパイル済みバージョン、(画像ファイルのような)バイナリ形式のメディア資産などです。通常、Mercurial はファイルの差分を保存するので、注意が必要です。バイナリ ファイルの内容を少し変更すると、多くのファイル、または大半のファイルでバイト数が変わる可能性があります。バイナリ ファイルに変更をコミットすることにより、Mercurial が大規模なファイルの全体または大半を複数回保存する可能性があります。  

Linux 環境の場合

Linux 環境で大規模ファイルを検索するには、次のパイプ コマンドを使用します。

$ find . -type f \( ! -regex ".*/\..*" \) -print | xargs ls -l | sort -k5,5rn | head

このコマンドは非表示ファイルとディレクトリを無視します。たとえば、このコマンドは .hg ディレクトリ内のすべてを無視します。ls の出力をサイズ順で並び替えし、head コマンドを使用して、上位 10 個の大規模ファイルを返します。たとえば、現在の Bitbucket チュートリアル リポジトリには、次の大規模ファイルがあります。

-rwxr-xr-x 1 manthony staff 548107 Feb 12 11:18 ./yearone.html
-rw-r--r-- 1 manthony staff 205672 Feb 12 11:18 ./images/mahmoud-darwish.gif
-rw-r--r-- 1 manthony staff 155848 Feb 12 11:18 ./images/so_many_activities.jpg
-rw-r--r-- 1 manthony staff 149472 Feb 12 11:18 ./images/EleanorRoosevelt.png
-rw-r--r-- 1 manthony staff 122251 Feb 12 11:18 ./images/AmbroseBierce.gif
-rw-r--r-- 1 manthony staff 112894 Feb 12 11:18 ./javascripts/foundation.js
-rw-r--r-- 1 manthony staff 109986 Feb 12 11:18 ./images/Deep-Thought.png
-rw-r--r-- 1 manthony staff 88873 Feb 12 11:18 ./images/AlbertEinstein.png
-rw-r--r-- 1 manthony staff 88387 Feb 12 11:18 ./images/willferrell.png
-rw-r--r-- 1 manthony staff 87721 Feb 12 11:18 ./images/NeilTysonOriginsA-FullSize.jpg

Windows 環境の場合

Windows 環境では、PowerShell を使用することを推奨します。Windows 7 で PowerShell を開くには、次の操作を行います。

  1. スタート ボタンをクリックします。
  2. プログラムとファイルの検索フィールドで、PowerShell と入力します。
  3. Windows PowerShell オプションを選択します。
    PowerShell コマンド ウィンドウが開きます。 
  4. リポジトリのルートに変更します。
  5. コマンドプロンプトで次のように入力します。

    gi -Path .\* -Exclude .hg | gci -r -ea 0 | sort Length -desc | select -f 10

    このコマンドは、.hg(メタデータ)ディレクトリのファイルを除く、リポジトリのファイルすべてを一覧表示します。システムは次のような出力を一覧表示します。

        Directory: C:\Users\manthony\Documents\tutorials
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a---3/25/2013 10:00 AM548107 yearone.html
    
     Directory: C:\Users\manthony\Documents\tutorials\images
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a---3/25/2013 10:00 AM 205672 mahmoud-darwish.gif
    -a--- 3/25/2013 10:00 AM 155848 so_many_activities.jpg
    -a--- 3/25/2013 10:00 AM 149472 EleanorRoosevelt.png
    -a--- 3/25/2013 10:00 AM 122251 AmbroseBierce.gif
    
     Directory: C:\Users\manthony\Documents\tutorials\javascripts
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a--- 3/25/2013 10:00 AM 112894 foundation.js
    
    Directory: C:\Users\manthony\Documents\tutorials\images
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a--- 3/25/2013 10:00 AM 109986 Deep-Thought.png
    
    Directory: C:\Users\manthony\Documents\tutorials
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a---3/25/2013 10:00 AM91116 index.html
    
     Directory: C:\Users\manthony\Documents\tutorials\images
    
    Mode LastWriteTime Length Name
    ----------------------- ----
    -a---3/25/2013 10:00 AM 88873 AlbertEinstein.png
    -a---3/25/2013 10:00 AM 88387 willferrell.png

大規模ファイルの削除

大規模ファイルを削除するには、convert エクステンションと --filemap オプションを使用します。convert エクステンションはリポジトリをフィルタリングし、並列履歴を持つ新しいリポジトリを作成します。--filemap オプションでは、ファイル処理用のフィルターを指定する filemap ファイルを使用します。変換処理時、convert エクステンションは filemap を使用して、処理するチェンジセットを修正します。filemap を使用すれば、個別のファイルやディレクトリ全体を含めたり、名前を変更したり、除外したりできます。

たとえば、次に示すのは簡単な filemap 指示文のセットです。

# Comment
include path/to/file
exclude path/to/file
rename from/file to/file

convert エクステンションと --filemap オプションの詳細については、ConvertExtension --filemap ドキュメントを参照してください。

変換によってリポジトリのファイルを縮小する例

次のようなディレクトリ構造のリポジトリを考えてみましょう。

repo
│─ doc
│─ commons-collections-3.2.1-javadoc.jar
│─ commons-io-2.0.1-javadoc.jar
└─ commons-lang-2.6-javadoc.jar
│─ lib
│─ commons-collections-3.2.1.jar
│─ commons-io-2.0.1.jar
└─ commons-lang-2.6.jar
└─ src
│─ commons-collections-3.2.1-sources.jar
│─ commons-io-2.0.1-sources.jar
└─ commons-lang-2.6-sources.jar

commons-lang 以外のすべてのライブラリを削除し、commons-io 用を除くすべての Javadoc を保持するには、リポジトリ ルートに次の filemap.txt ファイルを作成します。

include "repo"
exclude "repo/lib"
include "repo/lib/commons-lang-2.6.jar"

# the following include is optional
include "repo/doc"
exclude "repo/doc/commons-io-2.0.1-javadoc.jar"

次に、構造を変換するには、コマンドラインで次のコマンドを発行します。

hg convert --filemap filemap.txt initialHgRepo hgRepoAfterConversion

initialHgRepo は変換するリポジトリで、hgRepoAfterConversion は新しいリポジトリです。変換後の hgRepoAfterConversion リポジトリの構造は次のとおりです。

repo
│─ doc
│─ commons-collections-3.2.1-javadoc.jar
└─ commons-lang-2.6-javadoc.jar
│─ lib
└─ commons-lang-2.6.jar
└─ src
│─ commons-collections-3.2.1-sources.jar
│─ commons-io-2.0.1-sources.jar
└─ commons-lang-2.6-sources.jar

これで hgRepoAfterConversion リポジトリをチェックできます。

ファイル削除によるリポジトリ サイズの維持

使わないファイルを削除するのは、リポジトリのサイズを縮小するいい方法です。ファイルを削除しても履歴から削除されませんが、リポジトリの現在のバージョンを縮小します。古いファイルを取得する必要がある場合、どのクローン​​にもそのファイルが残っています。削除するべきファイルとして、次の項目を検討します。

  • SQL ダンプ
  • 大規模なメディア資産
  • アプリケーションのコンパイル済みバージョン
  • サードパーティ製のライブラリと依存性(jar、dll、gem など)
  • 履歴内の完全に不要な大規模ファイル

バイナリ ファイルは常に削除候補となります。DVCS システムは、バイナリ ファイルを格納するのに適しているとは言えません。Drive、Dropbox、Carbonite などのファイル ホスティング サービスにファイルをホスティングすることを検討するとよいでしょう。

プロジェクト リポジトリへのリポジトリの分割

コード プロジェクトごとにリポジトリを分割することにより、リポジトリのサイズを縮小できます。これには、プロジェクト間の相互参照状況を理解しておく必要があります。たとえば、大規模リポジトリ内に相互参照がない 4 つのプロジェクトがある場合、これを 4 つの小規模なリポジトリに分割できます。  

リポジトリを分割する手順については、リポジトリの 2 分割 を参照してください。


Last modified on Jun 28, 2017

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

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

Not finding the help you need?

コミュニティへの質問

Powered by Confluence and Scroll Viewport.