本文介绍通过 git 底层命令实现commit的功能。参考资料:Pro Git。
目标
我们想要达到的目标如下:
在已经初始化的空git仓库内,创建名为
dir/version.txt的文件,文件中包含的内容为:1
2Current version:
version 1在步骤1的基础上,修改文件
dir/version.txt的内容为:1
2Current version:
version 2在步骤2的基础上,增加文件
new.txt,文件内容为:上面的每个步骤分别对应一个commit。1
New file
实现
准备文件数据 (blob对象)
我们首先往git的数据库中准备我们所需的三个版本文件的内容:
1
2
3
4
5
6
7
8# 1. 增加version 1文件内容,得到的哈希值: 318430ba4ec37d61d2a6ed70d3c0c82b16608b89
echo -e "Current version:\nversion 1" | git hash-object -w --stdin
# 2. 增加version 2文件内容,得到的哈希值:8ffdf7bfc8d21a7d470393ccc90bedf09b84997d
echo -e "Current version:\nversion 2" | git hash-object -w --stdin
# 3. 增减new.txt文件内容,得到的哈希值:ea450f959b935cbf0fb1dc902981ae819386b84d
echo -e "New file" | git hash-object -w --stdin git cat-file -t可以查看这三个hash对象的类型,见下表:
| 哈希值 | 类型 |
|---|---|
| 318430 | blob |
| 8ffdf7 | blob |
| ea450f | blob |
创建tree对象
创建version 1的tree对象:
1
2
3
4
5
6
7
8# 1. 创建index区域内容,可以结合git status和git diff --staged 进行确认
git update-index --add --cacheinfo 100644 318430 dir/version.txt
# 2. 创建tree对象,哈希值:551ca19068f6f6dd085be75c230ec7c012887051
git write-tree
# 3. 查看对象类型:tree
git cat-file -t 551ca1创建version 2的tree对象:
1
2
3
4
5
6
7
8# 1. 创建index区域内容,注意此时已经存在dir/version.txt文件了,所以不需要--add参数
git update-index --cacheinfo 100644 8ffdf7 dir/version.txt
# 2. 创建tree对象,哈希值:795a69d10f5f0fd5c9645bf3673ad977ee87617d
git write-tree
# 3. 查看对象类型:tree
git cat-file -t 795a69创建new.txt的tree对象:
1
2
3
4
5
6
7
8
9
10
11
12
13# 1. 创建index区域内容
# 1.1 需要移除掉先前的dir/version.txt
git rm --cached dir/version.txt
# 1.2 此时index区域为空,读入第二步创建的tree对象
git read-tree 795a69
# 1.3 增加new.txt
git update-index --add --cacheinfo 100644 ea450f new.txt
# 2. 创建tree对象,哈希值:ca61f8adfba7f3c1d9fc5aedec8dfb3c28ec6921
git write-tree
# 3. 查看对象类型:tree
git cat-file -t ca61f8
创建commit对象
创建first commit
1
2
3
4
5# 1. 创建commit对象,哈希值:c9582acabd389dd80038711efbb65c2034a1d92d
echo "first commit" | git commit-tree 551ca1
# 2. 检查类型:commit
git cat-file -t c9582a创建second commit
1
2
3
4
5# 1. 创建second commit,其父commit为first commit,哈希值:5c5805c59dbdc96bccc73ca6b0cfe062fd31d857
echo "second commit" | git commit-tree 795a69 -p c9582a
# 2. 检查类型:commit
git cat-file -t 5c5805创建third commit
1
2
3
4
5# 1. 创建third commit, 哈希值:052afca2060a4a2b04e988988e814d160ceac215
echo "third commit" | git commit-tree ca61f8 -p 5c5805
# 2. 检查类型:commit
git cat-file -t 052afc
至此,3个commit创建完毕。
结果
最终创建的commit如下: 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
38
39
40
41
42
43
44
45
46git log -p 052afc
commit 052afca2060a4a2b04e988988e814d160ceac215
Author: Hongzhen Luo <hongzhen_lhz@163.com>
Date: Mon Sep 8 10:46:35 2025 +0800
third commit
diff --git a/new.txt b/new.txt
new file mode 100644
index 0000000..ea450f9
--- /dev/null
+++ b/new.txt
@@ -0,0 +1 @@
+New file
commit 5c5805c59dbdc96bccc73ca6b0cfe062fd31d857
Author: Hongzhen Luo <hongzhen_lhz@163.com>
Date: Mon Sep 8 10:44:22 2025 +0800
second commit
diff --git a/dir/version.txt b/dir/version.txt
index 318430b..8ffdf7b 100644
--- a/dir/version.txt
+++ b/dir/version.txt
@@ -1,2 +1,2 @@
Current version:
-version 1
+version 2
commit c9582acabd389dd80038711efbb65c2034a1d92d
Author: Hongzhen Luo <hongzhen_lhz@163.com>
Date: Mon Sep 8 10:42:35 2025 +0800
first commit
diff --git a/dir/version.txt b/dir/version.txt
new file mode 100644
index 0000000..318430b
--- /dev/null
+++ b/dir/version.txt
@@ -0,0 +1,2 @@
+Current version:
+version 1