Git LFS (Git Large File Storage) とは、Git で大きいサイズのバイナリファイル(本稿では、ラージファイルと省略して呼びます)をバージョン管理するための仕組みです。
Git はその性質から、ラージファイルを扱うにはいくつかの問題をはらんでいて、Git LFS はその問題を解決するための機能を Git の拡張として提供するものです。
本稿では Git LFS の概要紹介として、どういった問題が存在していて、どのように解決されるか、一方でどういった問題が解決されないかまでを、まとめて紹介します。
Git のラージファイル管理における問題点
まず Git LFS の背景として、ラージファイル管理における問題点を、Git の特徴を抑えつつ紹介します。
バイナリファイルの管理に不向き
Git は、ソースコード(テキストファイル)のバージョン管理に特化したツールです。
多くのプロダクトと同様に、バージョン間の差分算出を前提として機能が提供されています。
変更のマージはファイル間の差分を元に行いますし、リポジトリの最適化には差分圧縮が用いられます。
一方、バイナリファイルはフォーマットに乏しい点で差分算出が難しく、変更のマージやリポジトリの最適化が機能しません。
結果的に、開発メンバー間での変更の衝突や、リポジトリの肥大化といった問題の発生が想定されます。
各ローカルマシン上でリポジトリを管理する
バージョン管理システムは、リポジトリの扱いから集中管理と分散管理の二つに分類されます。
Git は分散管理に分類されるプロダクトで、リポジトリのコピーを各ローカルマシン上で持つことになります。
これによってローカルマシン上でのコミットが可能になるなど、集中管理システムと比べて、開発効率の向上がもたらされるものとされています。
一方で、分散管理システムにはデメリットもあります。
- リポジトリ管理が複雑
- ローカルマシンのストレージ負担
1つ目のデメリットは、Git がとっつきにくいものと捉えられる原因として、広く知られているものであるはずです。
2つ目のデメリットですが、これは多くのプロジェクトでリポジトリサイズというのは無視できる程度になっているはずで、あまり意識されていませんが、前述のようにラージファイルを管理対象とする場合にはリポジトリの肥大化が懸念され、無視できない問題となります。
ちなみに、リポジトリのコピーというのは、単に最新バージョンの全てのファイルのコピーを持つだけでなく、過去の全てのバージョンのコピーを持つということを意味していて、ラージファイルの変更が繰り返された場合には、単純計算で変更回数の系数倍サイズのデータを各ローカルマシンが抱えることになります。
Git LFS の特徴
Git LFS は、サーバサイドおよびクライアントサイドにおいて Git の拡張として実装される仕組みですが、大きく 2つの機能を実現することで、ラージファイル起因の問題の解決に取り組みます。
また、それとは別に Git LFS に付随するメリットとして2つを紹介します。
LFS サーバによるの集中管理
1つ目は、ラージファイルの "実体" を LFS サーバと呼ばれる中央サーバで集中管理する機能です。
リポジトリ上では実体の代わりに、ラージファイルの "ポインタ" を管理します。
ポインタは、LFS サーバに実体を問い合わせるための情報を格納した、数百バイトのテキストファイルです。
さらに、ローカルマシンにおいて、ラージファイルの実体は最新バージョンのもののみを持ちます。
バージョンの更新があった場合には、LFS サーバへアクセスして実体を適宜入れ替えます。
これによって、ローカルマシンのストレージ負担が大きく軽減されます。
ロックのサポート
2つ目は、編集ロック機能です。
これは、開発メンバー間での同時変更による衝突を防ぐためのもので、普段はロック状態が維持されていて、編集が必要になった時に各メンバーが適宜編集権をリクエストするような作業フローになります。
ロックは中央サーバで管理され、同時に二人以上のメンバーに編集権を渡すことはありません。
Git の透過的な拡張として実装されている
これまでラージファイルをバージョン管理するには、別のバージョン管理システムを併用する必要がありました。
Git LFS は Git の拡張として透過的に実装されていて、これによって既存のワークフロー(レビュー、自動デプロイ、アクセス権限の付与など)を変えることなく、多くのプロジェクトに適用することが可能です。
さらに、リソース管理が Git に統一されることで、作業面での煩わしさも解消されます。
ちなみに、Git LFS はラージファイルの並列転送にも対応していて、リポジトリのクローンや複数ファイルのコミットにおいてパフォーマンスを発揮します。
ホスティングサービスによるサポート
Git LFS は、すでに多くのホスティングサービス(GitHub, GitLab, BitBucket など)でサポートされています。
LFS 用のストレージ空間が用意されていて、通常のストレージ空間よりもサイズ制限が緩くなっています。
サービス名 | サポート状況 |
---|---|
GitHub | 2015年4月よりサポートを開始。2GB まで利用可。(参考) |
GitLab | 2015年11月よりサポートを開始。(参考) |
BitBucket | 2016年7月よりベータ公開。(参考) |
Git LFS に残る課題
このように、ラージファイルのバージョン管理に大いに活躍する Git LFS ですが、一部解決できない問題や Git LFS それ自体の不便というのも存在します。
プロジェクトへの採用には、これらの問題が許容可能かどうかを検証してください。
LFS サーバへのストレージ負担
Git LFS によって、ローカルリポジトリの肥大化は回避することが出来ますが、LFS サーバへの負担は免れません。
LFS サーバ上では、過去の全バージョンのラージファイルの実体が、差分圧縮されることなく管理されるためです。
多くのラージファイルを扱うプロジェクト(ゲーム開発など)では、ホスティングサービスの用意するキャパシティでは心もとないでしょうから、ストレージ空間に余裕のあるホストを別途用意する必要があります。
開発フローが LFS サーバに依存する
Git はリポジトリの分散管理によって、各ローカルマシン上で作業を完結できることが特徴の一つですが、ラージファイルの管理が LFS サーバに依存することで、このメリットが失われることになります。
例えば、ラージファイルの実体がローカルマシン上に存在することが保証されるのは最新バージョンのコピーのみなので、これまで checkout したことがないような過去の commit を checkout したくなった場合には、そのバージョンのラージファイルの実体を取得する必要があるため、LFS サーバにアクセス可能な環境にあることが条件となります。
環境依存の問題が発生する
Git LFS は、これまでも触れているように、Git の拡張として透過的に提供されますが、これは嬉しいことばかりでもありません。
使い勝手としては、同様に Git の拡張として提供される、Git Submodule を思い浮かべるとわかりやすいかも知れません。
例えば、Git LFS を利用しているリポジトリは、一見すると普通の Git リポジトリと同じに見えます。
誤って Git LFS 非インストール環境下でリポジトリが clone され、ラージファイルの追加が push された場合、ポインタ管理が機能せずに実体がそのままリポジトリ管理されてしまいます。
さらに、Git LFS インストール環境からは、ポインタとして見えるはずのラージファイルが実体として見えることで不整合が発生してしまい、ニッチもサッチもいかない状況になります。
まとめ
- Git LFS はラージファイルの集中管理とロックをサポートすることで、リポジトリの肥大化や変更の衝突を回避します。
- 既存のワークフローを変えることなく、プロジェクトに適用できます。
- 開発環境の制限や環境依存で発生する問題など、一部デメリットも存在します。