忘れやすい人のための git diff チートシート

`git diff` は色んな場面で本当によく使うんですが、できることが多いだけに全然覚えられずに毎回調べてしまいます。
なので、場面ごとに使えるコマンドを一覧でまとめてみました。

先に[ワークツリーとインデックス【Gitの基本】- サルでもわかるGit入門](http://www.backlog.jp/git-guide/intro/intro1_4.html)を読んでおくと、ここに書いてある diff について理解しやすいと思います。

## git pull する前にリモートとの変更点を見る

```bash
git diff HEAD..リモート名/ブランチ名
```

`git pull` をする前にローカルの最新コミットと pull 先のリモートリポジトリとの変更点が見たいときはこのコマンドで見れます。
ここでいうリモート名は **origin** とかそういうやつです。

## git push する前にリモートとの変更点を見る

上記のコマンドは、こんな感じで逆にもできます。

```bash
git diff リモート名/ブランチ名..HEAD
```

`..` の右側が時系列的に最新とみなされるので、この場合は `git commit` した後にリモートリポジトリとそのこれから push したい箇所を表示したい場合に使えます。

## git add する前に変更点を見る

```bash
git diff
```

`git add` する前に変更した箇所とインデックスとの変更点が見たいときはこのコマンドです。

## git add した後に変更点を見る

```bash
git diff --cached
```

`git add` した後にインデックスと最新のコミットとの変更点を見たいときは `--cached` を付けます。

`--staged` も同じ意味なのですが、直感的な命名なのでむしろこっちのほうが覚えやすいかもしれません。

## 今回コミットした変更点を見る

```bash
git diff HEAD^
```

`git commit` した後に、コミットした箇所を表示したい場合はこのコマンドで見れます。
「最新のコミット」と「最新のコミットのひとつ前」との差分ということです。

本来は `git diff HEAD^..HEAD` と書くのが正しいのですが、`..` の右側を省略すると暗示的に現在のブランチのHEADを示すことになるので、この書き方で問題ありません。

cherry-pick したときに、どんなファイルが更新されたかを調べたい時もこれで見れます。

## コミット同士を比較する

```bash
git diff 変更前のSHA..変更後のSHA
```

SHA さえ分かればそのコミット同士の変更点もこのように確認できます。
SHA は GitHub のコミット一覧で表示されているこういうやつです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/37435/fbca7788-61a3-c986-d33f-213acda08765.png" width="60%" />

## あるコミットの変更点を見る

```bash
git diff 確認したいコミットのSHA^..確認したいコミットのSHA
```

確認したいコミットの SHA だけ分かれば、`^` を使うことでそのコミットで変更されたファイルも確認できます。

## ブランチ同士を比較する

```bash
git diff ブランチA..ブランチB
```

Pull Request を送る前に、自分が作ったブランチとマスタとの変更点を見たいときなどに使います。

## ある1ファイルの変更点を見る

```bash
git diff -- 対象のファイルパス
```

`git add` する前に、ある変更したファイルに対しての変更点が見たい場合はこう書きます。
パスなので、もちろんディレクトリ単位での比較もできます。
ちなみに git が引数をファイルと推測できる場合は `--` は省略可です。

特定のファイルを別のブランチと比較したい場合はこんな感じになります。

```bash
git diff ブランチA..ブランチB -- 対象のファイルパス
```

## 別ファイル同士を比較する

```bash
git diff -- ファイルパスA ファイルパスB
```

`--` の後は常にパスとして認識されます。
で、それを2つ並べるとそのパス同士の比較になります。

## どれくらい変更したかだけを見る

```bash
git diff --stat
```

変更点をすべて表示するのではなく、ファイルごとにどれくらい変更したかを表示したい場合にこのオプションを使います。こんな感じです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/37435/1e1c6834-51e4-736d-c785-67a923ef5bd4.png" width="350" />

変更したファイルが多くて、かつ変更したらマズイファイルが含まれていないかをパッと確認したい時に有用です。

## ファイル名だけ見る

```bash
git diff --name-only
```

変更点を表示するときに、変更があったファイルのパスだけを表示してくれます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/37435/1e28f275-5875-826d-3e5a-7a1859aa3e9c.png" width="350" />

これ単体で使うというよりも、cp などの外部コマンドとかと組み合わせて変更ファイルに対して一括処理をすることが多いです。

```bash
git add -n .; git diff --name-only
```

こう書くと、いったん `git add` の dry-run した上で追加されたファイル名も含めてくれます。
`git status` と違って出力結果がファイル名だけになるので、いろいろ応用できるコマンドです。

## 改行コードや空白を無視する

```bash
git diff -w
```

改行コードの違いや、文頭・文末の空白を無視したい場合は `-w` を付けます。
`-b` もありますが、`-w` さえ覚えておけばほとんどのケースで問題無いです。

## 空行を無視する

```bash
git diff --ignore-blank-lines
```

`--ignore-blank-lines` オプションを付ければ空行が増減しても無視してくれます。

## 変更点の前後に表示される行数を変える

```bash
git diff -U0
```

こうすると前後の行数が消えます。逆に `-U10` とかにすれば前後10行が表示されます。

## 単語単位で比較する

```bash
git diff --color-words
```

メソッド名を変更したときなど、行単位ではなく、単語単位で比較したい場合に `--color-words` オプションを付けると見やすくなります。

[gitのdiff, status, logを極限までコンパクト化＋便利化する](http://qiita.com/yuya_presto/items/ef199e08021dea777715#2-1)

この記事にあるように `.gitattributes` と組み合わせると、言語単位での比較をしてくれて、より分かりやすくなるのでオススメです。

## Excel の中身を比較する

上記を応用すると Excel の変更点も見れます。

Mac の場合は Homebrew を用意しているので下記コマンドを、

```bash
brew tap shibukk/git-xlsx-textconv
brew install git-xlsx-textconv
```

Windows の場合は[こちらのリンク](https://github.com/shibukk/git-xlsx-textconv/releases/tag/v1.0.0)にある git-xlsx-textconv_windows_amd64.zip という zip ファイルをダウンロード・解凍して、パスの通っているフォルダに置いて下さい。

あとは差分が見たいプロジェクト直下にある `.git/config` と `.git/info/attributes` にそれぞれ下記を記述するだけで OK です。

```git:.git/config
[diff "xlsx"]
  binary = true
  textconv = git-xlsx-textconv
```

```git:.git/info/attributes
*.xlsx diff=xlsx
*.XLSX diff=xlsx
```

下記コマンドでセル単位の変更点が見れます。

```bash
git diff --color-words -- 対象のExcel
```

[こんな便利なツール](https://github.com/tokuhirom/git-xlsx-textconv)を作っていただき、@tokuhirom さん本当にありがとうございます！

## 圧縮された JavaScript ファイルを展開して比較する

[圧縮/難読化されたJavaScriptファイルのgit diffをみやすくする](http://qiita.com/castor4bit/items/782ca023e92ae6ff8e51)

これをそのまんま参考にします。
僕の場合は圧縮した json も比較する必要があったので、json もこんな感じで対象にしています。

```git:.git/info/attributes
*.min.js diff=minjs
*.json diff=minjs
```

## おまけ
Git 2.9.0 から diff が賢くなり、`compactionHeuristic` を ON にしておくと上方向に比較差分が出るようになりました。
見やすくていいですね。

```bash
git config --global diff.compactionHeuristic true
# diffコマンドのオプションに --compaction-heuristic をつけるだけでもOK
```

```diff
diff --git a/foo.rb b/foo.rb
index 64bb579..a2b5573 100644
--- a/foo.rb
+++ b/foo.rb
@@ -3,6 +3,10 @@ module Foo
   def finalize(values)

     values.each do |v|
+      v.prepare
+    end
+
+    values.each do |v|
       v.finalize
     end
 end
```

↑これが、↓こうなります。

```diff
diff --git a/foo.rb b/foo.rb
index 64bb579..a2b5573 100644
--- a/foo.rb
+++ b/foo.rb
@@ -2,6 +2,10 @@ module Foo

   def finalize(values)

+    values.each do |v|
+      v.prepare
+    end
+
     values.each do |v|
       v.finalize
     end
```

こういう diff のやり方便利だぜ！というのがありましたら、ぜひ教えてくださいmm