导读:当我们执行git log --name-status
的时候,git都做了些什么?
我们先来看看这个命令的输出内容,然后根据输出内容,探寻对应的数据来源:
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
|
git log --name-status
commit dc91f7f38cdb3c8876a7bfd38020e2a64f33015d (HEAD -> master, origin/master)
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:28:09 +0800
delete conn.c
D src/conn.c
commit 0909df98f750118bebab6fb325ede8a836b6b7c1
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:27:38 +0800
rename demo.c to conn.c
R100 src/demo.c src/conn.c
commit 1deeef231881649821b6437594293b22bb9183a0
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:26:53 +0800
second commit
M README.md
commit 02bc27b851963a71d8b8c80f8d6834db25b716a1
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:26:29 +0800
init commit
A README.md
A src/demo.c
A src/main.c
|
git log --name-status
commit dc91f7f38cdb3c8876a7bfd38020e2a64f33015d (HEAD -> master, origin/master)
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:28:09 +0800
delete conn.c
D src/conn.c
commit 0909df98f750118bebab6fb325ede8a836b6b7c1
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:27:38 +0800
rename demo.c to conn.c
R100 src/demo.c src/conn.c
commit 1deeef231881649821b6437594293b22bb9183a0
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:26:53 +0800
second commit
M README.md
commit 02bc27b851963a71d8b8c80f8d6834db25b716a1
Author: ticktechman <ticktechman@gmail.com>
Date: 2024-06-12 19:26:29 +0800
init commit
A README.md
A src/demo.c
A src/main.c
可以看到上面有4个版本的历史数据,每个版本中显示了commit对象ID、作者&提交人信息、修改描述以及修改的文件清单。
不带版本参数的情况下,Git默认从HEAD开始追踪历史记录,HEAD位于.git/HEAD
,里面的内容为:
1
2
3
4
5
6
7
|
## 查看HEAD内容,这里是一个符号引用(sym-ref),指向master
cat .git/HEAD
ref: refs/heads/master
## 查看master引用文件内容
cat .git/refs/heads/master
dc91f7f38cdb3c8876a7bfd38020e2a64f33015d
|
## 查看HEAD内容,这里是一个符号引用(sym-ref),指向master
cat .git/HEAD
ref: refs/heads/master
## 查看master引用文件内容
cat .git/refs/heads/master
dc91f7f38cdb3c8876a7bfd38020e2a64f33015d
上面master引用文件中存储的内容是一个commit对象的ID,通过下面的命令可以打印它的内容:
1
2
3
4
5
6
7
|
git cat-file -p dc91f7f38cdb3c8876a7bfd38020e2a64f33015d
tree 9bdf3e7865533385c7718f7e34fbf86d1a727a29
parent 0909df98f750118bebab6fb325ede8a836b6b7c1
author ticktechman <ticktechman@gmail.com> 1718191689 +0800
committer ticktechman <ticktechman@gmail.com> 1718191689 +0800
delete conn.c
|
git cat-file -p dc91f7f38cdb3c8876a7bfd38020e2a64f33015d
tree 9bdf3e7865533385c7718f7e34fbf86d1a727a29
parent 0909df98f750118bebab6fb325ede8a836b6b7c1
author ticktechman <ticktechman@gmail.com> 1718191689 +0800
committer ticktechman <ticktechman@gmail.com> 1718191689 +0800
delete conn.c
通过上面的commit对象的内容,我们可以拿到上面日志中的大部分信息,但是细心的小伙伴可能发现了问题,这里没有和文件相关的信息,例如在第一条日志记录中,我们删除了一个文件src/conn.c
,这里看不到,那Git是如何知道的呢?
答案在tree对象里面,但这不是直接获取的,而是要通过对比当前版本与上一个版本的tree对象的内容差异来获取。
可以通过下面的命令查看不同版本tree对象的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
## v4(当前版本)版本的tree对象的内容
git ls-tree HEAD -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v3 版本的tree对象的内容
git ls-tree HEAD^ -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/conn.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v2 版本的tree对象的内容
git ls-tree HEAD^^ -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/demo.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v1 版本的tree对象的内容
git ls-tree HEAD^^^ -r
100644 blob 2e23b77e9d108d265c6205bec72177f5fccec9e4 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/demo.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
|
## v4(当前版本)版本的tree对象的内容
git ls-tree HEAD -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v3 版本的tree对象的内容
git ls-tree HEAD^ -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/conn.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v2 版本的tree对象的内容
git ls-tree HEAD^^ -r
100644 blob d21cf5020db5abcace9348a55fa6d871eaf24eb7 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/demo.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
## v1 版本的tree对象的内容
git ls-tree HEAD^^^ -r
100644 blob 2e23b77e9d108d265c6205bec72177f5fccec9e4 README.md
100644 blob 8d8a1a21a7e49591c70f100175279fc0d3a1f711 src/demo.c
100644 blob 0c124f091e9fff8e05cd5de11b8058b05beb1f96 src/main.c
- 通过对比v3和v4版本,很明显的可以看到v4版本中删除了
src/conn.c
。
- 对比v2和v3,我们可以明显看到
src/demo.c
被重命名为src/conn.c
,因为blob对象的SHA1值都是8d8a1a21a7e49591c70f100175279fc0d3a1f711
(SHA1相同表示内容完全一样)。
- 对比v1和v2,也可以看到
README.md
被修改了,因为两个BLOB对象的SHA1值不同。
Git通过遍历每个commit对象的parent指针,显示所有版本的信息,直到commit对象的parent为空为止,例如:
1
2
3
4
5
6
|
git cat-file -p 02bc27b851963a71d8b8c80f8d6834db25b716a1
tree 8c34ef7320c2bd6b3b69fa9e64b23ff2cd74de5e
author ticktechman <ticktechman@gmail.com> 1718191589 +0800
committer ticktechman <ticktechman@gmail.com> 1718191589 +0800
init commit
|
git cat-file -p 02bc27b851963a71d8b8c80f8d6834db25b716a1
tree 8c34ef7320c2bd6b3b69fa9e64b23ff2cd74de5e
author ticktechman <ticktechman@gmail.com> 1718191589 +0800
committer ticktechman <ticktechman@gmail.com> 1718191589 +0800
init commit
这个版本中,没有parent对象指针,表示这是一个根commit对象,这个版本的tree对象中记录的所有文件都是新增文件。