はじめに
Advent Calendar用の記事です。
なにかgitネタで書くと宣言し(てしまっ)たので"ファイルの差分"というテーマにしてみました。
(gitで困ったこと、こういうのどうするの?みたいなのがあれば記事にしますと言っていたのですが、誰も声をかけてくれませんでした。みんなシャイですね。何を書こうか悩みました。)
ウォークスルー形式で進めます。
基本
この辺はさらっと流し見て構いません。
以下のようなファイルがあります。
$ git ls-files text/
text/A.txt
$ git show HEAD:./text/A.txt
Hello
Good-bye
編集して保存します。
$ vim text/A.txt # edit and save
Hello
How aer you?
Good-bye
差分を見ます。
$ git status
HEAD detached from f2a9634
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: text/A.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git diff
diff --git a/text/A.txt b/text/A.txt
index 423514f..ea8e95f 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,2 +1,3 @@
Hello
+How aer you?
Good-bye
git diff
で差分を見ます。+How aer you?
が差分です。(typoしています。)
$ git add text/A.txt
$ git diff --cached
diff --git a/text/A.txt b/text/A.txt
index 423514f..1e8e901 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,2 +1,3 @@
Hello
+How aer you?
Good-bye
add
でステージしたファイルの差分はdiff --cached
で見ます。シノニムに--staged
があります。
とりあえずコミットして、その内容を確認します。
$ git status
HEAD detached from f2a9634
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: text/A.txt
$ git commit -m "Update A.txt"
[detached HEAD 689a77d] Update A.txt
1 file changed, 1 insertion(+)
$ git log -1 -p
commit 689a77da0b2565b6a93e8dabcbd85c561de5dd49 (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 00:30:50 2020 +0900
Update A.txt
diff --git a/text/A.txt b/text/A.txt
index 423514f..1e8e901 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,2 +1,3 @@
Hello
+How aer you?
Good-bye
ここでlog
のオプションを2つ使っています。
-
--patch
-p
: コミットの差分を表示 -
-<N>
:N
個のコミットログを表示
ここではgit log -1 -p
なので、ヘッドのコミット1個分の+How aer you?
まで表示しています。
log
のオプションには差分のサマリーを表示するオプションもあります。
$ git log -1 --stat
commit 689a77da0b2565b6a93e8dabcbd85c561de5dd49 (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 00:30:50 2020 +0900
Update A.txt
text/A.txt | 1 +
1 file changed, 1 insertion(+)
-
--stat
: ファイルとその差分のサマリーを表示-
diff
でも指定可能
-
単語単位/正規表現
aer
とtypoしていたので直します。
$ vim text/A.txt # fix and save
Hello
How are you?
Good-bye
$ git diff
diff --git a/text/A.txt b/text/A.txt
index 1e8e901..ea8e95f 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,3 +1,3 @@
Hello
-How aer you?
+How are you?
Good-bye
diff
には単語単位で差分を見るオプションがあります。
$ git diff --word-diff
diff --git a/text/A.txt b/text/A.txt
index 1e8e901..ea8e95f 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,3 +1,3 @@
Hello
How [-aer-]{+are+} you?
Good-bye
[-aer-]{+are+}
の部分が単語単位の差分です。aer
が削除分、are
が追加分です。(慣れていないと読みにくいかもしれません。) --word-diff
を指定しない場合と比べれば、変更のある行内のどの部分が変更されたかが分かります。行が長い場合などに効果的です。
単語単位ではなく、正規表現にマッチした部分を表示することもできます。
$ git diff --word-diff-regex=.
diff --git a/text/A.txt b/text/A.txt
index 1e8e901..ea8e95f 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,3 +1,3 @@
Hello
How a[-e-]r{+e+} you?
Good-bye
パターンが.
なので1文字単位で差分を表示します。r
の前のe
が削除され、後にe
が追加されています。
パターンにマッチしない場合は表示上は差分が無いように見えます。
$ git diff --word-diff-regex=x
diff --git a/text/A.txt b/text/A.txt
index 1e8e901..ea8e95f 100644
--- a/text/A.txt
+++ b/text/A.txt
@@ -1,3 +1,3 @@
Hello
How are you?
Good-bye
-
--word-diff
: 単語単位で差分を表示-
--word-diff=plain
がデフォルト -
--word-diff=color
は色のみで[--]
、{++}
がつかない
-
-
--word-diff-regex=<pattern>
: 正規表現でマッチした部分を表示 - どちらも
log -p
と併せて指定可能- ex.)
git log -p --word-diff
- ex.)
使いどころ
ファイル名の変更を含むコミットの差分を見る時に有効です。
以下、雑なサンプル。
$ git ls-files java/
java/main/sample/Sample.java
java/main/sample/util/MessageManager.java
$ git show HEAD:./java/main/sample/Sample.java
package sample;
import sample.util.MessageManager;
public class Sample {
public static void main(String... args) {
MessageManager.send("hello");
MessageManager.receive(1);
MessageManager.clear();
}
}
$ git show HEAD:./java/main/sample/util/MessageManager.java
package sample.util;
public class MessageManager {
public static int send(String message) {
throw new UnsupportedOperationException("TODO: implement");
}
public static String receive(int count) {
throw new UnsupportedOperationException("TODO: implement");
}
public static int clear() {
throw new UnsupportedOperationException("TODO: implement");
}
}
MessageManager.java
をMessages.java
に変更します。(途中は省略。)
$ git add java/
$ git status
HEAD detached from a00b52c
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: java/main/sample/Sample.java
renamed: java/main/sample/util/MessageManager.java -> java/main/sample/util/Messages.java
$ git diff --cached
diff --git a/java/main/sample/Sample.java b/java/main/sample/Sample.java
index 9af1ad9..1db16a4 100644
--- a/java/main/sample/Sample.java
+++ b/java/main/sample/Sample.java
@@ -1,11 +1,11 @@
package sample;
-import sample.util.MessageManager;
+import sample.util.Messages;
public class Sample {
public static void main(String... args) {
- MessageManager.send("hello");
- MessageManager.receive(1);
- MessageManager.clear();
+ Messages.send("hello");
+ Messages.receive(1);
+ Messages.clear();
}
}
diff --git a/java/main/sample/util/MessageManager.java b/java/main/sample/util/Messages.java
similarity index 92%
rename from java/main/sample/util/MessageManager.java
rename to java/main/sample/util/Messages.java
index 014c758..79b2e77 100644
--- a/java/main/sample/util/MessageManager.java
+++ b/java/main/sample/util/Messages.java
@@ -1,6 +1,6 @@
package sample.util;
-public class MessageManager {
+public class Messages {
public static int send(String message) {
throw new UnsupportedOperationException("TODO: implement");
}
これを--word-diff-regex=.
で表示すると以下のようになります。(記事上は色がつかないのでちょっと読みにくいです。)
$ git diff --cached --word-diff-regex=.
diff --git a/java/main/sample/Sample.java b/java/main/sample/Sample.java
index 9af1ad9..1db16a4 100644
--- a/java/main/sample/Sample.java
+++ b/java/main/sample/Sample.java
@@ -1,11 +1,11 @@
package sample;
import sample.util.Message[-Manager-]{+s+};
public class Sample {
public static void main(String... args) {
Message[-Manager-]{+s+}.send("hello");
Message[-Manager-]{+s+}.receive(1);
Message[-Manager-]{+s+}.clear();
}
}
diff --git a/java/main/sample/util/MessageManager.java b/java/main/sample/util/Messages.java
similarity index 92%
rename from java/main/sample/util/MessageManager.java
rename to java/main/sample/util/Messages.java
index 014c758..79b2e77 100644
--- a/java/main/sample/util/MessageManager.java
+++ b/java/main/sample/util/Messages.java
@@ -1,6 +1,6 @@
package sample.util;
public class Message[-Manager-]{+s+} {
public static int send(String message) {
throw new UnsupportedOperationException("TODO: implement");
}
[-Manager-]{+s+}
の部分が差分になります。この例ではあまりうまみがあるようには見えませんが、量が多くなると差分が読みやすくなることがあります。
(ならないこともあります。.
を...
等に変えるなどしてちょうどいいところを探すこともあります。)
(--word-diff
ではないのは"word"の単位が自然でないから。
[-MessageManager-]{+Messages+}.send("hello");
となりそうなところが
[-MessageManager.send("hello");-]{+Messages.send("hello");+}
となります。記号が区切りにならない……。なんで?)
ファイル名変更の追跡
上のファイル名(パス)変更をコミットして履歴を見てみます。
$ git log -p java/main/sample/util/Messages.java
commit 8334bd7b68d6feae63e2335aa71e7fb3d2e9ca22 (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 02:02:02 2020 +0900
Rename file
diff --git a/java/main/sample/util/Messages.java b/java/main/sample/util/Messages.java
new file mode 100644
index 0000000..79b2e77
--- /dev/null
+++ b/java/main/sample/util/Messages.java
@@ -0,0 +1,15 @@
+package sample.util;
+
+public class Messages {
+ public static int send(String message) {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+
+ public static String receive(int count) {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+
+ public static int clear() {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+}
コミット1個分しか表示されません。コミット作成時のstatus
では
renamed: java/main/sample/util/MessageManager.java -> java/main/sample/util/Messages.java
とありましたが、
new file mode 100644
index 0000000..79b2e77
--- /dev/null
+++ b/java/main/sample/util/Messages.java
と、新規ファイルとしての履歴しかありません。
そこで--follow
オプションを使います。
$ git log -p --follow java/main/sample/util/Messages.java
commit 8334bd7b68d6feae63e2335aa71e7fb3d2e9ca22 (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 02:02:02 2020 +0900
Rename file
diff --git a/java/main/sample/util/MessageManager.java b/java/main/sample/util/Messages.java
similarity index 92%
rename from java/main/sample/util/MessageManager.java
rename to java/main/sample/util/Messages.java
index 014c758..79b2e77 100644
--- a/java/main/sample/util/MessageManager.java
+++ b/java/main/sample/util/Messages.java
@@ -1,6 +1,6 @@
package sample.util;
-public class MessageManager {
+public class Messages {
public static int send(String message) {
throw new UnsupportedOperationException("TODO: implement");
}
commit 2132e1b4e45bbd777bef2572981299306deae8f2
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 01:30:37 2020 +0900
Add java sample code
diff --git a/java/main/sample/util/MessageManager.java b/java/main/sample/util/MessageManager.java
new file mode 100644
index 0000000..014c758
--- /dev/null
+++ b/java/main/sample/util/MessageManager.java
@@ -0,0 +1,15 @@
+package sample.util;
+
+public class MessageManager {
+ public static int send(String message) {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+
+ public static String receive(int count) {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+
+ public static int clear() {
+ throw new UnsupportedOperationException("TODO: implement");
+ }
+}
これでコミット2個分の履歴が出ました。ファイル名変更に対し、オプションを指定しない場合は、ファイル名変更したコミットがファイルの最古の履歴となりますが、--follow
オプションでファイル名変更を追跡することが可能です。(-p
は必須ではありませんが、だいたいセットで使っています。)
-
--follow
: ファイル名変更を追跡- ファイル単位でのみ利用可能
- 複数ファイル指定、ディレクトリ指定はできない
ファイル名変更の追跡 - 差分の割合
ファイル名を変更した上に、その内容も変更した場合の差分と履歴を追跡するケースを紹介します。
以下のようなファイルがあります。(内容に意味はありません。)
$ git ls-files ./text/
text/A.txt
text/B.txt
$ git show HEAD:./text/B.txt
1. aaa bbb ccc
2. aaa bbb
3. bbb ccc
4. bbb aaa ccc
5. ccc aaa ddd eee
6. ddd aaa bbb aaa eee
7. aaa eee bbb
8. eee ccc ddd fff
9. eee fff aaa ccc
10. fff ccc
11. fff eee ddd bbb aaa
B.txt
をC.txt
に変更 + 内容変更をします。
$ mv ./text/B.txt ./text/C.txt
$ sed -i 's/\<aaa\>/xxx/g' text/C.txt # `sed -i ""` if mac
aaa
をxxx
に書き換えます。もはや3. ...
、8. ...
、10. ...
の行しか変更のない行はありません。
これをステージして差分を見てみます。
$ git add text/
$ git status
HEAD detached from 7556ed3
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: text/B.txt
new file: text/C.txt
$ git diff --cached
diff --git a/text/B.txt b/text/B.txt
deleted file mode 100644
index a373951..0000000
--- a/text/B.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-1. aaa bbb ccc
-2. aaa bbb
-3. bbb ccc
-4. bbb aaa ccc
-5. ccc aaa ddd eee
-6. ddd aaa bbb aaa eee
-7. aaa eee bbb
-8. eee ccc ddd fff
-9. eee fff aaa ccc
-10. fff ccc
-11. fff eee ddd bbb aaa
diff --git a/text/C.txt b/text/C.txt
new file mode 100644
index 0000000..e033c8b
--- /dev/null
+++ b/text/C.txt
@@ -0,0 +1,11 @@
+1. xxx bbb ccc
+2. xxx bbb
+3. bbb ccc
+4. bbb xxx ccc
+5. ccc xxx ddd eee
+6. ddd xxx bbb xxx eee
+7. xxx eee bbb
+8. eee ccc ddd fff
+9. eee fff xxx ccc
+10. fff ccc
+11. fff eee ddd bbb xxx
操作としてはファイル名変更 + 内容変更ですが、git上ではB.txt
の削除とC.txt
の追加と認識されました。gitは削除と追加とのペアがあると、それをファイル名の変更とみなすか、そのまま削除 & 追加とみなすかの割合があります。デフォルトで内容の類似が50%以上ならファイル名変更、そうでなければ削除 & 追加とみなします。
そこで類似の割合を下げてみます。
$ git diff --cached -M20%
diff --git a/text/B.txt b/text/C.txt
similarity index 22%
rename from text/B.txt
rename to text/C.txt
index a373951..e033c8b 100644
--- a/text/B.txt
+++ b/text/C.txt
@@ -1,11 +1,11 @@
-1. aaa bbb ccc
-2. aaa bbb
+1. xxx bbb ccc
+2. xxx bbb
3. bbb ccc
-4. bbb aaa ccc
-5. ccc aaa ddd eee
-6. ddd aaa bbb aaa eee
-7. aaa eee bbb
+4. bbb xxx ccc
+5. ccc xxx ddd eee
+6. ddd xxx bbb xxx eee
+7. xxx eee bbb
8. eee ccc ddd fff
-9. eee fff aaa ccc
+9. eee fff xxx ccc
10. fff ccc
-11. fff eee ddd bbb aaa
+11. fff eee ddd bbb xxx
3. ...
、8. ...
、10. ...
の行が変更なしとして差分を表示できました。このオプションはstatus
、log
でも使えます。
$ git status -M2 # as same as `-M20%`
HEAD detached from 7556ed3
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: text/B.txt -> text/C.txt
$ git commit -m "Rename B.txt to C.txt, and change content"
[detached HEAD 7556ed3] Rename B.txt to C.txt, and change content
2 files changed, 11 insertions(+), 11 deletions(-)
delete mode 100644 text/B.txt
create mode 100644 text/C.txt
$ git log -1 -p -M2
commit 7556ed3467875734b03e6eacc1cca944eec33d7b (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:22:29 2020 +0900
Rename B.txt to C.txt, and change content
diff --git a/text/B.txt b/text/C.txt
similarity index 22%
rename from text/B.txt
rename to text/C.txt
index a373951..e033c8b 100644
--- a/text/B.txt
+++ b/text/C.txt
@@ -1,11 +1,11 @@
-1. aaa bbb ccc
-2. aaa bbb
+1. xxx bbb ccc
+2. xxx bbb
3. bbb ccc
-4. bbb aaa ccc
-5. ccc aaa ddd eee
-6. ddd aaa bbb aaa eee
-7. aaa eee bbb
+4. bbb xxx ccc
+5. ccc xxx ddd eee
+6. ddd xxx bbb xxx eee
+7. xxx eee bbb
8. eee ccc ddd fff
-9. eee fff aaa ccc
+9. eee fff xxx ccc
10. fff ccc
-11. fff eee ddd bbb aaa
+11. fff eee ddd bbb xxx
--word-diff
と併せます。
$ git log -1 -p --word-diff -M2
commit 7556ed3467875734b03e6eacc1cca944eec33d7b (HEAD)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:22:29 2020 +0900
Rename B.txt to C.txt, and change content
diff --git a/text/B.txt b/text/C.txt
similarity index 22%
rename from text/B.txt
rename to text/C.txt
index a373951..e033c8b 100644
--- a/text/B.txt
+++ b/text/C.txt
@@ -1,11 +1,11 @@
1. [-aaa-]{+xxx+} bbb ccc
2. [-aaa-]{+xxx+} bbb
3. bbb ccc
4. bbb [-aaa-]{+xxx+} ccc
5. ccc [-aaa-]{+xxx+} ddd eee
6. ddd [-aaa-]{+xxx+} bbb [-aaa-]{+xxx+} eee
7. [-aaa-]{+xxx+} eee bbb
8. eee ccc ddd fff
9. eee fff [-aaa-]{+xxx+} ccc
10. fff ccc
11. fff eee ddd bbb [-aaa-]{+xxx+}
-
--find-renames=<rate>
-M<rate>
: ファイル名変更を追跡する類似の割合-
diff
、status
、log -p
、log --stat
で指定可能 -
-M20%
=-M2
- デフォルトは50% (
git help diff
参照) - あまり小さい割合を指定するとまったく関係ないファイルどうしが
rename
として表示されることがある1
-
コミット間の差分
単純な差分
これまでの履歴が以下の通りあります。
$ git log --oneline
7556ed3 (HEAD) Rename B.txt to C.txt, and change content
7b8a7c7 Add B.txt
aa343a0 Rename file
...
7b8a7c7
でB.txt
の追加、7556ed3
でC.txt
にファイル名を変更しました。git log -p
ではその内容をコミットごとに表示できました。
次はaa343a0
から7556ed3
までの差分をまとめて表示します。
$ git diff aa343a0 7556ed3
diff --git a/text/C.txt b/text/C.txt
new file mode 100644
index 0000000..e033c8b
--- /dev/null
+++ b/text/C.txt
@@ -0,0 +1,11 @@
+1. xxx bbb ccc
+2. xxx bbb
+3. bbb ccc
+4. bbb xxx ccc
+5. ccc xxx ddd eee
+6. ddd xxx bbb xxx eee
+7. xxx eee bbb
+8. eee ccc ddd fff
+9. eee fff xxx ccc
+10. fff ccc
+11. fff eee ddd bbb xxx
途中のB.txt
の履歴は出ません。単純に2つのコミットの間にある差分のみが表示されます。なのでC.txt
が新規ファイルとして追加、という差分になっています。
ブランチ間の差分
これまでのC.txt
に変更を以下のように加えました。
$ git log --graph --oneline -3 work1 work2
* 3ab0563 (HEAD -> work2) Fix C.txt line 8
| * 07cfb3f (work1) Fix C.txt line 3
|/
* 7556ed3 Rename B.txt to C.txt, and change content
$ git log -1 -p work1
commit 07cfb3f43f1602decebc376b194573ade74b8ab5 (work1)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 03:47:02 2020 +0900
Fix C.txt line 3
diff --git a/text/C.txt b/text/C.txt
index e033c8b..542480e 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -1,6 +1,6 @@
1. xxx bbb ccc
2. xxx bbb
-3. bbb ccc
+3. yyy ccc
4. bbb xxx ccc
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
$ git log -1 -p work2
commit 3ab056358c5c5946b01b02734ba683a3c651c6d8 (HEAD -> work2)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 03:47:36 2020 +0900
Fix C.txt line 8
diff --git a/text/C.txt b/text/C.txt
index e033c8b..fcd254a 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -5,7 +5,7 @@
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
work1
とwork2
の各ブランチで別の箇所に変更を加えています。
work1
のヘッドとwork2
のヘッドの差分を見てます。
$ git diff work1 work2
diff --git a/text/C.txt b/text/C.txt
index 542480e..fcd254a 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -1,11 +1,11 @@
1. xxx bbb ccc
2. xxx bbb
-3. yyy ccc
+3. bbb ccc
4. bbb xxx ccc
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
work1
(07cfb3f
)では
-3. bbb ccc
+3. yyy ccc
の変更が
-3. yyy ccc
+3. bbb ccc
となっています。つまり07cfb3f
の変更が元に戻す差分として表示されています。
マージ後の状態
work2
をwork1
にマージする場合にどのような変更になるかを、マージせずに見る方法があります。ピンとくる方もいると思いますが、プルリクエスト(マージリクエスト)の際の差分を見る方法です。
$ git diff work1...work2
diff --git a/text/C.txt b/text/C.txt
index e033c8b..fcd254a 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -5,7 +5,7 @@
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
これでwork2
(3ab0563
)の分だけが表示されました。
-
diff <merge-base>...<merge-target>
: マージ時の差分表示- コンフリクトがある場合は
<merge-target>
側がマージ後の状態として表示される
- コンフリクトがある場合は
マージコミットの差分
work2
をwork1
にマージします。
$ git checkout work1
Switched to branch 'work1'
$ git merge work2
Auto-merging text/C.txt
Merge made by the 'recursive' strategy.
text/C.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log -1 -p
commit 3f844aae20b295603f7843bfb2be2539c238811e (HEAD -> work1)
Merge: 07cfb3f 3ab0563
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:32:58 2020 +0900
Merge branch 'work2' into work1
マージコミットは-p
では差分が表示されません。マージコミットでの差分も表示する場合は-m
オプションを追加します。
$ git log -1 -p -m
commit 3f844aae20b295603f7843bfb2be2539c238811e (from 07cfb3f43f1602decebc376b194573ade74b8ab5) (HEAD -> work1)
Merge: 07cfb3f 3ab0563
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:32:58 2020 +0900
Merge branch 'work2' into work1
diff --git a/text/C.txt b/text/C.txt
index 542480e..b4d4bd7 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -5,7 +5,7 @@
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
commit 3f844aae20b295603f7843bfb2be2539c238811e (from 3ab056358c5c5946b01b02734ba683a3c651c6d8) (HEAD -> work1)
Merge: 07cfb3f 3ab0563
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:32:58 2020 +0900
Merge branch 'work2' into work1
diff --git a/text/C.txt b/text/C.txt
index fcd254a..b4d4bd7 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -1,6 +1,6 @@
1. xxx bbb ccc
2. xxx bbb
-3. bbb ccc
+3. yyy ccc
4. bbb xxx ccc
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
-
-m
: マージコミットの差分を表示-
-p
と併せて指定
-
差分の前後
差分表示はデフォルトで前後3行分が表示されます。この差分の前後を任意の行数で表示できます。
$ git log -1 -p 3ab0563
commit 3ab056358c5c5946b01b02734ba683a3c651c6d8 (work2)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 03:47:36 2020 +0900
Fix C.txt line 8
diff --git a/text/C.txt b/text/C.txt
index e033c8b..fcd254a 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -5,7 +5,7 @@
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
$ git log -1 -p -U7 3ab0563
commit 3ab056358c5c5946b01b02734ba683a3c651c6d8 (work2)
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 03:47:36 2020 +0900
Fix C.txt line 8
diff --git a/text/C.txt b/text/C.txt
index e033c8b..fcd254a 100644
--- a/text/C.txt
+++ b/text/C.txt
@@ -1,11 +1,11 @@
1. xxx bbb ccc
2. xxx bbb
3. bbb ccc
4. bbb xxx ccc
5. ccc xxx ddd eee
6. ddd xxx bbb xxx eee
7. xxx eee bbb
-8. eee ccc ddd fff
+8. eee yyy ddd fff
9. eee fff xxx ccc
10. fff ccc
11. fff eee ddd bbb xxx
変更箇所だけでなく、ファイルの多くを表示したい場合に-U100
などで使っています。
-
-U<N>
: 差分の前後N
行表示-
diff
、log -p
で指定可能 - デフォルトは3行
-
config
でデフォルトを変更可能- ex.)
git config --global diff.context 7
- ex.)
-
特定箇所の履歴
log -p
では対象ファイルのすべての差分が表示されますが、特定箇所の差分の履歴を表示する場合は-L
を使います。
以下はC.txt
の1行目から3行目のみの履歴を表示します。
$ git log -L 1,3:./text/C.txt
commit 07cfb3f43f1602decebc376b194573ade74b8ab5
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 03:47:02 2020 +0900
Fix C.txt line 3
diff --git a/text/C.txt b/text/C.txt
--- a/text/C.txt
+++ b/text/C.txt
@@ -1,3 +1,3 @@
1. xxx bbb ccc
2. xxx bbb
-3. bbb ccc
+3. yyy ccc
commit 7556ed3467875734b03e6eacc1cca944eec33d7b
Author: Kikuchi.M <wildflower.pink0102@gmail.com>
Date: Mon Dec 7 06:22:29 2020 +0900
Rename B.txt to C.txt, and change content
diff --git a/text/C.txt b/text/C.txt
--- /dev/null
+++ b/text/C.txt
@@ -0,0 +1,3 @@
+1. xxx bbb ccc
+2. xxx bbb
+3. bbb ccc
ファイル名変更を追跡していないので、ファイル名変更のコミットを含む2コミット分が表示されました。git log -p ./text/C.txt
ではマージコミットを含む4コミット分が表示されます。(省略)
-
-L <start>,<end>:<file>
:file
のstart
行からend
行の部分のみの履歴を表示 -
-L :<function>:<file>
:file
のfunction
の履歴を表示
まとめ
ファイルの差分、履歴を辿る場合に普段使うオプションを紹介しました。git log -p --word-diff -U10 -m -M2 path/to/file/Foo.java
のように組み合わせて使えるので、どのような差分を調べたいかによってうまく使いわけるといいでしょう。
また説明なしに使ったshow
、ls-files
もトラックしているファイルを表示するのにも便利ですので興味のある方は使ってみてください。
-
(小言) ファイル名変更をする場合、ファイル名変更とファイル内容変更とはコミットを分ける方がいいでしょう。
--follow
オプションで追跡できないほどの内容変更があると、デフォルト(類似50%)では履歴が途切れてしまいます。履歴からどういう意図でどのように変更されてきたかを読むのが困難になります。また-M10%
のように割合を小さくするほど、Y.txt -> Z.txt
の意図で変更したはずのファイルの履歴がX.txt -> Z.txt
のような履歴として出てくるなど、本来変更されたファイルと違うファイルを追跡してしまい、これもまた履歴を辿りにくくします。 ↩