🐱

部分的にgit cloneしたりgit checkoutする

2021/06/05に公開

概要

調べ物をしているとフレームワークやライブラリのソースコードが手元に欲しくなるときがあります。
そんなときにリポジトリを丸ごとcloneしたりcheckoutするのではなく、特定の部分に絞ることで時間とディスクを節約したいというのが本記事の趣旨です。

部分的にcloneする

git clonegit fetch--depthオプションで取得するコミット数を指定できます。

Springで試してみましょう。

まず--depthを設定せずに取得します。[1]

$ time git clone --no-checkout git@github.com:spring-projects/spring-framework.git
Cloning into 'spring-framework'...
remote: Enumerating objects: 609218, done.
remote: Counting objects: 100% (38/38), done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 609218 (delta 7), reused 21 (delta 4), pack-reused 609180
Receiving objects: 100% (609218/609218), 163.78 MiB | 6.27 MiB/s, done.
Resolving deltas: 100% (297615/297615), done.
git clone --no-checkout git@github.com:spring-projects/spring-framework.git  13.09s user 2.49s system 49% cpu 31.448 total
$ du -sh spring-framework/.git
193M    spring-framework/.git
$

git cloneに31秒かかり、.gitのサイズは193MBでした。

次に--depth=1を設定して取得します。

$ time git clone --no-checkout --depth=1 git@github.com:spring-projects/spring-framework.git
Cloning into 'spring-framework'...
remote: Enumerating objects: 10774, done.
remote: Counting objects: 100% (10774/10774), done.
remote: Compressing objects: 100% (7299/7299), done.
remote: Total 10774 (delta 3038), reused 8527 (delta 2780), pack-reused 0
Receiving objects: 100% (10774/10774), 12.45 MiB | 5.86 MiB/s, done.
Resolving deltas: 100% (3038/3038), done.
git clone --no-checkout --depth=1   0.70s user 0.19s system 14% cpu 6.121 total
$ du -sh spring-framework/.git
 13M    spring-framework/.git
$

git cloneは6秒になり、.gitのサイズは13MBになりました。

すべてのコミットを取得したくなった場合はgit fetch --unshallowを実行してください。

部分的にcheckoutする

前セクションでgit cloneするときに--no-checkoutというオプションを設定していました。
これを付けているとclone後にHEADcheckoutしなくなる、つまり.gitディレクトリのみが作成されることになります。

この状態から特定のディレクトリだけをcheckoutするためにgit sparse-checkoutを使います。

--depth=1を設定してcloneしたSpringのリポジトリを使って試してみます。

$ cd spring-framework
$ ls -a
.    ..   .git
$ git sparse-checkout init
$ git checkout
Your branch is up to date with 'origin/main'.
$ ls -a
.                      .git                   .mailmap               LICENSE.txt            build.gradle           gradlew.bat            settings.gradle
..                     .gitattributes         CODE_OF_CONDUCT.adoc   README.md              gradle.properties      import-into-eclipse.md
.editorconfig          .gitignore             CONTRIBUTING.md        SECURITY.md            gradlew                import-into-idea.md
$

まずls -a.gitしかないことを確認しています。

次にgit sparse-checkout initsparse-checkoutを有効化しています。

最後にもう一度ls -aでリポジトリのルートディレクトリにあるファイルだけがcheckoutされていることを確認しています。

sparse-checkoutの設定

sparse-checkoutでどのファイルがcheckoutの対象になるのかはlistサブコマンドで確認できます。

デフォルトの設定は次のようになっています。

$ git sparse-checkout list
/*
!/*/
$

これはルートディレクトリ内のすべてのファイルを対象とし(/*)、ルートディレクトリの1つ下のディレクトリ内は対象外とします(!/*/)。

checkoutの対象を増やしたいときはaddサブコマンドを使います。

試しにspring-webmvcディレクトリを対象に加えましょう。

$ git sparse-checkout list
/*
!/*/
$ ls
CODE_OF_CONDUCT.adoc   LICENSE.txt            SECURITY.md            gradle.properties      gradlew.bat            import-into-idea.md
CONTRIBUTING.md        README.md              build.gradle           gradlew                import-into-eclipse.md settings.gradle
$ git sparse-checkout add spring-webmvc
$ git sparse-checkout list
/*
!/*/
spring-webmvc
$ ls
CODE_OF_CONDUCT.adoc   LICENSE.txt            SECURITY.md            gradle.properties      gradlew.bat            import-into-idea.md    spring-webmvc
CONTRIBUTING.md        README.md              build.gradle           gradlew                import-into-eclipse.md settings.gradle
$

sparse-checkoutの設定とファイル一覧を確認してからaddサブコマンドでspring-webmvcを追加しました。
それから再度sparse-checkoutの設定とファイル一覧を確認しています。
spring-webmvcディレクトリがcheckoutできていることがわかります。

sparse-checkoutをやめたい、つまりすべてのファイルをcheckoutしたくなった場合はdisableサブコマンドを使用してください。

脚注
  1. git cloneの時間を計測するためにtimeコマンドを使用しています。作業環境はmacOSです。 ↩︎

Discussion