Git clone depthで履歴を削減して高速クローン

Git
この記事は約6分で読めます。
記事内に広告が含まれています。

次のようなケースではgit clone時にdepthオプションを付与すると、履歴を削減して高速クローンが可能です。

  • 最新ソースでビルドなどをしたい。
  • 最新ソースの指定ブランチをチョロっと変更してCommit & Pushしたい。

履歴を削減
⇒ depthで指定した履歴数しか取得しないってことです。

以下、本ページの目次です。depth関連で少し書いてみました。

git clone –depth

基本的にいつものgit cloneに–depthオプションを付与すればOKです。

git clone --depth N <url>
例:git clone --depth 1 https://github.com/microsoft/vscode.git

depth=1の場合、git logで確認可能な履歴数は1個となります。該当履歴には「grafted」(日本語訳で接木)という単語が付与されます。

$git log
commit 6a0c953d12687879533cb03e407eea1cf80e6d6a (grafted, HEAD -> main, origin/main, origin/HEAD)

⇒ 最終取得の履歴にgraftedという文字列が付与される。

ブランチがmainしかない・・・。checkout/switch出来ない・・・。

そうなのよ。関連オプションを紹介するね。

  • mainではなく指定ブランチを最小履歴で取得したい。
    -b <branchName>オプションを付ける。
    例:git clone –depth 1 -b develop <url>
  • 全ブランチを最小履歴で取得したい。
    –no-single-branchオプションを付ける。
    例:git clone –depth 1 –no-single-branch <url>

後から履歴を追加取得

やっぱりもう少しログを確認したくなった場合は、追加取得が可能です。

git fetch --depth N
例:git fetch --depth 5

やっぱりブランチや履歴を含めて全部取得したい。

git fetch --unshallow
git remote set-branches origin '*'
git fetch

※再取得だけだと関連付けがないため、リモートブランチを関連付けして再fetchする感じ。

ブランチマージは?

ブランチマージはマージ元・先の履歴を利用するものなので、履歴削減状態だと失敗します。
※ブランチがmainしかなくてもダメ。

git merge develop
→ fatal: refusing to merge unrelated histories

通常のcloneをやり直しかな?

そうだね、素直にやり直しが無難かな。けど履歴の追加取得でも可能だった。

git fetch –depth N によってブランチの分岐点までの履歴を再取得しところ、git mergeは動作しました。
→ ブランチの分岐点 = 例えばmain, developであれば派生元の履歴まで再取得。

最初に「–no-single-branch」で全ブランチ情報を取得していることが前提です。
※ブランチが無いのに、git fetch –depth Nは無意味です。

実施の効果はどの程度?

10万越えの履歴をもつ「vscode.git」で試してみます。

# 通常のclone(depth未指定)
$ time git clone https://github.com/microsoft/vscode.git vscodeFull.git
Cloning into 'vscodeFull.git'...
remote: Enumerating objects: 1581743, done.
remote: Counting objects: 100% (1575/1575), done.
remote: Compressing objects: 100% (951/951), done.
remote: Total 1581743 (delta 910), reused 1165 (delta 600), pack-reused 1580168
Receiving objects: 100% (1581743/1581743), 892.72 MiB | 15.46 MiB/s, done.
Resolving deltas: 100% (1012724/1012724), done.
Updating files: 100% (7324/7324), done.

real    1m21.519s
user    0m0.000s
sys     0m0.000s
# 履歴1のclone(depth=1指定)
$ time git clone --depth 1 https://github.com/microsoft/vscode.git vscodeDepth1.git
Cloning into 'vscodeDepth1.git'...
remote: Enumerating objects: 9234, done.
remote: Counting objects: 100% (9234/9234), done.
remote: Compressing objects: 100% (7790/7790), done.
remote: Total 9234 (delta 1335), reused 4296 (delta 717), pack-reused 0
Receiving objects: 100% (9234/9234), 19.31 MiB | 15.13 MiB/s, done.
Resolving deltas: 100% (1335/1335), done.
Updating files: 100% (7324/7324), done.

real    0m8.138s
user    0m0.000s
sys     0m0.015s

結果を表でまとめます。

clone depthClone時間.gitの容量
未指定1分21秒942 MB
1指定8秒20 MB
  • 処理時間は約10倍早くなりました。
  • リポジトリの管理フォルダである「.git」の容量は約1/47のサイズになりました。
  • 履歴数の多さにもよりますが、肥大化したリポジトリに対しては予想以上の効果を発揮します。

最後に

最新ソースを利用したビルドなどに活用できそうなgit clone –depthについて書きました。

  • git clone時にdepthを指定すると高速clone出来ます。
    ⇒ リポジトリの履歴数に依存しますが、10倍以上早くなることもあります。
  • ブランチマージは出来ません。
    ⇒ けど、再fetchして履歴を追加取得すれば可能になります。
# clone時にdepth指定
git clone --depth N <url>

# clone時にdepth指定&対象ブランチ指定
git clone --depth N -b <branchName> <url>

# clone時にdepth指定&全ブランチ指定
git clone --depth N --no-single-branch <url>

# 履歴を追加取得
git fetch --depth N

最後までごらんいただき、ありがとうございました!

コメント

Top
タイトルとURLをコピーしました