Gitにおける大容量ファイルの未来はGitそのもの
(tylercipriani.com)- Gitプロジェクトは最近、公式に大容量ファイル管理の問題を直接解決し始めている
- Git LFSは、ユーザーにさまざまなコストやベンダーロックインなどをもたらす暫定策である
- 最近のpartial clone機能により、Git自体だけでLFSの役割の大半を代替できるようになった
- 今後はlarge object promisorという新しいソリューションも公式Gitへの統合が準備されている
- こうした変化により、大容量ファイル管理の究極的な解決策は外部拡張ではなくGitそのものへと収束していく見込みである
Gitの大容量ファイル問題と変化
- Git最大の宿敵(Nemesis)は、まさに大容量ファイルである
- 大容量ファイルはGitリポジトリを肥大化させ、
git cloneの速度を低下させ、ほとんどのホスティング環境にも悪影響を与える
Git LFSの登場と限界
- 2015年、GitHubはGit LFSをリリースし、大容量ファイル問題を回避した
- しかしGit LFS自体が、新たな複雑さとストレージコストを追加した
- Gitコミュニティは静かに大容量ファイルの根本問題を考え続けてきたが、最近のGit公式リリースでは、LFSなしで大容量ファイルを管理する新たな方向性が示されている
今すぐ使える方法: Git LFSをpartial cloneで置き換える
-
partial cloneの仕組み
- Git LFS: 大容量ファイルをリポジトリ外に置き、必要なファイルだけをダウンロードして作業する仕組み
- Git partial clone(2017年導入):
--filterオプションで、指定したサイズ以上のblobを除外して複製する- 必要になったときだけ、その大容量ファイルをサーバーから取得する
Partial cloneを使うと、CloneやFetchの途中で[大容量バイナリアセット]を事前にダウンロードする必要がなくなるため、ダウンロード時間とディスク使用量を削減できる
-
partial cloneとLFSの共通点
- 1. チェックアウト容量の最小化: 最新版だけを取得し、ファイル全体の履歴は省略する
- 2. 高速な複製: 大容量ファイルの転送がないため、cloneが速い
- 3. 高速なセットアップ: shallow cloneと違い、プロジェクト全体の履歴にアクセスできる
-
partial cloneの活用例
- 大容量PNGファイルの履歴が多いrepoでの、複製速度とディスク使用量の実例:
- 通常のcloneでは約4分、1.3GBの容量を使用
- partial cloneで100KBのblob制限を適用すると、6秒で複製でき、49MBを使用
- 元と比べて複製速度は97%改善、チェックアウトサイズは96%縮小
- 大容量PNGファイルの履歴が多いrepoでの、複製速度とディスク使用量の実例:
-
partial cloneの限界
- フィルタリングしたデータが必要になった場合(例:
git diff,git blame,git checkout)、Gitはサーバーにファイルを要求する - これはGit LFSと同じ特徴である
- 実務では、バイナリファイルに対してblameを行うことはまれである
- フィルタリングしたデータが必要になった場合(例:
Git LFSの問題点
- 強いベンダーロックイン: GitHubの実装は独自サーバーしかサポートせず、課金と依存関係を生む
- コストの問題: 50GB保存時、GitHub LFSは年間40ドル、Amazon S3は13ドル
- 元に戻しにくい: いったんLFSへ移行すると、履歴を書き換えない限り元に戻せない
- 継続的な設定コスト: すべての共同作業者にLFSのインストールが必須で、未導入だとファイルの代わりにメタデータファイルが見えてしまう(混乱の原因になる)
今後の展望: Large Object Promisor
- 大容量ファイルはホスティングプラットフォーム(GitHub、GitLab)にとってもコスト上の問題を引き起こす
- Git LFSは大容量ファイルをCDNへオフロードすることで、サーバーコストを削減している
-
Large Object Promisorとは
- 今年初め、Gitはlarge object promisorという機能を公式にマージした
- この機能はLFSに似た形でサーバー側のストレージ負荷を減らしつつ、ユーザー側の複雑さを大きく減らす
この取り組みは、サーバー側の作業、特にすでにバイナリ形式で圧縮されている大きなblobの処理を改善することを目的としている
Git LFSの代替となるソリューションである
– Large Object Promisors, git-scm.com
-
動作原理
- 1. ユーザーが大容量ファイルをGitホストへpushする
- 2. ホストがバックエンドのpromisorへ大容量ファイルのオフロードを行う
- 3. clone時にGitホストがクライアントへpromisor情報を提供する
- 4. クライアントは必要に応じて、そのpromisorから自動的に大容量ファイルを取得する
-
現在の導入状況と課題
- 大容量promisorはまだ開発中であり、2025年3月に一部コードがGitへマージされた
- GitLabなどで追加実装と未解決課題の議論が進んでいる
- 広く普及するまでにはまだ時間が必要である
- 当面は大容量ファイル保存でGit LFSへの依存は避けられない
- promisorが普及すれば、GitHubでも100MBを超えるファイルのアップロードが可能になる見込みである
結論: Gitの大容量ファイルの未来はGit
- Gitプロジェクトは、あなたに代わって大容量ファイル問題を絶えず考え続けている
- 現時点では、依然としてGit LFSの利用が必要である
- しかしpartial cloneとlarge object promisorsが進化するにつれて、Git LFSは徐々に不要になり、近い将来、大容量ファイルをGitだけで容易に管理できる時代が到来するだろう
- 将来は、GitにMP3ライブラリを入れようという発想だけが、大容量活用を妨げる最後の障害になるだろう
1件のコメント
Hacker Newsの意見
昔のsvnであれば、大容量バイナリファイルが多い150GBの作業ディレクトリでも特に問題なく動いていたが、gitはそうではない。なぜsvnが大容量バイナリファイルでgitと異なるアプローチを取っているのか、gitにも同じことができないのか気になる。さらに、バイナリデータを扱うときに本当に必要な機能はファイルロックで、特定のファイルは1人だけが作業し、他の人は読み取り専用であるべきで、そうしないと混乱を招くマージ問題を避けられない。大容量ファイルを外部にオフロードすることで実際に性能や安定性の問題が改善するのかもよく分からない。結局は保存先が違うだけで、リポジトリはリポジトリだ。オフロードは実質的にパブリックなgit forgeが大容量ファイル保存コストを回避しようとする方法に見える
Large object promisorという概念は気に入った。S3のようなものを簡単に接続して使えるなら、既存のLFSからすぐ移行すると思う。S3は大容量バイナリファイルをバージョン管理するときに相性が良い。インテリジェントティアリングで、データが古くなるほど自動的に安価なストレージティアへ移せる利点もある。10年前のデータを復元するのに半日かかっても構わない
私も同感だ。なぜ最初からこれがデフォルトでなかったのか分からない。小さなgit LFSサーバーを自前で動かしているが、gitがS3をネイティブサポートしてくれるならすぐにでも切り替える準備がある
今の職場ではLFSオブジェクトをコスト削減のためバケットにキャッシュしている。PR実行のたびに
git lfs ls-filesでファイル一覧を取得し、gcpから持ってきて、git lfs checkoutでローカルにオブジェクトを保存し、pullで不足分だけ追加取得する。キャッシュされていないファイルはgcloud storage rsyncで再びバケットへアップロードする。開発者側では追加設定なしで新しいオブジェクトだけpullすればよく、GitHub UIでもリポジトリの状態に混乱がない。以前はLFSバックエンドを自前で立てようかと思っていたが、この方法で当面の最大の問題は解決できている。GitHubはLFSファイルをCIで取得するたびに転送料金が高すぎたし、キャッシュの10GB制限とブランチ間で共有できない仕様のせいで毎回取り直さなければならなかった。キャッシュ容量を有料でも増やしたかったが、その方法もなかった。これを開発者に適用するのもgit hookを追加する程度で済むほど簡単だS3はAmazon関連のサービスなのか気になる
Git LFSのよくない点はいくつも挙げられているが、ベンダーロックインがあるという点には同意しない。GitHubがオープンなクライアントとサーバーを提供しているので、その主張は不当だ。ただし、LFSはオフラインやスニーカーネットでの作業では動作せず、これは一般的なケースではないにせよ言及する価値はある。large object promisorはLFSのクライアント側の複雑さをサーバー側へ移したように見えるが、結局は複雑さの所在が変わっただけにも思える。gitサーバーがLFSサーバーとオブジェクトストレージへファイルをアップロードする構成なら、別のトレードオフが生じる。パブリックなgitサーバーでpromisor remoteを隠したままアップロードするとどうなるのか気になる
LFSは本当にいまひとつだと思う。サーバー実装もひどいし、オブジェクトの内容と保存方法が混在している。opt-inのやり方もひどく、何も考えずに使うと本当に欲しいファイルではなく小さなテキストファイルしか得られない。新しい解決策がより良いかは分からないが、LFSが良くないのは確かだ
最近知ったGit LFSの別の問題は、マイグレーションが上位コミットの
.gitattributesまで汚染することだ。つまり、コミット A→B→C の順で、Cでのみ大容量ファイルをLFSとして追加した場合でも、AとBにも存在しないLFSファイルを指す.gitattributesが生じる。マイグレーションの過程で.gitattributesが履歴をさかのぼって伝播してしまうのは、現在のコミットにその実体が存在するかどうかを参照していないためだ以前はGit LFSがSSHをサポートしておらず、SSL証明書を必ず取得しなければならなかったため、自宅でセルフホスティングする人にとって参入障壁になっていた。GitLabは最近SSHサポートのパッチを当てたようだ
ソフトウェア工学の授業では、大容量ファイル(メディアなど)はGitに入れず、アーティファクトリポジトリ(Artifactoryなど)に置くよう勧められていた。そうすればスナップショット依存関係の形で配布でき、ビルドシステムが自動で最新バージョンだけを取得するよう制御できる。同僚たちのローカルに溜まった古いファイルも、ビルドシステムのキャッシュを消すだけですぐ整理できる
このやり方は一種のgitサブモジュールのようにも感じる。もしサブモジュールで問題が解決できるなら、みんなすでに使っていたはずだ。gitサブモジュールも浅いクローンをサポートしている(関連リンク: https://stackoverflow.com/questions/2144406/how-to-make-shallow-git-submodules)。自分は大容量ファイルの問題に遭遇したことがないので、もしこの方法ではだめな理由があるなら知りたい。SOに書かれている欠点はそれほど大きくは見えない
授業でCI/CDシステムのアーキテクチャも教えているのか気になる。最近の新人エンジニアはGitLab、Artifactory、CodeSonar、Anchoreなどと連携する全体構成にあまり慣れていない
この方法にも欠点はある。CI/CDシステムや開発者に追加の認証情報が必要になる。コミットも複数段階に増え、まずアーティファクトIDを知る必要があり、これを自動化しようとしてgit hookを使い始めると結局git-lfsのように複雑になる
この記事はLFSを不当に評価している。LFSはGitHubに依存しておらず、プロトコルもオープンだ。LFSの欠点はgit拡張である以上やむを得ない部分で、promisorsも実質的にはLFSと同じ概念だ。ただ、git内部に組み込まれたことでUXが少し良くなっただけだ
これは本当の解決策ではない。git LFSもその場しのぎにすぎず、クローン時にフィルタ引数を付けるとしても根本解決ではない。git cloneはすべての利用者が最初に学ぶコマンドなのに、そのたびにフィルタを覚えていなければならず、ミスすると時間がかかるだけで、うまくいってもクローンしたリポジトリが正しく動かないことがある。結局はrsyncのように最新ファイルから効率的に取得する構造へ移行しないと根本的には解決しない。gitはこうした根本的な変更をあまりしない
強く同意する。gitはいつもフラグを1つ追加する形で問題を「解決」するが、ほとんどの利用者はその機能を知らない。デフォルト自体を改善すれば、互換性を壊さずに問題を解けるはずだ
リポジトリ容量の大半が過去リビジョンにあるなら、rsyncのように最新バージョンだけをまず受け取る方式が大半の利用者にとって最適な解決策だ
Gitコアに大容量ファイル対応が追加されるのはとてもうれしい。外部ソリューションであっても結局opt-in構造は同じだ。できるだけコマンドを減らしてシームレスにしたかったので、
.gitattributesファイルのsmudge/cleanフィルタにだけ限定してAPIを設計した。また、AtlassianやMicrosoftと直接協力してベンダーロックインをなくそうとし、ファイルロッキングAPIでもAtlassianから多くの支援を受けた。LFSは3つのホストで互換性のあるオープンソースとして提供されている私たちはgitやgit-lfsで経験した問題を解決するために
oxenを開発している。gitのインターフェースをそのまま踏襲しつつ、大容量ファイルや数百万ファイルを含むモノレポ環境でずっと高速に動作する。オープンソースのCLIとサーバーを提供しているので、興味があればフィードバックがほしいhttps://github.com/Oxen-AI/Oxen
gitの保存方式そのものも、resticやborgのような現代的なバックアップツールのように、ファイルやディレクトリをコンテンツ定義チャンク分割(content-defined chunking)で扱う形へ全面的に見直す必要がある
GitLFSの欠点として認証の問題も抜けている。SSH-agentを使わないと、1回pushするだけでも認証を何度も通さなければならない。自分の経験では2、3回以上求められたこともある