Git
git-lfs
GitLFS

GitLFSのLFSオブジェクトを圧縮する

課題

  • GitLFSは非常に便利ですがLFSオブジェクト(.git/lfs/objects以下にあるファイル)は非圧縮で管理されるためディスク容量がもったいない。
  • リモートリポジトリへpushするときもそのまま非圧縮で転送されるため通信帯域がもったいない。
  • 圧縮したい!

解決策

やってみる

検証環境はサーバーが GitBucket-4.13.0 でクライアントが Windows8.1 / Cygwin(xzだけ) / Git for Windows で詳細なバージョンはこんな感じ

$ git version
git version 2.14.2.windows.3

$ git lfs version
git-lfs/2.3.2 (GitHub; windows amd64; go 1.8.3; git 81153cc0)

(Git for Windows は GitLFS を同梱しているので導入が楽ですね)

$ ls -gh hoge.dat
-rw-r--r-- 1 なし 42M 2月   6 01:59 hoge.dat

$ git config lfs.extension.compress.clean "xz -z"
$ git config lfs.extension.compress.smudge "xz -d"
$ git lfs track hoge.dat
$ git add -vA
add '.gitattributes'
add 'hoge.dat'

$ find .git/lfs/objects/ -type f | xargs ls -gh
-rw-r--r-- 1 なし 5.4M 2月  11 18:15 .git/lfs/objects/7c/e4/7ce459e1bfaac3371800decd182254712e20393e2426f8c8e85092d84dbc9d55
  • 42MBあったファイルが5.4MBのLFSオブジェクトに!!(デフォルトでは42MBのまま管理される)
  • push時にもこのファイルがそのまま転送されるので通信帯域にもやさしい。
  • 素晴らしいことにこの拡張設定はポインタファイルに明記されるため、すでに運用しているLFSリポジトリに途中から導入できる。

まとめ

  • xzだと圧縮率は高いがそれなりに時間がかかってしまうのでzstdなど軽めの圧縮コマンドを使うなど用途に応じて調整するのがおすすめ。
  • GitLFS拡張は複数設定できるものの拡張子で拡張設定を選択することはできないようなので、 %f でファイル名を引数に受け取って分岐する独自コマンドを作るのが良いかも。
  • この拡張の設定はリモートリポジトリには保存されないのでGitHubのようなWebフロントエンドからは圧縮ファイルしか閲覧できない。
  • 同じ理由でclone後に毎回この設定を行う必要があり、そのままだとLFSの展開に失敗してしまう。対策としてclone時にcheckoutされるデフォルトブランチを環境設定用ブランチにしておいて、LFS設定&masterチェックアウトするスクリプトだけ配置しておくというのが現実的かもしれません。