Git 内部架构🏛
初始化仓库
暂存文件
提交
分支
Git 为解决复杂问题提供了一个极其简洁优雅的方案。我认为,为了充分理解它的简洁性和强大功能,我们必须了解其背后的工作原理和工程决策。
Git 如何存储文件?运行各种 Git 命令时会发生什么?所有组件之间是如何关联的?它使用的数据结构是什么?
我们将回答以下所有问题👇
初始化仓库
当你git init在某个目录中运行 Git 时,Git 会创建该.git目录,Git 存储和操作的几乎所有内容都位于该目录中。
tree .git👆运行该git init命令后的输出
它包含几种不同类型的文件和目录:
- 配置:
.git/config和.git/description文件.git/info/exclude主要用于配置本地存储库。 - 钩子:该
.git/hooks目录包含可在存储库的某些生命周期事件上运行的脚本。 - 暂存区:该
.git/index文件(尚未出现在上面的树状列表中)将为我们的工作目录提供一个暂存区。 - 对象数据库:该
.git/objects目录是默认的 Git 对象数据库,其中包含所有内容或指向本地内容的指针。 - 引用:该
.git/refs目录是存储本地和远程分支、标签和头部引用指针的默认位置。引用是指向对象的指针,通常为 `Object`tag或 ` Object` 类型commit。引用在对象数据库之外进行管理,以便随着代码库的演进,引用指向的位置可以发生变化。特殊情况下,引用可以指向其他引用,例如 `Object.references`HEAD。
暂存文件
当我们运行命令时,git add .Git 会将工作目录中的所有更改添加到暂存区,并在.git/objects子目录中创建 blob 文件。
每个对象文件都以一个 40 个字符的 SHA-1 哈希值作为文件名。Git 使用文件名的前两个字符来组织目录中的对象。
这个 Blob 对象包含文件的内容。所有对象一旦创建便不可更改。对文件进行更改并暂存后,将会创建一个全新的对象。
让我们来验证并检查这个blob文件的内容。当我们运行命令时,cat .git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238
并没有得到预期的结果。
实际上,Git 使用zlib压缩每个对象,因此你看到的是压缩后的内容。
要查看文件的实际内容,请使用以下命令git cat-file -p <SHA-1>
提交
运行该git commit命令会在子目录中创建两个新对象objects。一个是树对象,另一个是提交对象。
树状对象
单个树对象包含一个或多个条目,每个条目都是一个 blob 或子树的 SHA-1 哈希值,并包含其关联的模式、类型和文件名。
提交对象
提交对象的格式很简单:它指定了项目快照在该点的顶级树、父提交(如果有)、作者/提交者信息和提交消息。
我们常用的提交 ID 是提交对象内容的 SHA-1 哈希值。
Git 使用各种不同类型的对象,将所有内容存储为有向无环图。以下是此时的数据结构示例。
分支
在 Git 中,分支本质上是一个指向某个提交对象的轻量级可移动指针。正因如此,在 Git 中创建新分支的成本很低。
每次提交时,分支指针都会自动向前移动。
Git 如何知道你当前在哪个分支上?它维护着一个名为 HEAD 的特殊指针HEAD。HEAD 就是一个指向分支的特殊指针,也就是你当前正在工作的分支。
当我们运行命令时,git checkout -b <NAME>Git 会在以分支名称命名的目录中创建一个新文件refs/heads。该文件包含指向最新提交的指针。
总之,Git 命令是对数据存储的一种抽象。哈希表、基于文件的键值存储和树形数据结构,这些是 Git 的核心技术。
欢迎随时在推特上联系我。
请告诉我你还对哪些建筑深度解析感兴趣。请在下方留言。👇
文章来源:https://dev.to/anuj_bansal_/git-internal-architecture-o1j







