git diffの--ignoreオプションにおけるスペース、タブ、改行の扱いを理解する

`git diff`コマンドの`--ignore`オプションを指定した場合に **どのような行を無視する（変更前後の差分として扱わない）のか** をまとめました。

以下の表は各オプションによって無視する行の違いについてまとめたものです。

オプション                                   | 行末スペース | 連続スペース | スペース | 連続空行
:-------------------------------------- | :----: | :----: | :--: | :--:
オプションなし                                 |        |        |      |
--ignore-space-at-eol                   |   無視   |        |      |
-b, --ignore-space-change               |   無視   |   無視   |      |
-w, --ignore-all-space                  |   無視   |   無視   |  無視  |
–ignore-blank-lines                     |        |        |      |  無視
--ignore-all-space --ignore-blank-lines |   無視   |   無視   |  無視  |  無視

`git diff`コマンドを使用する場合、どのようなオプションを指定するかによって **追加行数と削除行数に大きな差が生じます** 。

もし`git diff`コマンドを使用して論理LOCを算出しているのであれば、各オプションの違いについてしっかりと理解し、 **論理LOCの明確な定義を定める** ことによって生産性評価や品質評価、工数見積の精度を高めることができます。

本稿では、`sample.txt`という名前のテキストファイルにおける

- **HEAD^** : 変更前のコミット
- **HEAD** : 変更後のコミット

を例にして、各オプションの違いについて詳しく説明していきます。

以下は、変更前後におけるテキストファイルの中身です。ここで`$`は改行（LF）、`^I`はインデントを示しています。

**HEAD^** : 変更前のコミット

```
$ cat -et sample.txt
Add a space in the end of line.$
Delete a space in the end of line. $
Add a tab in the end of line.$
Delete a tab in the end of line.^I$
Add a sequence of spaces.$
Delete     a sequence of spaces.$
Add^Ia sequence tabs.$
Delete^I^I^I^I^Ia sequence tabs.$
Add some spaces.$
D e l e t e some spaces.$
Add some tabs.$
D^Ie^Il^Ie^It^Ie some tabs.$
Add a line feed between this line$
$
$
and this line.$
Delete a line feed between this line$
$
$
and this line.$
```

**HEAD** : 変更後のコミット

```
$ cat -et sample.txt
Add a space in the end of line. $
Delete a space in the end of line.$
Add a tab in the end of line.^I$
Delete a tab in the end of line.$
Add     a sequence of spaces.$
Delete a sequence of spaces.$
Add^I^I^I^I^Ia sequence tabs.$
Delete^Ia sequence tabs.$
A d d some spaces.$
Delete some spaces.$
A^Id^Id some tabs.$
Delete some tabs.$
Add a line feed between this line$
$
$
$
and this line.$
Delete a line feed between this line$
$
and this line.$
```

## オプションなし: あらゆる変更を差分として扱う

オプションを指定しなかった場合は、あらゆる変更を差分として扱います。

```
$ git diff HEAD^ HEAD
diff --git a/sample.txt b/sample.txt
index 491a2f5..71eaa57 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,20 +1,20 @@
-Add a space in the end of line.
-Delete a space in the end of line.
-Add a tab in the end of line.
-Delete a tab in the end of line.       
-Add a sequence of spaces.
-Delete     a sequence of spaces.
-Add    a sequence tabs.
-Delete                                 a sequence tabs.
-Add some spaces.
-D e l e t e some spaces.
-Add some tabs.
-D      e       l       e       t       e some tabs.
+Add a space in the end of line.
+Delete a space in the end of line.
+Add a tab in the end of line.  
+Delete a tab in the end of line.
+Add     a sequence of spaces.
+Delete a sequence of spaces.
+Add                                    a sequence tabs.
+Delete a sequence tabs.
+A d d some spaces.
+Delete some spaces.
+A      d       d some tabs.
+Delete some tabs.
 Add a line feed between this line


+
 and this line.
 Delete a line feed between this line

-
 and this line.
```

```
$ git diff --numstat HEAD^ HEAD
13      13      sample.txt
```

## --ignore-space-at-eol: 行末スペースの変更を無視する

> Ignore changes in whitespace at EOL.

`--ignore-space-at-eol`オプションを指定した場合は、以下の変更を無視します。

- 行末スペースの追加
- 行末スペースの削除
- 行末タブの追加
- 行末タブの削除

```
$ git diff --ignore-space-at-eol HEAD^ HEAD
diff --git a/sample.txt b/sample.txt
index 491a2f5..71eaa57 100644
--- a/sample.txt
+++ b/sample.txt
@@ -2,19 +2,19 @@ Add a space in the end of line.
 Delete a space in the end of line.
 Add a tab in the end of line.  
 Delete a tab in the end of line.
-Add a sequence of spaces.
-Delete     a sequence of spaces.
-Add    a sequence tabs.
-Delete                                 a sequence tabs.
-Add some spaces.
-D e l e t e some spaces.
-Add some tabs.
-D      e       l       e       t       e some tabs.
+Add     a sequence of spaces.
+Delete a sequence of spaces.
+Add                                    a sequence tabs.
+Delete a sequence tabs.
+A d d some spaces.
+Delete some spaces.
+A      d       d some tabs.
+Delete some tabs.
 Add a line feed between this line


+
 and this line.
 Delete a line feed between this line

-
 and this line.
```

```
$ git diff --ignore-space-at-eol --numstat HEAD^ HEAD
9 9 sample.txt
```

## -b, --ignore-space-change: 行末スペースと連続スペースの変更を無視する

> Ignore changes in amount of whitespace. This ignores whitespace at line end, and considers all other sequences of one or more whitespace characters to be equivalent.

`-b`または`--ignore-space-change`オプションを指定した場合は、以下の変更を無視します。

- 行末スペースの追加
- 行末スペースの削除
- 行末タブの追加
- 行末タブの削除
- **1文字以上** の連続したスペースに対するスペースの追加
- **1文字以上** の連続したスペースに対するスペースの削除
- **1文字以上** の連続したタブに対するタブの追加
- **1文字以上** の連続したタブに対するタブの削除

```
$ git diff --ignore-space-change HEAD^ HEAD
diff --git a/sample.txt b/sample.txt
index 491a2f5..71eaa57 100644
--- a/sample.txt
+++ b/sample.txt
@@ -6,15 +6,15 @@ Add a sequence of spaces.
 Delete a sequence of spaces.
 Add                                    a sequence tabs.
 Delete a sequence tabs.
-Add some spaces.
-D e l e t e some spaces.
-Add some tabs.
-D      e       l       e       t       e some tabs.
+A d d some spaces.
+Delete some spaces.
+A      d       d some tabs.
+Delete some tabs.
 Add a line feed between this line


+
 and this line.
 Delete a line feed between this line

-
 and this line.
```

```
$ git diff --ignore-space-change --numstat HEAD^ HEAD
5 5 sample.txt
```

## -w, --ignore-all-space: スペースの変更を無視する

> Ignore whitespace when comparing lines. This ignores differences even if one line has whitespace where the other line has none.

`-w`または`--ignore-all-space`オプションを指定した場合は、以下の変更を無視します。

- スペースの追加
- スペースの削除
- タブの追加
- タブの削除

```
$ git diff --ignore-all-space HEAD^ HEAD
diff --git a/sample.txt b/sample.txt
index 491a2f5..71eaa57 100644
--- a/sample.txt
+++ b/sample.txt
@@ -13,8 +13,8 @@ D     e       l       e       t       e some tabs.
 Add a line feed between this line


+
 and this line.
 Delete a line feed between this line

-
 and this line.
```

```
$ git diff --ignore-all-space --numstat HEAD^ HEAD
1 1 sample.txt
```

## --ignore-blank-lines: 連続した空行の変更を無視する

> Ignore changes whose lines are all blank.

`--ignore-blank-lines`オプションを指定した場合は、以下の変更を無視します。

- **2文字以上** の連続した空行に対する空行の追加
- **2文字以上** の連続した空行に対する空行の削除

```
$ git diff --ignore-blank-lines HEAD^ HEAD
diff --git a/sample.txt b/sample.txt
index 491a2f5..71eaa57 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,15 +1,15 @@
-Add a space in the end of line.
-Delete a space in the end of line.
-Add a tab in the end of line.
-Delete a tab in the end of line.       
-Add a sequence of spaces.
-Delete     a sequence of spaces.
-Add    a sequence tabs.
-Delete                                 a sequence tabs.
-Add some spaces.
-D e l e t e some spaces.
-Add some tabs.
-D      e       l       e       t       e some tabs.
+Add a space in the end of line.
+Delete a space in the end of line.
+Add a tab in the end of line.  
+Delete a tab in the end of line.
+Add     a sequence of spaces.
+Delete a sequence of spaces.
+Add                                    a sequence tabs.
+Delete a sequence tabs.
+A d d some spaces.
+Delete some spaces.
+A      d       d some tabs.
+Delete some tabs.
 Add a line feed between this line
```

```
$ git diff --ignore-blank-lines --numstat HEAD^ HEAD
12 12 sample.txt
```

## --ignore-all-space --ignore-blank-lines

`--ignore-all-space`と`--ignore-blank-lines`オプションを指定した場合は、以下の変更を無視します。

- スペースの追加
- スペースの削除
- タブの追加
- タブの削除
- **2文字以上** の連続した空行に対する空行の追加
- **2文字以上** の連続した空行に対する空行の削除

```

$ git diff --ignore-all-space --ignore-blank-lines HEAD^ HEAD
```

```

$ git diff --ignore-all-space --ignore-blank-lines --numstat HEAD^ HEAD
0 0 sample.txt
```

--------------------------------------------------------------------------------

[Git - git-diff Documentation](https://git-scm.com/docs/git-diff)

[![クリエイティブ・コモンズ・ライセンス](https://i.creativecommons.org/l/by/4.0/88x31.png)](http://creativecommons.org/licenses/by/4.0/)<br>
この 作品 は [クリエイティブ・コモンズ 表示 4.0 国際 ライセンス](http://creativecommons.org/licenses/by/4.0/)の下に提供されています。