Shallow cloneとは
Gitには、shallow cloneという便利な機能があります。Shallow cloneを行うことで、最新のコミット履歴のみを取得する代わりに高速にcloneを行うことができます。
古いコミット履歴を取得しないという特性から、これは長い歴史をもつGitリポジトリに対して特に効果があります。
$ git clone --depth 1 https://github.com/ruby/ruby Cloning into 'ruby'... remote: Enumerating objects: 9894, done. remote: Counting objects: 100% (9894/9894), done. remote: Compressing objects: 100% (8679/8679), done. remote: Total 9894 (delta 954), reused 3988 (delta 802), pack-reused 0 Receiving objects: 100% (9894/9894), 13.64 MiB | 2.48 MiB/s, done. Resolving deltas: 100% (954/954), done. $ cd ruby/ $ git log --oneline | wc -l 1
Shallow cloneであったとしてもデフォルトブランチに存在するファイルはcloneされてくるため、履歴を見る必要がない操作は問題なく行うことができます。
たとえばgit grep
や、git commit
, git push
などが行なえます。またファイルの編集も行えます。
ですが、当然ながらgit log
やgit blame
などのコマンドは、手元にcloneしてあるコミットに対してのみ有効です。
そのため、たとえば「ライブラリのコードを手元で追いたいためにshallow cloneした」といったケースでは、git grep
などでコードを追っているうちは問題がありませんが、過去の履歴までさかのぼってコードを追いたくなった場合に行き詰まってしまいます。
Unshallow
そこでunshallowという機能が役に立ちます。
Shallow cloneしたリポジトリ内でgit fetch --unshallow
を実行すると、そのリポジトリにフェッチされていない全ての履歴をフェッチすることができます。
つまりshallow cloneしたリポジトリであっても、git fetch --unshallow
を実行することで過去の履歴も追うことが可能となります。
問題点
当然のことながら、git fetch --unshallow
コマンドはgit clone
時に高速化した分の時間がかかります。
そのため「過去の履歴も調査したい!」と思ってから実際に調査するまでには、若干の時間がかかってしまうことになります。不便ですね。
解決策
Shallow cloneによって高速にリポジトリをcloneしたい、でも過去の履歴を追う時に待ちたくはない。
この要望を叶えるには、shallow cloneをした直後にバックグラウンドでgit fetch --unshallow
を実行すると解決できそうですね。
これによってデフォルトブランチの先頭にあるファイルは高速にcloneしつつ、非同期的に全ての履歴を取得できます。
今回はこの機能をget
というツールに実装しました。
このツールはghq get
とgo get
のラッパーコマンドです。
とりあえずはghq get
の代わりにget ghq
と打つと動く、と考えておくと良いでしょう。
get
についてより詳しく知りたい方は、READMEやリリース時のブログをご覧ください。
Install
まずはget
をインストールします。
$ go get github.com/pocke/get
Usage
get
には-shallow
と-unshallow
の2つのオプションがあります。
-shallow
オプションをつけると、リポジトリをshallow cloneします。
そして-unshallow
オプションをつけると、shallow cloneが終わった直後にそのリポジトリでgit fetch --unshallow
を実行します。
例を見てみましょう。
# リポジトリがshallow cloneされた後、バックグラウンドでgit fetch --unshallowが実行される。 $ get ghq -shallow -unshallow https://github.com/ruby/ruby
便利ですね。ですが、少しタイプ数が多いです。
Shallow cloneしてunshallowする挙動は便利なので、これをデフォルトにしてしまうと便利そうです。
そのために設定ファイルを書きましょう。以下の内容を~/.config/get/args
として保存します。1
-shallow -unshallow
すると、なにもオプションをつけなくてもshallow cloneとunshallowが行われるようになります。
# 特に何も引数を渡さなくても、shallow cloneしてunshallowする $ get ghq https://github.com/ruby/ruby
便利ですね。
まとめ
Gitのshallow cloneとunshallowの紹介、そしてそれを便利に使う実装であるpocke/getを紹介しました。 この記事を機にpocke/getを使っていただけると嬉しいです。