Gitにおける大容量ファイルの悪夢
AI開発、動画処理、あるいはデータベース運用に携わる方なら、誰もが一度は経験したことがあるのではないでしょうか。うっかり8GBのモデルチェックポイントや15GBのzipファイルをリポジトリにコミットしてしまい、数回のコミットだけで.gitディレクトリが数百GB規模にまで肥大化してしまう事態です。その結果、チームメンバーがgit cloneを実行するたびに接続タイムアウトが頻発し、Gitサーバーが過負荷エラーを吐き出すことになります。
Gitは本来、テキストベースのソースコードを追跡するために設計されています。重いバイナリファイルをコミット履歴に含めてしまうと、Gitはファイルが変更されるたびに新しいバージョン全体を圧縮・保存するため、リポジトリの容量はファイルサイズに比例して雪だるま式に急増します。
一般的に、まず最初に検討される解決策はGit LFS (Large File Storage) です。しかし、LFSはGitサーバーに強く依存する中央集権型(集中管理)アーキテクチャで動作します。例えばGitHubの場合、無料枠で提供されるストレージとダウンロード帯域幅は月あたりわずか1GBずつです。上限を超えると、データパック(50GB)ごとに月額5ドルの追加料金が発生します。数テラバイト規模のデータセットを扱うチームにとって、このランニングコストは急速に膨らんでいきます。
さらに、オフィスに40TBのNASがあったり、自前のMinIOバケットを運用していたりしても、Git LFSではこれらの既存リソースを柔軟に活用することが困難です。こうした背景から、多くのエンジニアがgit-annexへと移行しています。
git-annexはどのように動作するのか?
根本的な違いは、その分散型(Peer-to-Peer)アーキテクチャにあります。
git-annexは、すべての巨大ファイルを中央サーバーへ強制的に送信させるのではなく、各PC、サーバー、外付けHDDなどをそれぞれ独立した1つのノードとして扱います。ファイルをgit-annexに追加すると、以下の処理が行われます。
- ファイルの実データは
.git/annex/objects/内の内部ストレージに移動され、誤編集を防ぐために書き込み権限がロック(読み取り専用)されます。 - 作業ディレクトリ上には、git-annexによってそのオブジェクトを指すシンボリックリンクまたはポインタファイルが作成されます。通常のGitはこのポインタファイル(わずか数十バイト程度)のみをコミットします。
- git-annexは、
git-annexというバックグラウンドブランチを通じて各ファイルの実際の保管場所を追跡します。このブランチには、「ハッシュ値Xのファイルが現在開発者のノートPC、GPUサーバー、社内NASのどこに存在しているか」というメタデータが記録されます。
git-annexとGit LFSのクイック比較
| 比較項目 | Git LFS | git-annex |
|---|---|---|
| アーキテクチャ | 集中型クライアント・サーバー | 分散型ピア・ツー・ピア(Peer-to-Peer) |
| ストレージ基盤 | Gitホスティング(GitHub、GitLab等)に密結合 | Rsync、SSH、S3、MinIO、NAS、外付けHDDなど自由 |
| データの所有権 | サーバー側でマスターデータを一元保持 | どのノードにどのファイルを保持させるか自由に選択可能 |
| 運用コスト | ストレージ費用および下り転送(Egress)料金が発生 | 既存のインフラを活用すればほぼ0円 |
実践:git-annexの導入と基本操作
1. ツールのインストール
UbuntuまたはDebianの場合:
sudo apt update
sudo apt install -y git-annex
macOS(Homebrew)の場合:
brew install git-annex
2. リポジトリの初期化と大容量ファイルの管理
AIモデルの重みパラメータファイルを管理するシナリオを想定してみましょう:
mkdir ai-project && cd ai-project
git init
git annex init "workstation-laptop"
# テスト用に500MBのダミーバイナリファイルを生成
fallocate -l 500M model_weights_v1.bin
# 通常のgit addではなく、git-annexの管理下にファイルを追加
git annex add model_weights_v1.bin
# メタデータをGitにコミット
git commit -m "feat: track model_weights_v1.bin via git-annex"
ls -lを実行すると、model_weights_v1.binが.git/annex/objects/内のファイルを指すシンボリックリンクになっていることが確認できます。Gitはこのシンボリックリンクのみを追跡するため、Gitリポジトリ自体は非常に軽量な状態を維持できます。
3. SSH/rsyncによるSpecial Remoteの設定
git-annexの真骨頂はSpecial Remotes機能にあります。オフィスのSynology NASや社内バックアップサーバーを、そのままストレージバックエンドとして活用できます:
# 社内サーバーを指すrsyncリモートを初期化
git annex initremote office-nas type=rsync \
[email protected]:/volume1/annex-data \
encryption=none
4. 同期とローカルストレージの解放
モデルのトレーニングが完了したら、データをNASへ転送します:
# ファイルの実データをNASサーバーへ転送
git annex copy model_weights_v1.bin --to=office-nas
# ファイルの現在の所在を確認
git annex whereis model_weights_v1.bin
実行結果には、このファイルがworkstation-laptopとoffice-nasの双方に存在していることが表示されます。
ノートPCのSSDの空き容量が逼迫してきた場合も、ワンコマンドで安全に容量を解放できます:
git annex drop model_weights_v1.bin
git-annexには安全機構が標準で備わっています。少なくとも1箇所以上のリモートにファイルが安全に退避されていない限り(numcopiesパラメータで設定。デフォルトは1)、dropコマンドは実行を拒否します。誤操作によってデータが失われる心配はありません。
チームメンバーがリポジトリをcloneし、検証用に該当ファイルの実データを手元に取得したい場合は、次のように実行します:
git annex get model_weights_v1.bin
5. ファイル内容の編集
sha256ハッシュの不整合を防ぐため、git-annex管理下のファイルはデフォルトで読み取り専用になっています。ファイルを編集するには、まずロックを解除します:
# ファイルの書き込みロックを解除
git annex unlock model_weights_v1.bin
# データを上書き・更新
echo "new checkpoint data" >> model_weights_v1.bin
# 新バージョンとして再度パッケージ・保存
git annex add model_weights_v1.bin
git commit -m "fix: update model weights checkpoint"
まとめ
git-annexを活用すれば、高額なGit LFSプランに依存することなく、従来のGitにおけるストレージ容量の制約を突破できます。ローカルマシン、SSHサーバー、クラウドストレージ間で柔軟にデータを分散配置し、データ管理の主導権を完全に取り戻すことができます。ぜひ次回のデータサイエンスや機械学習プロジェクトで、その真価を試してみてください。

