GitLFSは遅いというイメージを払拭したい

  • 32
    いいね
  • 0
    コメント

これまで GitLFS は遅いだとか大量のファイル管理に向いていないという印象を持っていました。
ですが、まあ大きいバイナリを扱うし遅いのは遅いんですが、やり方によっては現時点でもギリギリ実務に耐えれる程度だと今では思っています。

というわけで、遅さをなんとかする方法をいくつか(少ないですが)書いてみたいと思います。

GitLFSのファイル管理

その前に、GitLFS のファイル管理イメージを持っておくと、そのあとの理解がしやすいのでそこから説明します。

GitLFS は Git の smudge/clean filter の機能を使っています。

git checkout の際に GitLFS のトラッキング対象としているファイルが含まれていれば、smudge filter を介して GitLFS のストア先から実際のコンテンツを取得し、ポインタファイルをそのコンテンツに置き換えます。

ポインタファイル例
version https://git-lfs.github.com/spec/v1
oid sha256:4665a5ea423c2713d436b5ee50593a9640e0018c1550b5a0002f74190d6caea8
size 36

次に、git add の際に GitLFS のトラッキング対象としているファイルが含まれていれば、clean filter を介して GitLFS のストア先にある実際のコンテンツを更新し、そのコンテンツから算出したポインタファイルに置き換えます。

これにより、Git 上はポインタファイルだけが管理され、ローカルにはコンテンツそのものがあるという形を実現しています。

なるべく最新のバージョンにする

できるだけ GitLFS のクライアントを最新のバージョンにしましょう。これはとても重要です。

1.0.0 だと push した時に壊れてしまうことがかなりの頻度で発生していたのですが(なぜか Object not found on the server. になったりする)、現時点で最新の 1.4.1 にしたらかなり安定しました。
1.3.0 でレジュームアップロード/ダウンロードができるようになったためかもしれません。

後述の git lfs clone も 1.2.0 で実装された機能です。

git cloneは使わない

clone する際は git clone を使わずに、git lfs clone を使うようにしましょう。

git lfs clone git@github.com:shibukk/lfs-pull-test.git

普通に git clone した場合、smudge filter が一度に1つのファイルだけしか扱えないため、GitLFS のストアに対し大量のAPIコールが発生してしまいます。
git lfs clone はこれを解決するために用意されたコマンドで、smudge filter に依存しません。
なので、複数ファイルを並行ダウンロードすることができ、結果高速に clone できます。

smudgeはskipする

git lfs 上にあるコンテンツが何らかの理由で破損している場合、git pull がエラーになってしまいます。
これでは困るので、壊れててもいいからポインタファイルだけを取得するようにしておきます。

git config filter.lfs.smudge "git-lfs smudge --skip %f"
# --globalオプションをつければ全てのリポジトリに対して設定される

このコマンドを実行しておくと smudge が skip されるようになります。

smudge によるコンテンツ置き換えが実行されないので、ローカルはポインタファイルのままですが、git lfs pull を実行すればコンテンツに置き換えてくれます。
これは同時に高速化も果たします。(clone と同様の理由です)

一点気をつけないといけないのが、こんな感じで手動でコマンドを実行しないといけないので、手順から抜けてしまう可能性があります。

# git pullする場合
git pull
git lfs pull

# git checkoutする場合
git checkout
git lfs pull # git lfs fetch; git lfs checkout; とほぼ等価

なので、githooks の post-mergepost-checkoutgit lfs pull を仕込んでおくか、一連のコマンドをまとめたエイリアスを作っておくとよいです。

最後に

これらの Tips は今後変わる可能性があります。
というのも、GitLFS は stream 読み込みなど意欲的な Pull Request が出されているからです。

WIP: long running clean/smudge filter protocol

もっと早くなれば個人的にすごく嬉しいので、引き続き GitLFS の動向は追ってきたいと思います。

2017.02.09 追記

stream 読み込みの Pull Request が取り込まれて checkout はとても早くなっています。
こんな感じで GitLFS はどんどんよくなっていっています。
ここに記載している Tips はもう必要なくなっていたりしますが、今後も楽しみです!