数十GBのリポジトリでGit Cloneの速度を「爆速」にする方法

Git tutorial - IT technology blog
Git tutorial - IT technology blog

深夜2時、20GBのリポジトリが引き起こした悪夢

時計は深夜2時を指していました。緊急のホットフィックスをデプロイするために待機していましたが、突然CI/CDパイプラインが「Timeout」エラーを吐き出しました LOGを確認すると、git cloneのステップで15分以上経過しても終わっていないことに愕然としました。このリポジトリは10年以上の歴史が蓄積されており、古いバイナリファイルを含めて20GB近くもあったのです。

これらすべてのデータをダウンロードし終えるのを待っていたら、クライアントに怒鳴られてしまいます。窮地に立たされた私は、あることを思い出しました。数行のコードを修正するためだけに、プロジェクトの「家系図」すべてが必要なわけではないということです。そこで救世主となったのが、Shallow CloneとPartial Cloneでした。もしあなたも、コーヒーを淹れて戻ってきてもまだGitのクローンが終わっていないという状況にうずうずしているなら、この記事はあなたのためのものです。

【即効】30秒でクローンを高速化する方法

急いでバグを修正するために、今すぐコードを手元に持ってきたいですか?以下の2つのコマンドのいずれかを試してみてください。

方法1:最新のコミットのみを取得する(Shallow Clone)

git clone --depth 1 https://github.com/user/huge-repo.git

このコマンドは、すべての履歴を無視し、コードの最新状態のみをダウンロードします。結果として、ダウンロード容量を5GBからわずか100MB程度へと一瞬で削減できます。

方法2:履歴はすべて取得し、重いファイルを後回しにする(Partial Clone)

git clone --filter=blob:none https://github.com/user/huge-repo.git

こちらはよりスマートな方法です。コミット履歴はすべてダウンロードしますが、ファイルの実体(blobs)は「忘れた」状態にします。Gitは、別のブランチにチェックアウトするなど、実際にファイルが必要になった時にだけダウンロードを行います。


なぜリポジトリはこれほど肥大化するのか?

デフォルトのgit cloneコマンドは、最初のコミットからの全ファイルの全バージョン、全ブランチ、全タグなど、**すべて**をダウンロードしようとします。長年運用されているモノレポ(Monorepo)プロジェクトでは、これが帯域幅とストレージの両方にとって大きな負担となります。

1. Shallow Clone (–depth) — 表面だけをさらう

小説を最初から読むのではなく、最終章だけを読むようなイメージです。--depth 1は、切り詰められた履歴(truncated history)を作成します。

  • メリット: 極めて高速で、メモリを最大限に節約できる。
  • デメリット: 古いコミットのgit logが見られない。親コミットの情報が不足しているため、pushやmergeでエラーが発生することがある。

以前、JenkinsでShallow Cloneを使用して痛い目を見たことがあります。履歴が足りないため、SonarQubeがgit blameを実行できず、バグを正しく担当者に割り当てられませんでした。レポートの内容は支離滅裂。そのため、Shallow Cloneはビルドやクイックテストなどのタスクに限定して使用すべきです。

2. Partial Clone (–filter) — 必要な時にファイルをダウンロード

この機能はGit 2.20から登場した、まさに革命的なものです。コミット構造は維持しつつ、ファイルの内容だけをサーバーに残しておきます。

覚えておくべき2つの一般的なフィルタがあります:

  • --filter=blob:nonecheckoutするまで一切のファイルをダウンロードしません。速度と柔軟性のバランスが最も取れた選択肢です。
  • --filter=blob:limit=1m:1MB未満の小さなファイルのみをダウンロードします。画像や動画、バイナリなどの重いファイルは、実際に必要になるまでサーバーに置かれたままになります。

応用テクニック:Sparse Checkoutとの組み合わせ

バックエンドとモバイル用コードも含まれる巨大なモノレポで、/frontendフォルダだけが必要な場合はどうすればいいでしょうか?すべてをダウンロードする必要はありません。**Partial Clone + Sparse Checkout**のコンボを使いましょう。

# 1. クローンするが、ファイルはダウンロードせず、チェックアウトもしない
git clone --filter=blob:none --no-checkout https://github.com/user/huge-repo.git
cd huge-repo

# 2. 本当に必要なディレクトリだけを指定する
git sparse-checkout set web-app/src

# 3. そのフォルダのファイルを取得するためにチェックアウトする
git checkout main

この方法により、ダウンロード時間を節約できるだけでなく、マシン内に数千もの不要なファイルを保持する必要がなくなります。


実戦経験から:どの方法を選ぶべきか?

古いシステムで何度も冷や汗をかいた経験から、私は以下のような選択基準を設けています。

Shallow Clone (–depth) を使うべき場面:

  • CI/CDパイプラインの実行時(ビルド後にすぐ削除する場合)。
  • 本番サーバーで、待機時間を最小限にして緊急のホットフィックスを適用したい時。
  • rebaseや深い履歴の参照が必要ないと確信している時。

Partial Clone (–filter) を使うべき場面:

  • リポジトリが非常に重いプロジェクトで、長期的に開発を行う時。
  • コードの履歴調査のためにgit loggit blameが必要な時。
  • ストレージを節約しつつ、Gitの全機能を維持したい時。

一度、Shallow Cloneで履歴が完全に見えていない状態で作業し、誤ったブランチにforce pushしてしまったことがあります。その時の教訓は、「個人の開発マシンには常に**Partial Clone**を優先し、**Shallow Clone**は仮想マシン(VM)やDockerコンテナ内でのみ使用する」ということです。

まとめ

ツールを使いこなすことは、創造性を維持するための最良の方法です。Shallow CloneとPartial Cloneを理解すれば、大規模プロジェクトでのストレスが軽減されます。同時に、チームのCI/CDシステムも格段にスムーズに動作するようになります。git cloneのプログレスバーが止まっているのを見て落胆するのはもうやめましょう。ぜひ次のプロジェクトで試してみてください。その違いに驚くはずです!

Share: