巨大なリポジトリをクローンするときに便利なパーシャルクローンとsparse-checkout

create
2021年07月22日
update
2021年07月22日

Table 1. 環境
App Version

git

2.32.0

💪どう使うかの結論

クローン方法を選ぶワークフロー
Figure 1. クローン方法を選ぶワークフロー
Example 1. 一般的な使い方をするとき

リポジトリで作業をする場合はブロブレス・クローンを利用する。

git clone --filter=blob:none <URL>
Example 2. ビルド生成物だけが必要なとき

CI でビルドするためだけに使うなど、リポジトリにおいて git 操作をほぼ行わない場合はツリーレス・クローンまたはシャロー・クローンを利用する。

コミット履歴は参照したいならツリーレス・クローン
git clone --filter=tree:0 <URL>
コミット履歴も不要ならばシャロー・クローン
git clone --depth=1 <URL>
Example 3. 一部のファイル/ディレクトリだけ必要なとき

sparse-checkout 機能を使う。
パーシャルクローンと組み合わせると更に効果的。

git clone --filter=blob:none --sparse <URL>
cd <REPOSITORY>
git sparse-checkout init --cone
git sparse-checkout set <PATTERN1> [<PATTERN2> ...]

🍕パーシャルクローン( partial clone )とは

指定されたコミットの範囲内でダウンロードする blob オブジェクト[1]tree オブジェクト[2]の数を制限してクローンする機能のこと。
巨大なリポジトリから必要なものだけをクローンすることで、ダウンロード時間やディスク使用容量を削減するために使われる。

パーシャルクローンは git clone コマンドにおいて --filter オプションを指定することで有効化される。

GitHub から利用できるパーシャルクローンは ブロブレス・クローンツリーレス・クローン の2種類がある。

🌟ブロブレス・クローン

git clone 実行時にすべてのコミット履歴と tree オブジェクトはダウンロードされるが、各 blob オブジェクトはそれぞれが必要となった時にダウンロードされる[3]
このブロブレス・クローンは汎用的に使えるパーシャルクローンであり、一般的に使われる手法である。

リポジトリでの作業において、blob オブジェクトを必要とするコマンドは使用頻度が比較的低い。
そのため、ブロブレス・クローンは通常のクローンと同じような感覚で使える。

ブロブレス・クローンの実行
git clone --filter=blob:none <URL>
blobオブジェクトのダウンロードが行われるコマンド

git checkoutgit pullgit blame など。
ファイル内容を利用するコマンドが該当する。

ツリーレス・クローン

git clone 実行時にはすべてのコミット履歴のみがダウンロードされ、tree オブジェクトと blob オブジェクトはそれぞれが必要となった時にダウンロードされる[3]

利用方法はシャロー・クローンと似たような感じになり、使い所が限られる。
tree オブジェクトを必要とする git コマンドが意外とあるみたい)

ツリーレス・クローンの実行
git clone --filter=tree:0 <URL>

🧩一部のファイル/ディレクトリだけをクローンする( sparse-checkout

sparse-checkout 機能を利用することで、一部のファイルまたはディレクトリだけに制限してクローンすることができる。
この sparse-checkout 機能は git sparse-checkout コマンドから操作する。

例として Sparse-Checkout Example Repo リポジトリを対象にすると次のようになる。

Example 4. 一部のファイル/ディレクトリだけをクローンする例
パーシャルクローンと組み合わせ
git clone \
    --filter=blob:none \    (1)
    --sparse \              (2)
    https://github.com/derrickstolee/sparse-checkout-example

cd ./sparse-checkout-example
git sparse-checkout init --cone         (3)
git sparse-checkout set web/browser     (4)

ls -AF
bootstrap.sh  .git/  LICENSE.md  README.md  web/
1 ブロブレス・クローンとして実行[4]
2 リポジトリのルート直下にあるファイルだけをダウンロードするオプション。
3 sparse-checkout 機能の有効化。
4 ダウンロードしたいファイル/ディレクトリのパスをパターンで新規指定。
パターンを追加する場合は add サブコマンドを使う。
git v2.27.0 以降では --no-checkout オプションと git sparse-checkout の組み合わせはバグがあったため機能しない。
ただし v2.32.0 では修正されて動作するっぽい。

git sparse-checkout コマンドについて

git v2.32.0 でもまだ実験的なコマンドのため、動作やサブコマンドが変更される可能性がある。
sparse-checkout 機能の有効化
git sparse-checkout init --cone
  • パフォーマンス改善のため、 --cone オプションが一般的に付けられる(詳細は CONE PATTERN SET を参照)。

必要なパスのパターンを登録
git sparse-checkout set <PATTERN1> [<PATTERN2> ...]
git sparse-checkout add <PATTERN1> [<PATTERN2> ...]

set

指定したパターンで登録リストを新規作成。
既存のリストは上書きされる。

add

登録リストに指定したパターンを追加登録。

  • 指定するパターンの書式は .gitignore と同様。

登録されているパターンの一覧
git sparse-checkout list
sparse-checkout 機能を再適用
git sparse-checkout reapply
  • git mergegit rebase でパスを実体化した場合に使ったりする。

sparse-checkout 機能を無効化
git sparse-checkout disable

1. git 内部で使用されているオブジェクトタイプ。リポジトリ内の各ファイルの中身が保存されている。
2. ディレクトリのようなもの。各オブジェクトの階層情報が保存されている。
3. HEAD コミットだけは全てのデータがダウンロードされている。
4. 通常のクローンと比較して、この例では 172MB504KB へとサイズ削減できた。