git diffの全オプション一覧

[Git](https://git-scm.com/)のサイトには[Pro Git 2nd ed. Edition](https://www.amazon.com/Pro-Git-Scott-Chacon/dp/1484200772)という本が[全文無償公開](https://git-scm.com/book/en/v2)されていて、[日本語訳も公開](https://git-scm.com/book/ja/v2)されています。
なのでGitの使い方についてはこの本を読めば概ね事足ります。
ちなみに最新版は[GitHub](https://github.com/progit)にあります。

それはいいのですが、なにげに意外なことに[リファレンス](https://git-scm.com/docs)は日本語訳が、というか英語以外の言語がないみたいです。

以下は、諸事情で`git diff --break-rewrites`について知りたかったのだけど日本語解説が一件たりとも存在しなかったので調べたついでに全オプションについて軽く調べてみたメモです。
[マニュアル](https://git-scm.com/docs/git-diff)のバージョンは[2.20.0](https://git-scm.com/docs/git-diff/2.20.0)。

# git diff

## SYNOPSIS

書式。
基本的に`git diff`、オプション、対象コミット、`--`、対象ファイル名の順に書く。

```bash
git diff [<options>] [<commit>] [--] [<path>…​]
git diff [<options>] --cached [<commit>] [--] [<path>…​]
git diff [<options>] <commit> <commit> [--] [<path>…​]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path>
```

## DESCRIPTION

### `git diff [<options>] [--] [<path>…​]`

最新インデックスから現在までの差分を表示する。
addするとインデックスが更新されるので出てこなくなる。

### `git diff [<options>] --no-index [--] <path> <path>`

Git管理外のファイルも`--no-index`を付ければ対象にできる。
付けなければGit管理下にあるファイルのみが対象となる。

### `git diff [<options>] --cached [<commit>] [--] [<path>…​]`

最新コミットから最新インデックスまでの差分を表示する。
要するに最後のaddまでの差分。addした後の変更は出てこない。
`--staged`も同じ。

### `git diff [<options>] <commit> [--] [<path>…​]`

現在のブランチ(HEAD)と指定のコミットとの差分を比較する。

### `git diff [<options>] <commit> <commit> [--] [<path>…​]`

指定のふたつのコミットの差分を比較する。
片方を省略するとHEADを指定したものとなる(上と同じ)。

### `git diff [<options>] <commit>..<commit> [--] [<path>…​]`

スペース区切りと同じ。
片方省略もできる。

### `git diff [<options>] <commit>...<commit> [--] [<path>…​]`

指定のふたつのコミットについて、共通の祖先まで遡ってそこから後者への差分を比較する。
言葉だとわかりにくいが、画像を見れば一発だろう。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/26088/fdb12165-5dc0-e910-f919-302a81400a9d.png)
画像は[What are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges?](https://stackoverflow.com/questions/7251477/what-are-the-differences-between-double-dot-and-triple-dot-in-git-dif)より拝借。

### `git diff [<options>] <blob> <blob>`

コミットではなくBLOBオブジェクト同士の差分を比較する。


## オプション一覧

### -p
### -u
### --patch

パッチを作成する。デフォルトの動作。

### -s
### --no-patch

差分を標準出力に出さないようにする。
`git show`などと一緒に使うとよいが、`git diff`に使うと何も出ない。

### -U\<n\>
### --unified=\<n\>

変更された行の前後に出力する、変更されていない行の行数を変更する。
デフォルト3。
0にすると変更された行しか出さない。

### --raw

diffを[Rawフォーマット](https://git-scm.com/docs/diff-format#_raw_output_format)で出力する。
RawフォーマットはGitの内部形式らしい。

### --patch-with-raw

`-p --raw`と同じ。
なのだが、`-p --raw`より長い。

### --indent-heuristic

意図しているだろう感じで差分がうまく出るよう[判定を改善する](https://qiita.com/knsh14/items/72bfbfbe5fa0ab1cf584)。
デフォルトでオン。

### --no-indent-heuristic

`--indent-heuristic`を使わない。

### --minimal

できるだけ差分が少なくなるように比較する。
そのぶん処理に時間がかかる。

### --patience

[patience diffアルゴリズム](https://qiita.com/takaakikasai/items/3d4f8a4867364a46dfa3)を使って差分を生成する。

### --histogram

[histogram diffアルゴリズム](https://qiita.com/takaakikasai/items/3d4f8a4867364a46dfa3)を使って差分を生成する。

### --anchored=\<text\>

[anchored diffアルゴリズム](https://stackoverflow.com/questions/10066129/is-there-a-diff-like-algorithm-that-handles-moving-block-of-lines/47914789#47914789)を使って差分を生成する。
ということらしいのだが[結果](https://github.com/git/git/blob/2477ab2ea8651920a9909f6d05b15ad9004a6c64/t/t4065-diff-anchored.sh)を見てもよくわからない。

### --diff-algorithm={patience|minimal|histogram|myers}

任意のアルゴリズムを使って差分を生成する。
値を指定しない場合は`myers`が使われる。
値を`--diff-algorithm=default`とすると、設定ファイルに書かれている`diff.algorithm`が使われる。

### --stat[=\<width\>[,\<name-width\>[,\<count\>]]]

diffstat形式で出力する。diffstatは↓のような形式。

```git
  path/to/hoge,html     | 5000 +++--
  path/to/fuga,html     | 1234 -------
```

カンマ区切りで3つまで指定可能な引数で出力範囲を指定できる。
第1引数widthは全体の横幅。
第2引数name-widthはそのうちファイル名部分の横幅。
第3引数countは行数。指定行数を超えるとそれ以降は省略される。

### --stat-width=\<width\>
### --stat-name-width=\<name-width\>
### --stat-count=\<count\>

↑の`--stat`をそれぞれ個別に設定する。

### --compact-summary

diffstat形式に、ファイル作成・削除などのサマリを追加表示する。
new、gone、`+l`(シンボリックリンク)、`+x`(実行権限追加)など。
表示内容はstatのファイル名とグラフの間に出力される。

### --numstat

statと似ているがより省力で、追加行数、削除行数、ファイルパスだけを出力する。

```git
100 50 path/to/hoge,html
```

### --shortstat

statの最後の行、変更されたファイル数、追加行数、削除行数の合計だけを出力する。

```
999 files changed, 765 insertions(+), 573 deletions(-)
```

### --dirstat[=\<param1,param2,…​>]

ファイルの差分がどのディレクトリに多いかをパーセンテージで表示する。
ディレクトリ内のファイルが変更された割合ではない。

パラメータをカンマ区切りで追加することで動作を変更できる。例：`git diff --dirstat=files,10,cumulative`
`changes`はコードの移動はカウントせず、追加削除された行のみを計算する。
`lines`は行数でカウントする。通常のカウント。
`files`は変更されたファイル数をカウントする。中身は見ない。
`cumulative`はサブディレクトリも集計に入れる。合計は100%を超える。
数値は足切り。それ以下のディレクトリは親にまとめられる。

### --summary

ファイル追加削除、権限変更など拡張ヘッダ情報のみを表示する。

### --patch-with-stat

`-p --stat`と同じ。
`-p --stat`より長い。

### -z

`--name-only`や`--numstat`などと一緒に使うと、区切りが改行ではなくNULになる。
`--stat`などには効かない。

### --name-only

変更されたファイル名のみを表示する。

### --name-status

変更されたファイル名とステータスを表示する。

### --submodule[=\<format\>]

サブモジュールのdiffの表示形式を指定する。
`short`はサブモジュール内のcommitは最初と最後しか表示しない。
`log`はサブモジュール内のcommitを全て一覧表示する。
`diff`は普通にdiffを表示する。

### --color[=\<when\>]

カラー表示をどうするか指定する。
デフォルト設定は`color.ui`および`color.diff`で変更できる。

`always`はdiffをカラー表示する。
`never`は必ず白黒表示する。
`auto`はよくわからない。

### --no-color

`--color=never`と同じ。

### --color-moved[=\<mode\>]

移動したコードの色をどうするか指定する。
指定可能な値は`no`、`default`、`zebra`、`plain`、`blocks`、`dimmed-zebra`。

### --color-moved-ws=\<modes\>

`--color-moved`を検出する際に空白を取り扱う方法を指定する。
デフォルト設定は`diff.colorMovedWS`で変更できる。

`ignore-space-at-eol`は改行を無視する。
`ignore-space-change`はスペースの量の変化を無視する。スペース数0→1や1→0は検出するが1→10などは無視。
`ignore-all-space`はスペースの変化を完全に無視する。
`allow-indentation-change`は、スペースの変化量が全て同じブロックをグループ化する。

### --word-diff[=\<mode\>]

行単位ではなくワード単位でdiffを表示する。

`color`は色だけで表示する。コピペすると区切りがわからなくなる。
`plain`は追加を`{+ +}`で、削除を`[- -]`で括って表示する。中のテキストをエスケープしないので、同じ文字が入っていると区切りがわからなくなる。
`porcelain`は区切りを改行で表す。元々の改行は~で表す。正直わかりにくい。
`none`は何もしない、未指定と同じ。

### --word-diff-regex=\<regex\>

ワード単位でdiffを表示する際のワードの区切りを正規表現で指定する。

### --color-words[=\<regex\>]

`--word-diff=color -word-diff-regex`と同じ。

### --no-renames

ファイル名を変更しただけのファイルは検出しない。

### --check

スペースの次にタブ、および末尾スペースがあったときに警告メッセージを出す。
動作は`core.whitespace`で変更できる。

### --ws-error-highlight=\<kind\>

行末の空白をエラー表示するか否か。引数は,区切りで複数指定可能。
`old`は変更前をエラーとして表示する。
`new`は変更後をエラーとして表示する。
`all`は`old,new,context`に同じ。
表示色は`color.diff.whitespace`で設定する。

### --full-index

commitハッシュを省略形ではなくフル表示する。

### --binary

`--full-index`に加え、`git apply`で使えるバイナリのdiffも出力する。
と書いてあるのだが手元では`--full-index`の効果はなかった。

### --abbrev[=\<n\>]

`diff --raw`などに出力するハッシュの桁数を指定する。


### -B[\<n\>][/\<m\>]
### --break-rewrites[=[\<n\>][/\<m\>]]

diffを書き換えではなく、削除と挿入のペアとして表す。
引数を`-B/70%`とか`-B100%/0%`のように渡すことで、ファイルが編集ではなく完全な書き換えと判断する基準を変更することができる。
となっているみたいなのだが正直よくわからなかった。

### -M[\<n\>]
### --find-renames[=\<n\>]

リネームを検出する。
`-M90%`とすると、中身の90%以上が同じファイルは削除+追加ではなく名前変更とみなす。
デフォルトは50%。

### -C[\<n\>]
### --find-copies[=\<n\>]

コピーを検出する。
オプションの指定方法はリネームと同じ。
コピー元の候補になるのは、中身が変更されたファイルのみ。

### --find-copies-harder

`--find-copies`と同じだが、全てのファイルをコピー元の候補として調べる。
そのためとても重い。

### -D
### --irreversible-delete

削除されたファイルは差分を表示しない。

### -l\<num\>

`-M`および`-C`を使用した際、この制限を超えたら処理を打ち切る。
理由としてはそれらの処理時間が`O(n^2)`オーダーであるため。

### --diff-filter=[(A|C|D|M|R|T|U|X|B)…​[*]]

diffの出力をフィルタリングする。
`A`は追加されたファイルのみ、`D`は削除されたファイルのみ、`C`はコピーされたファイルのみ、`R`はリネームされたファイルのみ、`M`は変更されたファイルのみ。
`TUXB`はサブモジュールなど。
複数のオプションを`--diff-filter=ACDM`のように指定可能。
`*`を入れると、該当の差分がないときは何も表示せず、該当の差分があれば全ての差分を表示する。

小文字にすると逆になる。
`--diff-filter=a`であれば追加された以外の変更があったファイルを全て検出する。

### -S\<string\>

差分で引数の文字の出現回数が変更されたファイルを検出する。
`-f"hoge"`とすると、`hoge`の出現回数が変わったファイルを差分出力する。
100行目で`hoge`を追加し、200行目から削除したような場合は出力されない。

### -G\<regex\>

差分で引数の文字が出現したファイルを検出する。
文字列には正規表現を使用可能。
100行目で`hoge`を追加し、200行目から削除した場合でも出力される。

### --find-object=\<object-id\>

指定のオブジェクトの出現回数が変更されたファイルを検出する。
使い方は`-S`と同じ。

### --pickaxe-all

`-S`と`-G`において、ひとつでも変更が見つかったら全ファイルの差分を表示する。

### --pickaxe-regex

`-S`において正規表現を使えるようになる。

### -O\<orderfile\>

diffの出力ファイルの順番を、引数のファイルの設定に変更する。
ファイルの書式は[fnmatch](https://linuxjm.osdn.jp/html/LDP_man-pages/man3/fnmatch.3.html)で`.gitignore`と同じ。
引っかかった上から順に表示するとなっているのだが、手元ではどうやっても順番が変わらなかった。

### -R

`diff`の元ブランチと先ブランチを入れ替える。
つまり`diff AAAAAA BBBBBB`と`diff -R BBBBBB AAAAAA`は同じ。

### --relative[=\<path\>]

`--relative`だけだと、サブディレクトリからdiffを実行した際にカレントディレクトリ以下のファイルしか見ない。
`--relative="foo/bar/"`とすると、`foo/bar/`ディレクトリで`diff --relative`を実行したかのような出力になる。
サブディレクトリから実行する場合でも、パスの指定はgitルートからの指定になる。

### -a
### --text

全てのファイルをテキストファイルとみなして扱う。

### --ignore-cr-at-eol

[改行の前にあるCR](https://qiita.com/tomoki1207/items/81688fd6406436ac4dfb)を無視する。

### --ignore-space-at-eol

[改行の前にあるスペース](https://qiita.com/bremen/items/8a056b87c9e481e07e57)を無視する。

### -b
### --ignore-space-change

スペースの個数だけの変更は無視する。
0から1になった、1から0になった場合は無視しない。
`function`→`func tion`は無視しない。

### -w
### --ignore-all-space

0から1を含め、あらゆるスペースの変更を無視する。
`function`→`func tion`でも無視される。

### --ignore-blank-lines

空行のみの追加削除を無視する。
空行以外の変更があった場合は無視しない。

### --inter-hunk-context=\<lines\>

1ファイルに変更箇所が複数ある場合、デフォルトでは8行くらい離れているとdiff出力が別に分かれる。
この数値を大きくすると、離れた行もひとつの変更とみなす。

### -W
### --function-context

変更があったファイルは全てを表示する。

### --exit-code

差分があれば終了ステータス1、なければ終了ステータス0で終了する。

### --quiet

標準出力しない。`--exit-code`を含む。

### --ext-diff

外部diffヘルパーを使用する。
ということらしいが実際は`git config`等で指定が必要なので、単に↓と揃えただけと思われる。

### --no-ext-diff

外部diffヘルパーを使用しない。
デフォルトで外部diffヘルパーを使っている場合にそれをキャンセルする。

### --textconv
### --no-textconv

バイナリファイルの[テキスト変換フィルタ](https://git-scm.com/docs/gitattributes#_performing_text_diffs_of_binary_files)を指定している場合に、それを使って差分を表示する、もしくは使用しないでバイナリのまま比較する。

### --ignore-submodules[=\<when\>]

サブモジュールへの変更をどうするか。
`none`はサブモジュールの変更を全て取得する。
`untracked`は、変更は追跡する、新規ファイルは追跡しない。
`dirty`はサブモジュールで管理されているファイルは無視され、親プロジェクトで管理されているファイルは追跡する。
`all`はサブモジュール内の変更は全て無視する。
デフォルトは`all`。1.7.0までは`dirty`。

### --src-prefix=\<prefix\>

変更元ファイルのプレフィックスを`a/`ではなく指定した値にする。

### --dst-prefix=\<prefix\>

変更後ファイルのプレフィックスを`b/`ではなく指定した値にする。

### --no-prefix

両方のファイルからプレフィックスを表示しない。

### --line-prefix=\<prefix\>

出力の全行にこのプレフィックスを表示する。

### --ita-invisible-in-index
### --ita-visible-in-index

`git add -N`で追加したファイルは、`git diff`では登録済みの空ファイルとして、`git diff --cached`では未登録のファイルとして表示される。
`--ita-invisible-in-index`オプションを入れると`git diff`では未登録の新規ファイルとして表示し、`git diff --cached`では何も出てこない。
`--ita-visible-in-index`は未指定と同じ。

### -1 --base
### -2 --ours
### -3 --theirs

`merge`時のコンフリクトなど、3状態を比較する際に使用する。

### -o

マージされていないエントリについては出力を省略して、単に`Unmerged`とだけ出す。

### \<path\>…

パスを与えると、そのディレクトリ以下のファイルに対してのみdiffを実行する。


# 感想

なんだこりゃ。

何も考えず節操なく付け加えていった結果にしか見えない、

指定しても出力が変わらなくて何を意味するのか全くわからないオプションとかあって、少し整理したほうがいい気がする。