Gitを勉強中にgit diff
(オプション無し)の使い方について疑問に思ったことをまとめます。
それはgit diff
は何と何を比較するのか?ということです。
いくつか参考サイトを見たところ次のように書いてありました。
git diff は何と何を比較するのか
自分が調べた範囲だとgitの解説サイトにはgit diff
が何と何を比較するのかについて、次の二つのパターンがありました。
サイトA
ワークツリーとステージングを比較
サイトB
ワークツリーと最新のコミットを比較
はたしてどちらが正しいのでしょうか?
結論から言うとステージングに同じファイルがあるかどうかでgit diff
の比較対象は変わるので、どちらもありえます。
git diff の動作の違い
ワークツリーとステージングに同じファイルがある場合とない場合で、git diff
の動作は次のように変わります。
ステージングに同じファイル | git diff の動作 |
---|---|
ある | ワークツリーとステージングを比較 |
ない | ワークツリーと最新のコミットを比較 |
今の内容を図で示してみます。 *1
a)ステージングに同じファイルがある場合
flowchart LR 1[(ワークツリー)] <-- git diff --> 2[(ステージング)] 2[(ステージング)] <-- git diff staged --> 3[(最新コミット)] 1[(ワークツリー)] <-- git diff HEAD --> 3[(最新コミット)]
b) ステージングに同じファイルがない場合
flowchart LR 1[(ワークツリー)] <-- git diff <br> git diff HEAD --> 3[(最新コミット)]
git diff
はgit diff HEAD
と同じ対象を比較しています。
今後の使い分け
考え方としてはgit diff
の比較元は必ずワークツリーであり、比較対象はステージングに同じファイルがあればステージング、ステージングに同じファイルがなければ最新のコミットとなります。
※git diff --staged
は比較元をステージングに変更するオプションだと考えれば覚えやすいと思います。
またワークツリーと最新コミットを比較するコマンドはgit diff HEAD
ですが、ステージングに同じファイルがない場合にはgit diff
でも同様の動作をします。そのためgit diff
の動作を把握せずにgit diff
コマンドを使用していると、git diff
の比較対象がステージングなのか最新コミットなのか分からなくなってしまう可能性があります。
そのため自分は今後次のように使い分けることで、比較対象を明らかにしようと思います。
やりたいこと | コマンド |
---|---|
ワークツリーとステージングを比較したい | git diff |
ワークツリーと最新のコミットを比較したい | git diff HEAD |
参考資料
gitの公式マニュアル*2のdiffの説明(Examples)には次のようにあります。
Various ways to check your working tree
$ git diff (1)
$ git diff --cached (2)
$ git diff HEAD (3)
Changes in the working tree not yet staged for the next commit.
Changes between the index and your last commit; what you would be committing if you run git commit without -a option.
Changes in the working tree since your last commit; what you would be committing if you run git commit -a
git diff
はワーキングツリーの変更を表示するとしか書かれていないので、
比較対象はステージングの場合もあるし、最新コミットの場合もあるということで良いのかなと思います。
今回の記事について違うよというご指摘があれば是非お願いします。
※今回使用したGitのバージョンは2.34.1です。
*1:Mermaid記法で図を作成したのですが、--を単語の中で使う方法がわからなかったので、diff --stagedがdiff stagedという表記になってしまっています。