Git 使用一种称为对象存储的机制来管理和处理所有文件和目录内容,以及它们之间的关系。
Git 对象存储机制包括以下几个方面:
- Git 对象:Git 中的所有数据都被视为对象。一个对象可以是一个文件的内容(Blob)、目录结构(Tree)、提交记录(Commit)或标签(Tag)等。
- SHA-1 哈希:每个 Git 对象都具有与其内容相关联的唯一标识符,该标识符由其内容的 SHA-1 哈希值生成。这使得 Git 可以轻松地检测文件内容的更改。
- Git 数据库:Git 会将所有对象存储在一个数据库中,该数据库位于
.git/objects
目录下。该目录包含一个名为info
的子目录和一个名为pack
的子目录,其中info
子目录包含有关对象的元数据,而pack
子目录包含经过压缩的对象。
Git 数据库包含了许多不同类型的对象,这些对象相互关联形成一个有向无环图(DAG)。在 Git 中,每个对象都由 SHA-1 哈希值唯一标识,并按照其哈希值存储在 .git 目录下的 objects 目录中。
Git 对象包括四种主要类型:blob、tree、commit 和 tag。
Blob 对象代表一个文件的内容。每个 blob 都由一个唯一的 SHA-1 哈希值标识,并存储在 .git/objects 目录下。Blob 对象是 Git 数据库的基本单位,它们包含文件的原始内容而不包含任何元数据。
Tree 对象代表一个目录或文件夹,在 Git 中被称为“树”。它可以包含多个 blob 或其他 tree 对象,以及相关元数据,如文件名和权限等信息。Tree 对象也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下的 objects/trees 子目录中。
Commit 对象代表一个 Git 提交,包含作者和提交日期等元数据,以及一个指向对应 tree 对象的指针。每个 commit 也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下。
Tag 对象代表一个 Git 标签,它可以指向特定的 commit 或其他 tag。它包含了版本号、标签类型以及描述信息等元数据,以及对应对象的 SHA-1 哈希值指针。Tag 对象也由一个 SHA-1 哈希值唯一标识,并存储在 .git/objects 目录下。
这些 Git 对象之间的关系构成了一个有向无环图(DAG),每个节点都是一个对象,每个边表示一个指针。Git 使用这种数据结构来跟踪代码库的历史记录和变化,并支持分支、合并、撤销和回滚等操作。
git cat-file
命令在 Git 中是一个非常有用的工具,特别是对于那些需要深入了解 Git 内部机制的开发人员和高级用户来说。git cat-file
命令通常用于以下两种情况:
- 调试 Git 内部存储:如果您需要深入了解 Git 的内部工作方式,或者需要调试 Git 存储机制中的某些问题,则可以使用
git cat-file
命令查看 Git 对象的类型和内容。例如,您可以使用git cat-file -p <commit-SHA>
命令来查看一个提交对象的详细信息,包括其作者、时间、提交消息等。 - 恢复丢失的 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 子模块。-33188
或100644
:普通文件(文件权限为-rw-r--r--
)。-33261
或100755
:可执行文件(文件权限为-rwxr-xr-x
)。
Git 对象可以帮助我们跟踪文件的历史记录和变化,并在需要时恢复旧版本的文件或比较不同版本之间的差异。在 Git 中,提交记录、树对象和文件对象都有各自的哈希值,并以这些哈希值相互关联,形成一个完整的 Git 数据库。通过使用 git log
([[9.设置别名]])、git cat-file
等命令,我们可以查看存储库中的对象内容,并深入了解存储库的历史记录和变更。