盒子
盒子
文章目录
  1. 目标
  2. 实现
    1. 准备文件数据 (blob对象)
    2. 创建tree对象
    3. 创建commit对象
  3. 结果

git底层命令

本文介绍通过 git 底层命令实现commit的功能。参考资料:Pro Git

目标

我们想要达到的目标如下:

  1. 在已经初始化的空git仓库内,创建名为dir/version.txt的文件,文件中包含的内容为:

    1
    2
    Current version:
    version 1

  2. 在步骤1的基础上,修改文件dir/version.txt的内容为:

    1
    2
    Current version:
    version 2

  3. 在步骤2的基础上,增加文件new.txt,文件内容为:

    1
    New file
    上面的每个步骤分别对应一个commit。


实现

准备文件数据 (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对象

  1. 创建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

  2. 创建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

  3. 创建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对象

  1. 创建first commit

    1
    2
    3
    4
    5
    # 1. 创建commit对象,哈希值:c9582acabd389dd80038711efbb65c2034a1d92d
    echo "first commit" | git commit-tree 551ca1

    # 2. 检查类型:commit
    git cat-file -t c9582a

  2. 创建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

  3. 创建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
46
git 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