はんなりと、ゆるやかに

アジャイル、スクラムが好きなITエンジニアが日々から学んだことをアウトプット

git2.27以降にgit sparse-checkoutを使う場合はno-checkoutではなくsparseを使おう

以下の記事で紹介したPartial Cloneとgit sparse-checkoutコマンドの組み合わせが、git 2.27 から使えなくなっていました。自分の記事を参考に同じ手順で進めても成功しなかったので気づきました。本記事はgit 2.27 以降で同じようなことをする解決策をまとめます

iucstscui.hatenablog.com

git 2.26 で出来て、2.27で出来なくなった手順

  1. git clone --filter=blob:none --no-checkout https://github.com/git/git.git
  2. git sparse-checkout init --cone
  3. git sparse-checkout set Documentation

git 2.26の場合、「1」を実行するとディレクトリ内は空の状態でcloneされます。「2」を実行するとルートディレクトリのファイルが展開され、サブモジュールが初期化された状態になります。ディレクトリ関連は展開されません。「3」を実行するとDocumentationディレクトリが展開されます。

git 2.27 の場合、「2」「3」を実行してもファイルもディレクトリも展開されません

実は予期しないバグがあった

以下の記事で同じように困っている方に対して回答がありました。
stackoverflow.com

--no-checkout後のsparse-checkout 予期しないバグがあったため、f56f31aのコミットで機能しないように修正されたようです。
※英語ムズイ。読み間違えてなければこういうことらしい。

git 2.27以降でPartial Clone後にgit sparse-checkoutをする方法

今回調べて気づきましたが、git clone に専用のオプション--sparse がありました。これを使うことで解決できます。
git-scm.com

--sparse
Initialize the sparse-checkout file so the working directory starts with only the files in the root of the repository. The sparse-checkout file can be modified to grow the working directory as needed.
作業ディレクトリがリポジトリのルートにあるファイルのみで始まるようにします。スパースチェックアウトファイルは、必要に応じて作業ディレクトリを拡大するように変更できます。

--sparse を使ってsparse-checkoutすると以下のようになります。

$ git clone --sparse https://github.com/git/git.git 

Cloning into 'git'...
remote: Enumerating objects: 292088, done.
remote: Total 292088 (delta 0), reused 0 (delta 0), pack-reused 292088 eceiving objects: 100% (292088/292088), 143.50 MiReceiving objects: 100% (292088/292088), 143.51 MiB | 2.45 MiB/s, done.

Resolving deltas: 100% (217554/217554), done.

$ git sparse-checkout init --cone

$ git sparse-checkout set Documentation

これにより、ルートディレクトリのファイルと、git sparse-checkout set Documentation で後から追加したDocumentatinディレクトリのみが展開された状態になります。不要なオブジェクトを除外してダウンロードできるので、大きなリポジトリもサイズを抑えて素早くcloneできます。

--filter=blob:noneを追加すると、さらにリポジトリサイズを抑えることが出来ます。

$ git clone --filter=blob:none --sparse https://github.com/git/git.git 

Cloning into 'git'...
remote: Enumerating objects: 180497, done.
remote: Total 180497 (delta 0), reused 0 (delta 0), pack-reused 180497 eceiving objects: 100% (180497/180497), 61.63 MiBReceiving objects: 100% (180497/180497), 62.60 MiB | 2.66 MiB/s, done.

Resolving deltas: 100% (114752/114752), done.
remote: Enumerating objects: 385, done.
remote: Counting objects: 100% (385/385), done.
remote: Compressing objects: 100% (385/385), done.
remote: Total 439 (delta 0), reused 0 (delta 0), pack-reused 54
Receiving objects: 100% (439/439), 1.76 MiB | 1.76 MiB/s, done.
Updating files: 100% (440/440), done.

$ git sparse-checkout init --cone

$ git sparse-checkout set Documentation

remote: Enumerating objects: 347, done.
remote: Counting objects: 100% (347/347), done.
remote: Compressing objects: 100% (345/345), done.
remote: Total 751 (delta 6), reused 2 (delta 2), pack-reused 404
Receiving objects: 100% (751/751), 1.58 MiB | 1.34 MiB/s, done.
Resolving deltas: 100% (45/45), done.
Updating files: 100% (751/751), done.

cloneしたディレクトリのサイズを比較すると、--filter=blob:noneなしの場合は161MB、ありの場合は81MBと節約できました。

まとめ

  • git 2.27移行は--no-checkout を使ったsparse-checkoutができない
  • git clone --sparseを使う