19.了解Git对象存储机制

Git 使用一种称为对象存储的机制来管理和处理所有文件和目录内容,以及它们之间的关系。

Git 对象存储机制包括以下几个方面:

  1. Git 对象:Git 中的所有数据都被视为对象。一个对象可以是一个文件的内容(Blob)、目录结构(Tree)、提交记录(Commit)或标签(Tag)等。

  2. SHA-1 哈希:每个 Git 对象都具有与其内容相关联的唯一标识符,该标识符由其内容的 SHA-1 哈希值生成。这使得 Git 可以轻松地检测文件内容的更改。

  3. Git 数据库:Git 会将所有对象存储在一个数据库中,该数据库位于 .git/objects 目录下。该目录包含一个名为 info 的子目录和一个名为 pack 的子目录,其中 info 子目录包含有关对象的元数据,而 pack 子目录包含经过压缩的对象。

Git 对象

Git 数据库包含了许多不同类型的对象,这些对象相互关联形成一个有向无环图(DAG)。在 Git 中,每个对象都由 SHA-1 哈希值唯一标识,并按照其哈希值存储在 .git 目录下的 objects 目录中。

Git 对象包括四种主要类型:blob、tree、commit 和 tag。

Blob

Blob 对象代表一个文件的内容。每个 blob 都由一个唯一的 SHA-1 哈希值标识,并存储在 .git/objects 目录下。Blob 对象是 Git 数据库的基本单位,它们包含文件的原始内容而不包含任何元数据。

Tree

Tree 对象代表一个目录或文件夹,在 Git 中被称为“树”。它可以包含多个 blob 或其他 tree 对象,以及相关元数据,如文件名和权限等信息。Tree 对象也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下的 objects/trees 子目录中。

Commit

Commit 对象代表一个 Git 提交,包含作者和提交日期等元数据,以及一个指向对应 tree 对象的指针。每个 commit 也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下。

Tag

Tag 对象代表一个 Git 标签,它可以指向特定的 commit 或其他 tag。它包含了版本号、标签类型以及描述信息等元数据,以及对应对象的 SHA-1 哈希值指针。Tag 对象也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下。

实验

git cat-file 命令在 Git 中是一个非常有用的工具,特别是对于那些需要深入了解 Git 内部机制的开发人员和高级用户来说。git cat-file 命令通常用于以下两种情况:

  1. 调试 Git 内部存储:如果您需要深入了解 Git 的内部工作方式,或者需要调试 Git 存储机制中的某些问题,则可以使用 git cat-file 命令查看 Git 对象的类型和内容。例如,您可以使用 git cat-file -p <commit-SHA> 命令来查看一个提交对象的详细信息,包括其作者、时间、提交消息等。

  2. 恢复丢失的 Git 对象:如果您的代码库中丢失了某个对象,例如 Blob 或 Tree 对象,您可以使用 git cat-file 命令查看该对象的 SHA-1 标识符,并尝试从其他地方恢复它。例如,您可以使用 git cat-file -t <object-SHA> 命令来验证指定的对象是否存在,如果不存在,则表示该对象已经丢失。

我们现在开始实验

找到最新一条提交记录

# 查看最近一条提交日志
$ git hist --max-count=1
* 5dc8b1e 2023-05-05 | Added .gitignore (HEAD -> master) [aku]

查看提交对象的类型和对象的内容

-p:查看对象内容 -t:查看对象类型

# 查看对象类型
$ git cat-file -t  5dc8b1e
commit

# 查看对象内容
$ git cat-file -p 5dc8b1e
tree 8b1db75acbd6f424e485953d3b4b8fb0de2f9065
parent b77158ade22b7ec01d29dde4c2e20df0ed2008ec
author aku <aku@example.com> 1683342959 -0700
committer aku <aku@example.com> 1683342959 -0700

Added .gitignore
  • Tree:该提交所指向的树对象的 SHA-1 标识符。

  • Parent:该提交的父提交(可能有多个)的 SHA-1 标识符。

  • Author:该提交的作者姓名和电子邮件地址,以及提交时间戳。

  • Committer:该提交的提交者姓名和电子邮件地址,以及提交时间戳。

  • Moved test.txt to lab:我在提交时添加的注释。

探索

# 这里的哈希值,是上一步查看最新提交的 tree 哈希
$ git cat-file -p 8b1db75
100644 blob cb266c781c016fa3ae0be3bab90e71145dc6b09c    .gitignore
040000 tree 652058dd2d8057d2d79049dd3aa7a9f4e69d5e89    lab

# 查看 lab 文件夹的哈希
$ git cat-file -p 652058d
100644 blob 0605515085232c2911ca5e6c407da497c51a5c74    test.txt

# 查看 test 的哈希
$ git cat-file -p 060551
abc
123456

100644 是一种文件模式,也称为文件权限或 Unix 文件模式。 6 表示所有者可以读取和写入该文件,但不能执行。 4 表示组用户可以读取该文件,但不能写入或执行。 4 表示其他人可以读取该文件,但不能写入或执行。 在 Unix 系统中,文件权限由一组三个数字表示,分别代表文件所有者、组用户和其他人的文件权限。每个数字表示一个具体的权限:- 0:无权限。- 1:执行权限。- 2:写入权限。- 3:写入和执行权限。- 4:读取权限。- 5:读取和执行权限。- 6:读取和写入权限。- 7:读取、写入和执行权限。 例如上文中的 644 表示以下内容:文件所有者可以读写该文件(6 = 4 + 2)。组用户可以读该文件(4)。 其他人可以读该文件(4)。 以下是一些常见的 Git 文件模式及其含义:- 040000:子目录。- 120000:符号链接。- 160000:Git 子模块。- 33188100644:普通文件(文件权限为 -rw-r--r--)。- 33261100755:可执行文件(文件权限为 -rwxr-xr-x)。

Git 对象可以帮助我们跟踪文件的历史记录和变化,并在需要时恢复旧版本的文件或比较不同版本之间的差异。在 Git 中,提交记录、树对象和文件对象都有各自的哈希值,并以这些哈希值相互关联,形成一个完整的 Git 数据库。通过使用 git log([[9.设置别名]])、git cat-file 等命令,我们可以查看存储库中的对象内容,并深入了解存储库的历史记录和变更。

Last updated