今まで使っていなかった Git コマンドを学んでいく.今回は git sparse-checkout を試す.
git sparse-checkout とは?
コマンド名にある sparse は「わずかな」という意味で,Git リポジトリの「一部」を取得できる.git clone --depth を使ってコミットを刈り取るのではなく,指定したディレクトリを取得する.モノリポ(モノレポ)構成のときに効果的に使える.git sparse-checkout は歴史的な変化もあり,今年になって改善されている.記事を検索すると Git 2.25 より前の git sparse-checkout を紹介した記事が多いように感じたため,今回は Git 2.26.2 を使って試した.
- Git 1.7
- 2010年2月 リリース
git sparse-checkout導入
- Git 2.25
- 2020年1月 リリース
git sparse-checkout機能改善- Highlights from Git 2.25 - The GitHub Blog
- Git 2.26
- 2020年3月 リリース
git sparse-checkout add追加- Highlights from Git 2.26 - The GitHub Blog
derrickstolee/sparse-checkout-example を使う
git sparse-checkout を試すために,そこそこ大きめな GitHub リポジトリを探していた.以下の GitHub Blog の記事を読んだところ git sparse-checkout を試す手順(Git 2.25 前提)と,サンプルリポジトリが載っていたため,今回は derrickstolee/sparse-checkout-example リポジトリ(モノリポ構成)を使うことにした.
1. 既存リポジトリで git sparse-checkout を使う
まず,既存リポジトリ(git clone をした状態)で git sparse-checkout を使っていく.git clone をして,ファイル数をカウントすると 1585個 となる.ディレクトリ構成は GitHub Blog に載っている画像を見ればすぐ理解できる.tree で簡単に紹介すると,以下のようにモノリポ構成(2階層)になっている.例えば client/android ディレクトリや web/browser ディレクトリなど.
$ git clone git@github.com:derrickstolee/sparse-checkout-example.git Cloning into 'sparse-checkout-example'... remote: Enumerating objects: 21, done. remote: Counting objects: 100% (21/21), done. remote: Compressing objects: 100% (19/19), done. remote: Total 1901 (delta 2), reused 11 (delta 1), pack-reused 1880 Receiving objects: 100% (1901/1901), 170.93 MiB | 2.56 MiB/s, done. Resolving deltas: 100% (177/177), done. Updating files: 100% (1560/1560), done. $ cd sparse-checkout-example $ find . -type f | wc -l 1585 $ tree -L 2 . ├── LICENSE.md ├── README.md ├── bootstrap.sh ├── client │ ├── README │ ├── android │ ├── electron │ └── iOS ├── service │ ├── README │ ├── common │ ├── identity │ ├── items │ └── list └── web ├── README ├── browser ├── editor └── friends
さっそく,git sparse-checkout init --cone を実行して sparse-checkout を有効化する.--cone オプションはパターンマッチによりディレクトリ探索のパフォーマンスを改善するオプションとして付けておく.直後にファイル数をカウントすると,なんと 30個 に減っている.client/android ディレクトリや web/browser ディレクトリも除外されている.設定は .git/info/sparse-checkout ファイルにあり,意味としては「作業ディレクトリをルートにあるファイルに制限する」となる.
$ git sparse-checkout init --cone $ find . -type f | wc -l 30 $ tree -L 2 . ├── LICENSE.md ├── README.md └── bootstrap.sh $ cat .git/info/sparse-checkout /* !/*/
今のままだと重要なコードも除外されているため,例えば「Android アプリを開発するチーム」の場合は,git sparse-checkout set client/android を実行して,ディレクトリを設定できる.実際にファイル数は 56個 になり,client/android ディレクトリを参照できるようになる.
$ git sparse-checkout set client/android $ find . -type f | wc -l 56 $ tree -L 2 . ├── LICENSE.md ├── README.md ├── bootstrap.sh └── client ├── README └── android $ cat .git/info/sparse-checkout /* !/*/ /client/ !/client/*/ /client/android/
次に「フロントエンドを開発するチーム」の場合は,git sparse-checkout set service web/browser を実行する.すると service ディレクトリと web/browser ディレクトリを参照できるようになる.set は上書きする仕様になっているため,既に client/android ディレクトリは参照できなくなっている.さらに .git/info/sparse-checkout ファイルを見なくても git sparse-checkout list を使えばディレクトリを確認できる.
$ git sparse-checkout set service web/browser $ find . -type f | wc -l 636 $ tree -L 2 . ├── LICENSE.md ├── README.md ├── bootstrap.sh ├── service │ ├── README │ ├── common │ ├── identity │ ├── items │ └── list └── web ├── README └── browser $ git sparse-checkout list service web/browser
なお,Git 2.26 から git sparse-checkout add も使えるため,ディレクトリを追加するときに毎回 git sparse-checkout set をし直していた手順をシンプルにできる.次の手順で add を使っていく.
2. git clone --filter=blob:none --no-checkout と組み合わせる
git clone をするときに --filter=blob:none オプションを付けると,オブジェクトのダウンロードをせずに clone できる(Partial Clone とも言う).さらに --no-checkout オプションを付けると,チェックアウトをせずに clone できる.新しくリポジトリを取得する場合は git clone --filter=blob:none --no-checkout と組み合わせるとオーバーヘッドを減らして,モノリポを管理できる.
$ git clone --filter=blob:none --no-checkout git@github.com:derrickstolee/sparse-checkout-example.git Cloning into 'sparse-checkout-example'... remote: Enumerating objects: 13, done. remote: Counting objects: 100% (13/13), done. remote: Compressing objects: 100% (12/12), done. remote: Total 373 (delta 1), reused 7 (delta 1), pack-reused 360 Receiving objects: 100% (373/373), 76.78 KiB | 644.00 KiB/s, done. Resolving deltas: 100% (18/18), done. $ cd sparse-checkout-example $ find . -type f | wc -l 29
同じように git sparse-checkout init --cone を実行して sparse-checkout を有効化する.今回は add を使って client/android ディレクトリと service ディレクトリと web/browser ディレクトリを参照できるようにする.git sparse-checkout の手順は同じだけど,オブジェクトのダウンロードを後回しにできる点はメリットと言える.
$ git sparse-checkout init --cone $ git sparse-checkout add client/android $ git sparse-checkout add service web/browser $ find . -type f | wc -l 667 $ tree -L 2 . ├── LICENSE.md ├── README.md ├── bootstrap.sh ├── client │ ├── README │ └── android ├── service │ ├── README │ ├── common │ ├── identity │ ├── items │ └── list └── web ├── README └── browser
まとめ
今まで使っていなかった Git コマンドとして,今回は git sparse-checkout を試した.モノリポ(モノレポ)構成のときに効果的に使える.もし新しくリポジトリを取得する場合は git clone --filter=blob:none --no-checkout と組み合わせるとオーバーヘッドを減らして,素早く clone できる点も覚えておくと良さそう!