kakakakakku blog

Weekly Tech Blog: Keep on Learning!

知っておくと便利な git clone --depth と git diff --indent-heuristic

コミット履歴が無駄に多く,黒歴史のある Git リポジトリで開発をする場合,初回の git clone が非常に遅いという問題がある.コミット数に依存せずに素早く落とせる方法を探していて,最近(今さら...!) git clone--depth オプションのことを知った.用途によっては非常に便利なので,まとめておこうと思う.

前提

現時点で公開されている最新バージョンの Git 2.12.1 を前提にしている.Git は今もまだ機能が増えているため,定期的にバージョンアップしておくと良いと思う.Mac なら brew upgrade git でサクッと最新バージョンになる.

$ git --version
git version 2.12.1

git clone --depth とは

git clone--depth オプションを使うと,指定したコミット数で刈り取ることができる.以下の例では --depth 1 で,master ブランチにある最新のコミットだけを落としている.コミット履歴が大量にある Git リポジトリでも,素早く落とすことができるため便利.

ちなみに Git のドキュメントを読むと,--depth オプションを使った git clone のことを「シャロークローン (shallow clone)」と呼んでいた.合わせて覚えておくと良さそう.

$ git clone --depth 1 git@github.com:kakakakakku/togoo.git
$ cd togoo
$ git log --oneline | cat
80ff421 Added listing column "created_at"

shallow clone をしても pull / push に制約は無かった

shallow clone をすると pull / push ができないと書いてある記事が多かったが,少なくとも Git 2.12.1 では,普通に pull / push / fetch をすることができた.ようするに --depth 1git clone して,開発をして,プルリクエストを作ることができる.

よって,最初はある程度の深さ(100 など)で shallow clone をして開発を始めて,コミット履歴が必要になったり,git blame 警察をするときになってから,過去のコミットを取得し直せば良いということになる.

追加で過去のコミットを取得する

では,過去のコミットを取得したくなったときにどうすれば良いかと言うと,git fetch--depth オプションを使って深さを指定するか,--unshallow オプションで全てを取得することになる.

# 深さを指定して取得する場合
$  git fetch --depth 5

# 全てを取得する場合
$ git fetch --unshallow

git diff --indent-heuristic とは

せっかく Git の話を書いているので,案外知られていないように思う「便利な git diff オプション」の話も書いておこうと思う.

git diff で,差分結果が微妙にズレていて気持ち悪いなと感じた人は多いのでは?例えば,以下のようなサンプルコードで再現することができる.追加したのは最初の3行なのに...!という感じでツライ.

$ git diff
--- a/hoge.rb
+++ b/hoge.rb
@@ -1,3 +1,7 @@
 [1, 2, 3].each {|i|
+  puts i
+}
+
+[1, 2, 3].each {|i|
   puts i + 1
 }

この問題を解決するために Git 2.9 で git diff --compaction-heuristic というオプションが追加されている.ただし,このオプションは不完全で,Git のデフォルト設定としては採用されなかった.そして Git 2.11 で,さらに改善された git diff --indent-heuristic というオプションが追加された.--indent-heuristic は全てのケースで改善がされているらしく,今後のバージョンで Git のデフォルト設定になる予定があると公式ブログにも書いてあった.

The new option goes under the name --indent-heuristic (and diff.indentHeuristic), and will likely become the default in a future version of Git.

github.com

--indent-heuristic オプションを使うと,以下のように意図した差分結果になる.最高!

$ git diff --indent-heuristic
--- a/hoge.rb
+++ b/hoge.rb
@@ -1,3 +1,7 @@
+[1, 2, 3].each {|i|
+  puts i
+}
+
 [1, 2, 3].each {|i|
   puts i + 1
 }

--indent-heuristic オプションをデフォルトにする

~/.gitconfig に以下の設定をすれば,git diff のデフォルト設定が --indent-heuristic になる.個人的には必須な設定!

[diff]
  indentHeuristic = true

まとめ

  • Git は定期的にバージョンアップする
  • 巨大な Git リポジトリをサクッと落とす場合は git clone --depth を使う
  • 最新バージョンの Git なら shallow clone をしても pull / push ができる
  • ~/.gitconfigdiff.indentHeuristic を有効化すれば git diff が便利になる

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com