Git LFS vs. 標準Git:大規模アセットのパフォーマンス比較

大規模アセットにおけるGit LFSと標準Gitの比較。クローン動作、ポインタファイル、LFS追跡、LFSが有効なケースについて解説します。

Git LFS vs. 標準Git:大規模アセットのパフォーマンス比較

リポジトリに大規模なバイナリアセットが含まれるようになると、Git LFSと標準Gitの選択が現実的な問題となります。ソースコードは通常、圧縮や差分が効率的ですが、動画、デザインファイル、ゲームテクスチャ、モデルファイル、大規模データセットはクローンを遅くし、履歴の整理を困難にします。

Git Large File Storage(通常Git LFSと呼ばれる)は、選択したファイルを小さなポインタファイルに置き換え、実際のコンテンツをLFSオブジェクトストアに保存することで、通常のGitリポジトリを軽量に保ちます。このトレードオフは多くのチームに役立ちますが、魔法ではありません。適切なファイルを選択し、追跡ルールをコミットし、LFSがコンテンツをダウンロードするタイミングを理解する必要があります。

標準Gitのパフォーマンスボトルネック

標準Gitはコミットされたコンテンツをオブジェクトデータベースに保存し、すべてのコミットバージョンを再構築するのに十分な履歴を保持します。これはテキストファイルには非常に適していますが、同じ200MBのバイナリファイルが何度も変更される場合にはうまく機能しません。

すぐに2つの問題が現れます:

  • JPEG、MP4、ZIP、PSD、コンパイル済みアーティファクトなどのバイナリ形式は、デルタ圧縮がうまくいかないことが多い。
  • 削除されたファイルは、履歴を書き換えない限り履歴に残り続ける。
  • 新しいクローンは過去のミスを支払うことになる。なぜならGit履歴には依然としてそれらの古いオブジェクトが含まれているから。
  • リポジトリメンテナンスコマンドが検査およびパックするデータが増える。

例えば、チームがスプリントごとに大規模なエクスポートデザインファイルをコミットした場合、後で現在のブランチからファイルを削除しても、古いバージョンは履歴から削除されません。新しい開発者やCIワーカーは、誰も積極的に使用していないデータをダウンロードする可能性があります。

Git Large File Storage(LFS)の紹介

Git LFSは、選択したファイルを通常のGitオブジェクトデータベースの外部で管理する拡張機能です。リポジトリには小さなテキストポインタが保持されます。実際のファイルコンテンツは、Gitホストまたは別のLFSサーバーが提供するLFSストレージに保存されます。

ポインタシステム

LFSポインタは次のようになります:

version https://git-lfs.github.com/spec/v1
oid sha256:4c2d44962ff3c43734e56598c199589d8995a643...a89c89
size 104857600

このポインタが通常のGitが見るものです。Git LFSクライアントは、チェックアウトや明示的なLFSコマンドが必要なときに実際のファイルコンテンツをダウンロードします。

パフォーマンス比較:LFS vs. 標準Git

操作 標準Git Git LFS
初期クローン コミットされた大規模オブジェクトを含むGit履歴をダウンロード ポインタファイルを含むGit履歴をダウンロード;LFSコンテンツは設定に応じてチェックアウト時にダウンロードされる可能性あり
リポジトリの成長 大規模バイナリが.git履歴を肥大化させる可能性 追跡されたファイルコンテンツが外部にあるため、Git履歴は小さく保たれる
チェックアウト 既にGitデータベースにあるオブジェクトを使用 チェックアウトされたコミットのためにLFSオブジェクトを取得する必要がある可能性あり
CIジョブ 履歴アセットのダウンロードに時間を浪費する可能性 ビルドにアセットが必要ない場合、LFSダウンロードをスキップまたは制限可能
クリーンアップ 古いコミットされたブロブを削除するために履歴の書き換えが必要 それでも注意が必要だが、新しいLFS追跡バージョンは通常のGit履歴を肥大化させない

重要な詳細はチェックアウト動作です。Git LFSがインストールされた状態での単純なgit cloneは、チェックアウトされたコミットに必要なLFSファイルをダウンロードすることが多いです。ポインタのみが必要な場合は、クローン時にGIT_LFS_SKIP_SMUDGE=1を使用し、後でgit lfs pullでファイルを取得します。

Git LFSを使用すべき場合

Git LFSは、大規模でバイナリであり、変更が予想されるファイルに適しています。一般的な例は次のとおりです:

  • *.psd*.tiff*.blend、その他のデザインまたは3Dアセット。
  • *.mp4*.mov*.wav、その他のメディアファイル。
  • プロジェクトに必要な大規模モデルファイル、テストフィクスチャ、またはデータセット。
  • プロジェクトにバージョン管理する明確な理由がある場合のコンパイル済みバイナリ。

できるからといってすべてのファイルをLFSに入れないでください。テキストファイル、ソースコード、小さな設定ファイル、Gitで通常の差分を確認したいファイルは標準Gitに残すべきです。

LFSを採用する前に、ホスティングプロバイダーのストレージと帯域幅の制限を確認してください。GitHub、GitLab、Bitbucket、およびセルフホスト型プラットフォームでは、割り当て、課金、保持動作が異なる場合があります。

Git LFSの実装

Git LFSクライアントをインストールし、ユーザー用のフックを有効にします:

git lfs install

LFSで管理したいパターンを追跡します:

git lfs track "*.psd"
git lfs track "assets/*.mp4"

これらのコマンドは.gitattributesを作成または更新します。そのファイルを影響を受けるアセットと一緒にコミットします:

git add .gitattributes assets/
git commit -m "デザインアセットをGit LFSで追跡"
git push

大規模ファイルが既に通常のGit履歴にコミットされている場合、LFSで追跡しても将来のコミットにのみ影響します。既存の履歴を移行するには、git lfs migrate importなどの移行ツールを使用し、履歴の書き換えがコミットIDを変更するため、慎重に調整してください。

LFSコンテンツをすぐにダウンロードせずにクローンするには、次を使用します:

GIT_LFS_SKIP_SMUDGE=1 git clone [email protected]:example/assets-heavy-repo.git
cd assets-heavy-repo
git lfs pull --include="assets/*.mp4"

実践的なポイント

ソースコードや小さなテキストファイルには標準Gitを使用してください。リポジトリに属するが通常のGit履歴を肥大化させてはいけない大規模バイナリアセットにはGit LFSを使用してください。

チームリポジトリでは、早期にLFSルールを追加し、.gitattributesをコミットし、CIがLFSダウンロードをどのように処理するかを文書化し、ホストのLFS制限を確認してください。これにより、クローン、チェックアウト、リリースビルド中に開発者を驚かせることなく、パフォーマンスの利点が得られます。