[Git] git repository size を削減する
「This repository’s size is over 1 GB.」と Bitbucket に注意されました。
limit があるので 1GB を越えたところで警告するよ、ということのようです。
限定的ではありますが、対応してみました。
今後のために作業手順をメモしておきます。
Contents
状況
どれくらいの容量を使っているのかを調べる方法ですが、こちらに紹介されているので確認してみます。
size-pack がでかいのが問題のようです。
% git count-objects -v
count: 264
size: 43288
in-pack: 1394
packs: 1
size-pack: 998103
prune-packable: 0
garbage: 0
size-garbage: 0
git gc
コマンドがあったよねと言うことで、試してみます。
% git gc
Counting objects: 1612, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (757/757), done.
Writing objects: 100% (1612/1612), done.
Total 1612 (delta 915), reused 1344 (delta 812)
Removing duplicate objects: 100% (256/256), done.
確認すると size は減りましたが、size-pack は増えました。
過去にコミットした大きなサイズのファイルが問題のような気がします。。。
% git count-objects -v
count: 5
size: 3768
in-pack: 1612
packs: 1
size-pack: 1005953
prune-packable: 0
garbage: 0
size-garbage: 0
過去の悪行を確認したい場合は、こちらで確認できます。。。
% git log --stat
このあたりを手がかりに何とかしてみます。
対象ファイルを洗い出す
サイズの大きいファイルを見つけるシェルスクリプトがあるよ、ということなので使わせて頂きます。
% mv ~/Downloads/git_find_big.sh ./
% chmod 777 git_find_big.sh
.git/objects が大きくなってしまっているのか。
% du -hs .git/objects
986M .git/objects
シェルスクリプトを実行します。
思い当たるものばかり。
% ./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
351154 246494 2762739302d105a120661d098d5ea5ee42efde2b docs/psd/top.psd
328248 230949 26d7415a0e59bd252b1fbabce5ecd7e99c34cecc docs/psd/**.psd
167204 115206 224299c2ef8aa09c6ad31784c43f74137cd871be docs/psd/**.psd
164963 115923 a03394edaf3275362037878134d06cd4bae67e04 docs/psd/**.psd
163689 110466 ddb957fa00c95d62fd17de1597238b9924817e5c docs/psd/**.psd
85331 59402 4b48de6fcac3403ef59bafffa10ed2e7f7a90659 docs/psd/menu.psd
60383 40604 ca55a6873447ef856294b825e8b1e7111262df32 docs/psd/**.psd
57028 37763 172d017b83ae5cc01783c2e346670de5463f07ac docs/psd/**.psd
11501 11482 244e361c9b78f13e02a15dc69d4060deef6ed75b archive.zip
5004 4992 9c59e15d9218bc3d49891cd61d7fe3f831cc9737 archive.zip
.psd ファイルを削除したいですね。
準備と問題点
.git/objects からファイルを削除するには前回の手順だけでは足りず、git filter-branch
で歴史を書き換える必要があります。
準備
次節以降の手順で進めましたが、git の知識不足で何度もやり直しが発生しました。
望むような結果を得るために try & error したところ、事前に以下の整理を行う必要がありました。
- branch は merge して master にまとめる。
- tag は一度消して、後で付け直す。
- 別途、
git clone
して作業する。
問題点
以下、理解できていない点。
- branch や tag で分岐する前のコミットに削除したいファイルが含まれている場合、別の場所にも残っていると思われるファイルは後述手順だけでは解決できません。
- チェックサムが変わってしまうので、共同作業とかでは影響が大きそう。
push -f
してもリモートリポジトリが書き換わらないので、削除して作り直しました。- 今回は未使用で確認できなかったのですが issue がどうなるのか。
作業手順
branch や tag を整理し、リモートへ push しておきます。
リモートからこのリポジトリを git clone
で作業用リポジトリとして別途ローカルに落とします。
% git checkout master
% git gc --auto
大きなサイズのファイルを削除する
ここから「Remove large files Option 1: Delete files by name」を進めます。
% git filter-branch --index-filter 'git rm --cached --ignore-unmatch docs/psd/top.psd' HEAD
Rewrite f51f68b5f659046462d129c1934f17bc4db6ed30 (114/131)rm 'docs/psd/top.psd'
Rewrite 679f364ba5efc3f2da38cd0bfef5f2f66f47711a (115/131)rm 'docs/psd/top.psd'
Rewrite 7cc5632a4e8104d16070100b89cc05912cc0e066 (116/131)rm 'docs/psd/top.psd'
Rewrite 6fbe99c42c0aaf4eb78770d4168bda610e73d3aa (117/131)rm 'docs/psd/top.psd'
Rewrite dff043ddd6660f8837cabfdd858f61e49938064d (131/131)
Ref 'refs/heads/master' was rewritten
これを対象ファイル毎に繰り返します。
下記のエラーが出る場合は、上記のコマンドに -f
オプションを付けます。
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
下記を実行します。
(パイプの左側の部分で何もリストアップされないようで、結果、何も実行されていないような記憶があるのですが、試行錯誤の最中、きちんとログがとれていませんでした。)
% git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
さらに reflog を消します。
% git reflog expire --expire=now --all
git gc
を実行します。
(実際の作業では、この段階で削減できず、リモートとローカルのブランチとタグを削除してから再実行しています。)
% git gc --prune=now
Counting objects: 1572, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (661/661), done.
Writing objects: 100% (1572/1572), done.
Total 1572 (delta 870), reused 1552 (delta 868)
サイズが削減できたことを確認できました。
% du -hs .git/objects
46M .git/objects
リモートリポジトリを作成し直す
続けて以下を実行しましたが、リモートのリポジトリ容量は変わりませんでした。
% git push --all --force
ブラウザからリポジトリを削除し、新しく作成したローカルリポジトリを push し直します。
% git push -u origin --all
% git push -u origin --tags
元のリポジトリをリモートリポジトリの内容へ変更する
あとはリモートの origin/master と差分がないことを確認しつつ、元のローカルリポジトリへ fetch -> diff -> merge します。
マージ後、元のリポジトリのサイズを確認するとまだ大きいままです。
% du -hs .git/objects
1008M .git/objects
reflog の掃除をして、git gc
を実行します。
% git reflog expire --expire=now --all
% git gc --prune=now
% du -hs .git/objects
54M .git/objects
最後に git clone した作業用リポジトリを削除して終了しました。