The future of large files in Git is Git

Tyler Cipriani

Gitにおける巨大ファイルの未来はGitだ

原文は Tyler Cipriani により に公開されました。 このブログを購読する

Gitに天敵がいるとすれば、それは巨大なファイルだ。

巨大なファイルはGitのストレージを肥大化させ、git cloneを遅くし、Gitホスティングサービスに混乱をもたらす。

2015年、GitHubはGit LFSをリリースした。巨大ファイルの問題を力技で回避するGitの拡張機能だ。だがGit LFSは、新たな複雑さとストレージコストをもたらした。

一方で、Gitプロジェクトは水面下で巨大ファイルへの対応を進めてきた。そしてLFSはまだ現役ではあるものの、最新のGitのリリースは、LFSがついに不要になる未来への道筋を示している。

今すぐできること:Git LFSをGitのpartial cloneに置き換える

Git LFSは、巨大なファイルをリポジトリの外に保存することで機能する。

LFS経由でプロジェクトをクローンすると、リポジトリの履歴と小さなファイルは手に入るが、巨大なファイルはスキップされる。代わりにGit LFSは、作業コピーに必要な巨大なファイルだけをダウンロードする。

2017年、GitプロジェクトはGit LFSと同じ利点を提供するpartial cloneを導入した。

partial cloneにより、クローンやフェッチの際に[大きなバイナリアセット]を事前にダウンロードするのを避け、ダウンロード時間とディスク使用量を削減できる。

– Partial Clone Design Notes、git-scm.com

Gitのpartial cloneもLFSも、以下の点を実現する。

  1. 小さなチェックアウト – クローン時には、巨大なファイルのすべてのコピーではなく、最新のコピーだけを取得する。
  2. 高速なクローン – 巨大なファイルのダウンロードを避けるため、クローンは高速だ。
  3. 素早いセットアップ – shallow cloneとは異なり、プロジェクトの全履歴を取得できるため、すぐに作業を開始できる。

partial cloneとは?

Gitのpartial cloneとは、--filterを付けたクローンのことだ。

たとえば、100KBより大きなファイルのダウンロードを避けたい場合は、次のようにする。

git clone --filter='blobs:size=100k' <repo>

その後、チェックアウトに必要な100KBを超えるファイルは、Gitが必要に応じて遅延ダウンロードする。

デフォルトでは、厄介な25MBのPNGファイルが何度も改訂されたリポジトリをgit cloneすると、クローンは遅く、チェックアウトは目障りなほど肥大化する。

$ time git clone https://github.com/thcipriani/noise-over-git
Cloning into '/tmp/noise-over-git'...
...
Receiving objects: 100% (153/153), 1.19 GiB

real    3m49.052s

たった25MBのファイル1つをチェックアウトするのに、ほぼ4分もかかる!

$ du --max-depth=0 --human-readable noise-over-git/.
1.3G    noise-over-git/.
$ ^ 🤬

そして、そのたった1つの25MBファイルの50リビジョンで、1.3GBもの容量を食う。

だがpartial cloneなら、こうした問題を回避できる。

$ git config --global alias.pclone 'clone --filter=blob:limit=100k'
$ time git pclone https://github.com/thcipriani/noise-over-git
Cloning into '/tmp/noise-over-git'...
...
Receiving objects: 100% (1/1), 24.03 MiB

real    0m6.132s
$ du --max-depth=0 --human-readable noise-over-git/.
49M     noise-over-git/
$ ^ 😻 (the same size as a git lfs checkout)

フィルタのおかげでクローンは97%高速化し(3分49秒→6秒)、チェックアウトサイズは96%削減された(1.3GB→49M)!

ただし、いくつか注意点もある。

フィルタで除外したデータを必要とするコマンドを実行すると、Gitはそれを取得するためにサーバーに問い合わせる必要がある。そのため、git diffgit blamegit checkoutといったコマンドは、実行時にGitホスティングサービスへのアクセスが必要になる。

だが、巨大なファイルに関しては、これはGit LFSと同じ挙動だ。

そもそも、PNGにgit blameをかけた記憶なんてないし🙃。

なぜわざわざ手間をかけるのか? Git LFSの何が問題なのか?

Git LFSは、Gitが抱える巨大ファイルの問題をユーザーに押し付けている。

そしてその問題は深刻だ。

  • 🖕 強力なベンダーロックイン – GitHubがGit LFSを作った当時、他の巨大ファイル用システムであるGit FatやGit Annex、Git Mediaはサーバー側に依存しなかった。だがGitHubはユーザーを自社のプロプライエタリなサーバー実装に縛り付け、その利用に課金した。1
  • 💸 高コスト – GitHubはリポジトリを無料でホストできることで勝利した。だがGit LFSは当初有料プロダクトとして始まった。現在は無料枠もあるが、価格設定はGitHubの気まぐれに左右される。今日、GitHubで50GBのリポジトリをホストするとストレージに年40ドルかかる。一方、Amazon S3の標準ストレージで50GBを保存するコストは年13ドルだ。
  • 😰 元に戻すのが困難 – いったんGit LFSに移行すると、履歴を書き換えずに元に戻すことは不可能だ。
  • 🌀 継続的なセットアップコスト – 共同作業者全員がGit LFSをインストールする必要がある。Git LFSがインストールされていないと、共同作業者は期待する巨大なファイルの代わりに、メタデータだらけの不可解なテキストファイルを手にすることになる。

未来:Gitのlarge object promisor

巨大なファイルは、Gitホスティングサービス側にも問題を引き起こす。

GitHubやGitLabは、大きなファイルほどホストコストがかさむため、ファイルサイズに制限を設けている2。Git LFSは、巨大なファイルをCDNにオフロードすることでサーバー側のコストを抑えている。

だがGitプロジェクトには新たな解決策がある。

今年の初め、Gitは新機能であるlarge object promisorをマージした。large object promisorは、ユーザー側の手間を省きつつ、LFSと同じサーバー側の利点を提供することを目指している。

この取り組みは特にサーバー側の改善を目的としており、とりわけすでにバイナリ形式で圧縮された大きなblobを対象としている。

この取り組みはGit LFSの代替を提供することを目的としている。

– Large Object Promisors、git-scm.com

large object promisorとは?

large object promisorとは、巨大なファイルだけを格納する特別なGitリモートのことだ。

明るく輝かしい未来では、large object promisorは次のように動作する。

  1. あなたは巨大なファイルをGitホスティングサービスにプッシュする。
  2. バックグラウンドで、Gitホスティングサービスはその巨大なファイルをlarge object promisorにオフロードする。
  3. クローンする際、GitホスティングサービスはGitクライアントにpromisorの存在を伝える。
  4. クライアントはGitホスティングサービスからクローンし、巨大なファイルは自動的にpromisorリモートから取得する。

だが、その明るく輝かしい未来には、まだ距離がある。

Gitのlarge object promisorはまだ開発途上だ。その一部は2025年3月にGitへマージされた。だが、やるべきことはまだ残っており未解決の疑問もある。

だから今のところ、巨大なファイルにはGit LFSを使わざるを得ない。だがlarge object promisorが広く普及すれば、いつかGitHubでも100MBを超えるファイルをプッシュできるようになるかもしれない。

Gitにおける巨大ファイルの未来はGitだ。

Gitプロジェクトが巨大ファイルについて真剣に考えてくれている。だからあなたが悩む必要はない。

今日のところは、Git LFSから逃れられない。

だが近いうちに、Gitで巨大ファイルを扱う際の唯一の障害は、「MP3ライブラリをGitに突っ込むのはまずい」という、うっすらと記憶に残る不吉な予感だけになるだろう。


Refactoring English 編集


  1. 後になって、他のGitホスティングサービスが独自のLFSサーバーを作った。今日では複数のGitホスティングサービスにプッシュしたり、LFSトランスファーエージェントを使ったりすることもできるが、いずれもコントリビューターにとってセットアップは複雑になる。余計な手間をかけない限り、ほぼロックインされたままだ。↩︎

  2. ファイルサイズ制限:100MB for GitHub100MB for GitLab.com↩︎

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント