git diff を徹底攻略!よく使うオプションまとめ

最終更新:2021-05-10 by Joe

Gitにおいて、「git diff」はブランチ管理に必須コマンドとなっており、最もよく使うコマンドのひとつです。ファイルの比較・管理に始まる、git diff のよく使うオプションを覚え書きしました。

これであなたも git diff マスターに、ぐんと近づけると思います。

git diff の基本動作と、主要なオプション

まずはgit diffの基本の概念ですが、「git diff」の基本動作は「作業ツリーに行われた変更の表示」です。

そして、引数に「比較元」を指定できるのですが、もし比較元を指定しない場合は、デフォルトで、「インデックス」を比較元とし、 [インデックス] → [作業ツリー] と比較した際の差分を表示する事になります。

この基本的な動作仕様の認識が曖昧なまま使っている方も、少なくないのではないでしょうか。下記、最も主要な git diff の利用ケースを列挙します。

インデックスとの差分を見る

最も基本的な比較です。インデックスに対して作業ツリーで行った変更を見ますので、まだgit addしていない変更内容は、このコマンドで簡単にチェックできます。

// [インデックス] → [作業ツリー] の差分を見る
git diff

最新のコミットとの差分を見る

「HEAD」は現在のブランチの先頭のコミットへの参照です。git diff の比較元に、コミットを指定することで、[そのコミット] → [作業ツリー] の差分を表示しますが、ここで「HEAD」と参照を指定すれば、当然、現在作業中のブランチの先頭(すなわち最新コミット)を間接的に指定する事になります。

// [最新コミット] → [作業ツリー] の差分を見る
git diff HEAD

指定したコミットとの差分を見る

もちろん比較元の指定で、上述のような「HEAD」のような参照でなく、特定のコミットの識別子(SHA-1)を直接指定することで、[比較元] → [作業ツリー] の比較を行います。

// <commit> → [作業ツリー] の差分を見る
git diff <commit>

インデックスとHEADの差分を見る

冒頭で、git diff の基本は「作業ツリー」に行われた変更を表示する、と言及しましたが、この動作を下記の「--cached」オプションを利用する事で、「インデックス(ステージ領域)への変更を見る」ようになます。

こちらは、git commit を行うの直前に「あれ?結局何を add したんだっけな〜」と確認するために非常によく使うコマンドです。ぜひ覚えてたくさん利用しましょう。

--cached 利用時は、引数で比較元を指定しなかった場合、デフォルトでHEADが比較元になります。

// [最新のコミット] → [インデックス] を比較する
git diff --cached
git diff --cached HEAD // 同義

git diff の比較対象の違いについて

上記で紹介した3つの比較です。下記の3種類は、git diff でもっともよく利用するコマンドといってよいでしょう。

やりたい事 git diffコマンド
インデックス → 作業ツリー git diff
HEAD → 作業ツリーの比較 git diff HEAD
HEAD → インデックス git diff --cached

さて、これらの違いは混乱しやすいので、図を使って少し詳しく見ていきます。

「diff」と「diff --cached」の比較対象の違い

さて、おさらいですが、

  • 通常は比較元(デフォルトでインデックス)から作業ツリーへの差分
  • --cachedで比較下(デフォルトでHEAD)からインデックスへの差分

を見るように動作します。図にすると以下のようなイメージです。

git diff の基本動作

HEADは「作業中ブランチの先頭コミット」を指しますので、現在のコミットを作ろうとしている時、作業ツリーとインデックスの変更状況について分を調べたい時はもっぱら「git diff」「git diff --cached」「git diff HEAD」のいずれかを使うことになると思います。

インデックスと、コミットの関係

「インデックス」は「ステージ領域」とも呼ばれますが、この概念が Git 特有なので、入門者は非常に混乱しやい点だと思います。こちらについても少しまとめておきます。

まずは「インデックス」と「作業ツリー」の概念と、git add とgit commitの関係についてです。

「作業ツリー」は単純なファイルシステム上のファイルですが「インデックス」はGitが管理するバイナリファイルです。(.gitディレクトリ内にあるindexというファイルです。)

インデックスは将来的に(commit されれば)、正式なコミットになります。あえて図にすると、このようなイメージです。

上図で、作業ツリーの近くで汗をかいてがんばっているのは、もちろんあなたです。いつもお疲れ様です。

git diff のよく使うオプション

使用頻度はそれほどでもないですが、非常に便利な git diff のオプションをご紹介します。

ファイル名だけを表示する

差分が生じたファイルの、ファイル名の一覧を表示します。比較元(引数)は自由に指定できます。

// ファイル名だけを比較する
git diff --name-only

比較するファイルを限定する

// 比較するファイルを限定する
git diff <コミット名> <コミット名> ―― <ファイル名>

「ファイル名」と書きましたが、実際は「パス」(ディレクトリ名など)を指定して、比較する範囲を限定できます。

ついでに、似たような結果を得られるのがこちら:

// パスやファイル同士を比較する
git diff <コミット名>:<ファイル名> <コミット名>:<ファイル名>

指定する<コミット名>の代わりに、<コミット名>:<ファイル名> とすることで、範囲を限定した参照を指定することができます。これを利用して、git diff においても、比較対象を限定するというケースですね。

ご参考まで、こちらはgit object の指定方法に関する参考文献です

特定のコミット間を比較する

さて、git diff では、比較元だけでなく、比較先を指定することもできます。これにより2種類のコミットのコミット間の比較を行うこともできます。

// コミット同士を比較する
git diff [比較元のコミット] [比較先のコミット]

この場合、比較元 → 比較先 でなにが変更されたのかが、表示されます。(右から左に時系列がながれます)コミットの指定はコミットのID(SHA-1)、ブランチ名、HEAD(現在のブランチの先頭)など、特定識別子があれば大丈夫です。

直前のコミットの内容を表示

また、例えば、HEAD^など、「^」を使って1個前のブランチを比較するのはよく使います。こんな感じです。

// HEADの一個前 から HEADへの変化を表示
git diff HEAD^ HEAD

実際は、git show でよく似た効果が得られます。

// HEADのコミット内容を表示
git diff show

// 同義
git diff show HEAD

上記は、HEADで指定されるコミットが、マージコミット(git merge から生成されたコマンド)でない事に注意して下さいね、git showの動作が異なってしまいます。git show の動作はまた別の機会に深掘りしましょう。

リモートブランチとローカルブランチの差分を比較

「特定のコミット同士の比較」の応用編です。リモートブランチからmasterをpull する前に「どのくらい先にすすんじゃったんだろ?」なんて、事前に調べたい時に使います。

git pull は、いうなれば「git fetch & git merge」ですので、いきなり git pull を実行すると、いきなりローカルブランチにマージがかかってしまいます。

これを事前にdiffで差分を確認します。イメージしやすいように、masterブランチの例で書くと・・・、

// リモートを取ってきて・・
git fetch origin master

// [ローカル] → [リモート追跡]の差分を見る
git diff master origin/master

git fetch、git merge の振る舞いに関して、もやっとしている人は、ぜひこちらの記事を御覧ください:

スペースを無視する

上記までは、オプションによる比較対象の設定でしたが、ここからは、表示の出力方法における設定のオプションです。

// ファイル内のスペースの数の違いを無視する
git diff -b
git diff --ignore-space-changes

// ファイル内のスペースを完全に無視する
git diff -w
git diff --ignore-all-space

スペース(whitespace)だけの違いを、変更とみなさず、無視します。整形した行は表示しないでほしい時、ありますね。

前者の「b」は、行の末尾の空白と、1つ以上のスペースが連続しているとき、数の違いが発生して無視します。一方で、後者の「w」は、あらゆるスペースの有無と、スペースの数の差分を無視します。

w はスペースと言っていますが、改行コードの違い無視することもできます。

よく似ていますが、上記の仕様を覚えておけば、状況によって使い分けられそうですね。

文字レベルで違いを表示する

// 差分を文字レベルで表示する
git diff --word-diff

// 差分を文字レベルで表示する。色と+、ーだけで、差分を表現する
git diff --word-diff=color

// git diff HEAD --word-diff と同じ効果
git diff --color-words

git diff は、通常は行の差分を表示するのですが、文字レベルで違いを表示してくれます。これは細かい変更がある時便利です。

後者は「--word-diff=color」とモードしていをした時と同じです。文字の色が変わるだけになるので、こちらのほうが差分が見やすいです。

--word-diff=<モード> のオプションについて、利用可能なモードを抜粋しておきます:

word-diff のモード一覧

color
色だけを使って差分をハイライトする。

plain (デフォルト)
単語の差分を、[-removed-]と[+added+]を使って表示する。デリミタが入力に発生してもエスケープしない。出力が曖昧になることがある

porcelain
単語の違いを新しい1行を使って表示する。(通常は行内で差分を表現するが、必ず1行でadd, removedを表現する、porcelainは、結構読みにくいです・・。)

none
--word-diffを.gitconfigなどで強制している際に、word-diffをオフにするときに使う。

git diff --word-diff=plain の例

git diff word-diff=plain

git diff --word-diff=color の例

git diff word-diff=color

変更が多く細かくなると、後者のほうが見やすい、かもしれませんね。

git diff の関連リンク

最後に git diff の参考リンクです。だいたい公式マニュアルが最強です。

また、基本的な設定ですが、git diff に色をつけるgitconfig設定に関してです。


さて、git diff に関しては、以上です。git diff は、非常によく利用するコマンドなので、正確に理解しておくとハッピーになれると思います。

それでは、楽しい Git ライフを。