查看单个文件历史改动

命令行-p选项

1
2
git log -- filename # 不显示具体的改动内容
git log -p -- filename # 显示具体的改动内容

比如某个仓库共有如下4次提交历史:

1
2
3
4
5
$ git log --oneline --all --graph
* 841c6cd (HEAD -> master) 同时修改A/B.java
* 67aeb5a 修改B.java
* e792004 修改A.java
* df23fd5 First Commit

其中第一次提交中新增了A.javaB.java两个文件。

如果我们希望查看哪些提交中改动了文件A.java,可以通过如下的命令实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ git log -- A.java
commit 841c6cdf0e944f3b32dd62fbe6ab902454f03733 (HEAD -> master)
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:15:31 2024 +0800

同时修改A/B.java

commit e7920046eef378eca3c34c1228ba253bc4b2c686
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:13:22 2024 +0800

修改A.java

commit df23fd5d74982047163443150743add9936c63df
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:12:35 2024 +0800

First Commit # 新增了`A.java`和`B.java`两个文件

但是上面的输出中并不会显示每一次改动修改的内容,如果希望显示每次改动的内容,可以添加-p选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ git log -p -- A.java
commit 841c6cdf0e944f3b32dd62fbe6ab902454f03733 (HEAD -> master)
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:15:31 2024 +0800

同时修改A/B.java

diff --git a/A.java b/A.java
index 5f2f16b..4f142ee 100644
--- a/A.java
+++ b/A.java
@@ -1 +1,2 @@
1111
+2222

commit e7920046eef378eca3c34c1228ba253bc4b2c686
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:13:22 2024 +0800

修改A.java

diff --git a/A.java b/A.java
index e69de29..5f2f16b 100644
--- a/A.java
+++ b/A.java
@@ -0,0 +1 @@
+1111

commit df23fd5d74982047163443150743add9936c63df
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:12:35 2024 +0800

First Commit

diff --git a/A.java b/A.java
new file mode 100644 # 新增文件
index 0000000..e69de29

命令行–follow选项

假设我们在后续某次操作中,将文件A.java重命名为A1.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git mv A.java A1.java

MINGW64 /d/tmp/git-playground (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: A.java -> A1.java

$ git commit -m '修改文件名:A.java -> A1.java'
[master fea443b] 修改文件名:A.java -> A1.java
1 file changed, 0 insertions(+), 0 deletions(-)
rename A.java => A1.java (100%)

然后我们在后续的修改中,修了A1.java的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git show 3356864
commit 3356864626403629df5cf2378b273c8457433192 (HEAD -> master)
Author: TerryLikesCoding <18328621355@163.com>
Date: Sun Apr 7 16:41:32 2024 +0800

修改A1.java

diff --git a/A1.java b/A1.java
index 4f142ee..e0037f0 100644
--- a/A1.java
+++ b/A1.java
@@ -1,2 +1,3 @@
1111
2222
+3333

完整的git历史如下:

1
2
3
4
5
6
7
$ git log --all --oneline
3356864 (HEAD -> master) 修改A1.java
fea443b 修改文件名:A.java -> A1.java
841c6cd 同时修改A/B.java
67aeb5a 修改B.java
e792004 修改A.java
df23fd5 First Commit

如果使用命令不添加--follow选项,则输出的历史如下:

1
2
3
$ git log  --oneline -- A1.java
3356864 (HEAD -> master) 修改A1.java
fea443b 修改文件名:A.java -> A1.java

可以看到,并不包含3356864这一次针对重命名前针对文件A.java的更改。如果我们添加上--follow选项,则输出如下:

1
2
3
4
5
6
$ git log  --oneline --follow -- A1.java
3356864 (HEAD -> master) 修改A1.java
fea443b 修改文件名:A.java -> A1.java
841c6cd 同时修改A/B.java
e792004 修改A.java
df23fd5 First Commit

A1.java所有的修改记录(包括重命名之前的都可以查看到)。

注意:如果反过来:

1
2
3
4
5
6
7
8
9
10
11
$ git log  --oneline -- A.java
fea443b 修改文件名:A.java -> A1.java
841c6cd 同时修改A/B.java
e792004 修改A.java
df23fd5 First Commit

$ git log --oneline --follow -- A.java
fea443b 修改文件名:A.java -> A1.java
841c6cd 同时修改A/B.java
e792004 修改A.java
df23fd5 First Commit

则重命名后针对A1.java的改动不会显示。

使用gitk可视化查看

1
2
gitk A1.java
gitk --follow A1.java

--follow的含义同上

比如:

1
gitk --follow A1.java

image-20240407171009269