「Code for 青空文庫」アイデアソン #1に参加していました。参加してました、と言えるほど何も貢献してないんですけど。すみません。。
青空文庫については、こんなツイートがありました。たしかに青空文庫のGithubレポジトリはあって開催まで時間もあったわけで、 アイデアソンとはいえ「実際こんなのつくってみたよ!」みたいなのがもっとあってもよかった気がします。
青空文庫の一件、伽藍とバザール問題を地で行ってるというか、手を動かさないやつの意見は無駄なんですよというか
— Kazuho Oku (@kazuho) 2015, 5月 15
で、「手を動かす」のを妨げてるのは何かというと、ひとつはレポジトリのサイズが気軽にcloneできる大きさじゃない、ということがあると思います。個人的にはcloneしようとしてなかなか終わらなくて挫けました。完全に言い訳ですけど。
githubのaozorabunko/aozorabunko、du -k の結果は 7942612 です #aozorahack
— masayoshi takahashi (@takahashim) 2015, 5月 30
一念発起、実際git clone
してみて調べると、7.7GBありました。カタギの人間にはつらい重さです。
$ du -sh . 7.7G .
その理由は、↓こういう重めの画像ファイルを含むZIPファイルがレポジトリに入っているせいではないか、という話をちらっと聞いたので、その辺をレポジトリから削除するとどれくらい軽くなるか試してみました。
合計サイズ
そこまで大したサイズではなさそうです。うーん。
$ find . -name '*.zip' -exec stat --format=%s {} \; | awk '{sum+=$1}; END {print sum/1024/1024 "MB"}' 616.882MB
git filter-branch --index-filter
パスワードを含むファイルとか、やばいファイルをレポジトリに入れてしまったときは、過去のコミットからも消さないといけません。Gitにはそのためのコマンドが用意されています。これを使ってみます。
ただ、よく分かりませんがこのコマンドはたくさんのファイルを消す時には不向きのようです。
$ git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch $(find . -name '*.zip')" \ --prune-empty --tag-name-filter cat -- --all -bash: /usr/bin/git: Argument list too long
いくつかに絞ってみても、よく分からないエラーが出ます。ひとつのファイルしか指定できないみたいです。
$ git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch $(find . -name '*.zip' | head -3)" \ --prune-empty --tag-name-filter cat -- --all Rewrite 371bcfa53617dade8aa892cc0f23d724a7bd029e (1/1489)rm 'cards/001339/files/48380_txt_31990.zip' /usr/lib/git-core/git-filter-branch: 2: eval: ./cards/001339/files/48381_txt_31991.zip: not found /usr/lib/git-core/git-filter-branch: 3: eval: ./cards/001595/files/53683_txt_44483.zip: not found index filter failed: git rm --cached --ignore-unmatch ./cards/001339/files/48380_txt_31990.zip ./cards/001339/files/48381_txt_31991.zip ./cards/001595/files/53683_txt_44483.zip
こんな感じでforで回すことはできますが、いかんせん時間かかりすぎて断念しました。たぶん丸2日くらいかかる予感。
$ for z in $(find . -name '*.zip'); do git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch ${z}" \ --prune-empty --tag-name-filter cat -- --all done
BFG Repo-Cleaner
上のGithubの記事でも紹介されてましたが、git filter-branch
をもう少し楽にしたBFGというのがあるらしいです。
これを使ってみます。
今回は消すファイルは拡張子で判別できるので、--delete-files '*.zip'
を指定します。あと、安全のため最新のコミットは残すというのがデフォルトの挙動になっていますが、それも含めて消してほしいので--no-blob-protection
オプションをつけます(ドキュメントにあるみたいに、git clone --mirror
でクローンしてきた場合は不要だと思います)。git gc
はけっこう時間かかります。
$ java -jar bfg-1.12.3.jar --no-blob-protection --delete-files '*.zip' ...snip... $ git reflog expire --expire=now --all && git gc --prune=now --aggressive
で、これで消えたかと思いきや、stageされた差分として残っています。
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: cards/XXX/XXX.zip ...snip...
git reset HEAD
してstageを取り消し、実際のファイルも消します。あと、.gitignore
にも入れます。
$ git reset HEAD $ find . -name '*.zip' -delete $ echo '*.zip' >> .gitignore $ git add .gitignore $ git commit -m 'ignore ZIP files'
さあ、これでどれくらい減ったかというと…
$ du -sh . 2.3G .
うーん、1/3くらいにはなりましたが、まだ気軽にcloneできるサイズではなさそうです。
.pngとか.ebkとか色々消してみる
ここからさらに画像とかを消すと、1.1GBくらいにはなりましたが、それ以上は減らなそうでした。
上のレポジトリには反映していません。
git filter-branch --subdirectory-filter
git filter-branch
には、サブディレクトリをレポジトリとして切り出すコマンドがあります。これを使ってcards/
だけ切り出すとどうなるかやってみます。
$ git filter-branch --subdirectory-filter cards HEAD Rewrite 877a7e4624ea02e890219b7210b1dc8aae851c5f (1490/1490) Ref 'refs/heads/master' was rewritten
このディレクトリに関連するコミットだけが切り出されているので、さっき追加した.gitignore
は消えています。また作る必要があります。
これでどれくらいのサイズになるかというと…
$ du -sh . 962M .
まだ1GB程度はあります。あんまり変わってませんでした。
注:↓のレポジトリはディレクトリ数が多いので開くとブラウザが重くなります。 github.com
感想
人間が読むために人間が書くテキストファイルなんてそんな重くならないだろう、と勝手に思ってたんですが、たとえばこの作品とか、2MBあります。
ということで、これ以上は軽くならなそう。
青空文庫の歴史の重みを感じました。軽く見てすみませんでした。。