不同的树对象分别代表我们想要跟踪的不同项目快照。
    然而问题依旧:若想重用这些快照,你必须记住所有不同树对象的 SHA-1 哈希值。 并且,你也完全不知道是谁保存了这些快照,在什么时刻保存的,以及为什么保存这些快照。
    而以上这些,正是提交对象(commit object)能为你保存的基本信息。

    通过调用 commit-tree 命令创建一个提交对象,为此需要指定一个树对象的 SHA-1 值,以及该提交的父提交对象(如果有的话)。 我们从之前创建的第一个树对象开始:

    1. $ echo "first commit" | git commit-tree a376c417225045e853f785ef73ecd0b10291e1b9
    2. 76328ef53b2ecef2463943332f2b65f5ed925eb6

    由于创建时间和作者数据不同,你现在会得到一个不同的散列值。
    现在可以通过 git cat-file 命令查看这个新提交对象:

    1. $ git cat-file -p 76328ef53b2ecef2463943332f2b65f5ed925eb6
    2. tree a376c417225045e853f785ef73ecd0b10291e1b9
    3. author zdkk <1040893382@qq.com> 1666149234 +0800
    4. committer zdkk <1040893382@qq.com> 1666149234 +0800
    5. first commit

    提交对象的格式很简单:
    它先指定一个顶层树对象,代表当前项目快照;
    然后是可能存在的父提交(前面描述的提交对象并不存在任何父提交);
    之后是作者/提交者信息(依据你的 user.name 和 user.email 配置来设定,外加一个时间戳);
    留空一行,
    最后是提交注释。

    接着,我们将创建另两个提交对象,它们分别引用各自的上一个提交(作为其父提交对象):

    1. $ echo "second commit" | git commit-tree 22958f74c92ee3d5281002141288eca069c75b86 -p 76328ef53b2ecef2463943332f2b65f5ed925eb6
    2. c5f9689205729d1713ec9cf6a4e97fa7b5d9dfda
    3. $ echo "third commit" | git commit-tree 3387740527358bcad3ab519369794c8cc2c15673 -p c5f9689205729d1713ec9cf6a4e97fa7b5d9dfda
    4. 8156ac50b36237aa71db17f4d9e07e243fa1e412

    这三个提交对象分别指向之前创建的三个树对象快照中的一个。 现在,如果对最后一个提交的 SHA-1 值运行 git log 命令,会出乎意料的发现,你已有一个货真价实的、可由 git log 查看的 Git 提交历史了:

    1. $ git log --stat 8156ac5
    2. commit 8156ac50b36237aa71db17f4d9e07e243fa1e412
    3. Author: zdkk <1040893382@qq.com>
    4. Date: Wed Oct 19 11:20:02 2022 +0800
    5. third commit
    6. bak/test.txt | 1 +
    7. 1 file changed, 1 insertion(+)
    8. commit c5f9689205729d1713ec9cf6a4e97fa7b5d9dfda
    9. Author: zdkk <1040893382@qq.com>
    10. Date: Wed Oct 19 11:18:16 2022 +0800
    11. second commit
    12. new.txt | 1 +
    13. test.txt | 2 +-
    14. 2 files changed, 2 insertions(+), 1 deletion(-)
    15. commit 76328ef53b2ecef2463943332f2b65f5ed925eb6
    16. Author: zdkk <1040893382@qq.com>
    17. Date: Wed Oct 19 11:13:54 2022 +0800
    18. first commit
    19. test.txt | 1 +
    20. 1 file changed, 1 insertion(+)

    至此,没有借助任何上层命令,仅凭几个底层操作便完成了一个 Git 提交历史的创建!
    每次我们运行 git add 和 git commit 命令时,Git 所做的工作实质就是将被改写的文件保存为数据对象, 更新暂存区,记录树对象,最后创建一个指明了顶层树对象和父提交的提交对象。 这三种主要的 Git 对象——数据对象、树对象、提交对象——最初均以单独文件的形式保存在 .git/objects 目录下。
    下面列出了目前示例目录内的所有对象,辅以各自所保存内容的注释:

    1. $ find .git/objects/ -type f
    2. .git/objects/18/0cf8328022becee9aaa2577a8f84ea2b9f3827 # test2
    3. .git/objects/22/958f74c92ee3d5281002141288eca069c75b86 # tree 2
    4. .git/objects/33/87740527358bcad3ab519369794c8cc2c15673 # tree 3
    5. .git/objects/76/328ef53b2ecef2463943332f2b65f5ed925eb6 # first commit
    6. .git/objects/81/56ac50b36237aa71db17f4d9e07e243fa1e412 # third commit
    7. .git/objects/a3/76c417225045e853f785ef73ecd0b10291e1b9 # tree 1
    8. .git/objects/a5/bce3fd2565d8f458555a0c6f42d0504a848bd5 # test1
    9. .git/objects/c5/f9689205729d1713ec9cf6a4e97fa7b5d9dfda # second commit
    10. .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # test content
    11. .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt

    git_object.jpg
    当前Git 目录下所有可达的对象