開発プロジェクトが長いとリポジトリが肥大化しがちです.
大きくなったリポジトリではcloneやcheckoutのパフォーマンスが重く、ストレスを感じることが多いと思います.
そこで、大きくなってしまったリポジトリとうまく付き合っていくためのTipsをまとめてみました.
1. 最新履歴のみをcloneする(shallow-clone)
通常のcloneではリポジトリ内のすべての履歴を取得しますが、
CIツールなど、最新コミットや一部の履歴のみあれば十分な場合に shallow-clone を使用すると、ダウンロードするリポジトリデータのサイズを抑えることができます.
1-1. shallow-cloneを行う
shallow-cloneを行うには、clone時に以下のオプションを指定します.
$ git clone [url] --depth N
$ git clone [url] --single-branch -b [ブランチ名] --depth N
$ git clone [url] --no-single-branch --depth N
1-2. shallow-cloneされたブランチのupdate
shallow-cloneしたリポジトリのブランチをupdateするには、update-shallow オプションを指定します.
shallow-cloneで取得した起点コミット(grafted)以降の履歴のみを取得することができます.
git fetch --update-shallow [remote名] [ブランチ名]
ブランチ名を省略することですべてのブランチについてshallow-clone起点コミット(grafted)以降の履歴を取得することもできます.
ただし、shallow-cloneが維持されるのは既存のブランチのみで、
ローカルに起点コミットがない(ex. リモートに新規ブランチがある)場合は、新規ブランチについてすべての履歴が取得されてしまいます.
これを防ぐには depth オプションを指定して、新規含むすべての最新コミットを起点コミットとして取得しなおします.
$ git fetch --update-shallow [--depth=N]
1-3. shallow-cloneの解除
shallow-cloneを解除するには、unshallow オプションをつけてfetchをおこないます.
$ git fetch --unshallow
2. 必要なオブジェクトのみをcloneする(partial-clone)
リポジトリをcloneする際に、Gitの履歴オブジェクトのうち、実データ(blob)やファイル構成(tree)に関する情報は、実際に必要になったタイミングで行うよう設定します.
遅延取得するデータの種類によってはgitの一部機能に制限がかかることがありますが、初回clone時にダウンロードするローカルリポジトリのデータサイズを抑えることができます.
前提として、bareリポジトリのあるサーバ側のgit設定として下記が必要になります.
$ git config uploadpack.allowfilter true
$ git config uploadpack.allowanysha1inwant true
2-1. partial-cloneの種類
cloneから除外するオブジェクトの種類によって以下の2種類があります.
(1) tree-less clone
最新コミットと履歴のみを初回cloneで取得.
(2) blob-less clone
最新コミットと履歴のtreeを取得.
partiah-cloneについては、以下のサイトの解説がわかりやすいです.
github.blog
2-2. partial-cloneの操作
partial-cloneリポジトリは、以下のように設定します.
2-2-1. 新規にcloneするとき
$ git clone --fliter=tree:none [url] [clone_to]
$ git clone --fliter=blob:none [url] [clone_to]
2-2-2. completeリポジトリからpartial-cloneリポジトリへの変換
既存のリポジトリをblob-lessに変換する例.
$ git config remote.[remote_name].promisor true
$ git config remote.[remote_name].partialclonefilter blob:none
$ git repack -ad --filter=blob:none --filter-to=pack --no-write-bitmap-index
$ rm -f pack-*
2-2-3. partial-cloneリポジトリからcompleteリポジトリへの変換
$ git config --unset remote.[remote_name].partialclonefilter
$ git fetch --refetch
$ git gc --aggressive
3. 必要なファイルのみをcheckoutする(sparse-checkout)
submoduleで他プロジェクトを参照するときなどは、プロジェクトの一部ファイルのみさえあればよいといった状況があります.
sparse-checkoutでは、作業領域に展開するファイルを指定したファイル/ディレクトリのみに限定します.
ブランチを切り替えるときに、すべてのファイルをローカルに再現する必要がなくなるので、checkoutによるブランチ切り替えが高速になります.
3-1. sparse-checkoutを設定する
コマンドで設定する場合は以下の手順を行います.
$ git sparse-checkout init
$ git sparse-checkout set hoge/ fuga/
$ git sparse-checkout add hoga/
3-2. sparse-checkoutファイルを直接編集して適用
.git/info/sparse-checkoutファイルを直接作成/編集しても設定ができます.
.gitignoreと同じ書式で対象ディレクトリ/ファイルを指定します.
ファイル単位の指定は、.git/info/sparse-checkout ファイルを直接編集することで指定ができます.
直接編集したあと、後述の git sparse-checkout reapply
で作業領域に適用します.
/*
!/*/
/hoge/
/fuga/
3-3. sparse-checkoutを反映
info/sparse-checkoutファイルをもとに、ファイルの内容を作業領域へ反映します.
$ git sparse-checkout reapply
3-4. sparse-checkoutの設定解除
以下コマンドを実行するとsparse-checkoutが解除できます.
$ git sparse-checkout disable
解除後は, 再度 reapplyすることで再設定ができます.
参考情報