Git 原理简谈

JumpingYeah 2019-12-05

Git 本身是一个对 reference 进行管理的数据库,reference 指的是对原始数据的引用。通过对原始数据的追踪,那么就可以做到对版本的控制。Git 使用一个 DAG 存储了整个的reference,根据DAG 的特性,你不会找到一个环,也就是说对于版本的控制始终是有顺序保证的。

Git 有三个最基本的元素,Commit,Tree 和 Blob。Commit 记录了一次commit需要的信息,作者,comment和指向tree的指针。Tree 是一个指针,指向 Blob 和其他的 Tree,Tree 在逻辑上类似于 Unix 文件系统的文件夹,总对应着当前文件夹的情况。Blob 就是数据本身,例如代码或者其他本身需要追踪的数据。Tree 数据和 Blob 数据在逻辑上类似于文件夹和文件夹下的文件的关系。

Git 使用了SHA值作为文件名,对于三种内置类型的数据,都采用他们的本身计算出的 SHA-1 值作为文件名。为了方便索引,会把 SHA 值的前几个字符当作文件,然后进行索引。所有的文件都存储在 .git/ 目录。

Git 基本的工作模型如下
每一个 branch 会记录了一个对应的 commit,如果有多个 branch 就记录对应的 commit 信息。一次commit在逻辑上代表了一次的版本。每一次的 commit 指向了上一次的commit 和一个 tree。显然,指向上一次的 commit 是用来进行每一次版本控制,每一个的 tree 则是用来指向当前的文件夹信息,这里 tree 也有指向另一个 tree 的部分,这说明这当中有文件夹嵌套出现,一个文件夹中还有一个文件夹就会出现这样的情况。blob 就是对应的文件信息。

一个最基本的 Git 模型如下。
Git 原理简谈

我们可以使用一个最基本的文件夹进行说明。在初始化的时候,产生所有的文件如图所示。
Git 原理简谈

这里,我们重点关注 .git/objects/ 下的文件,git 产生的三种内置类型的文件都会存放在这里。
在使用 git add 命令新添加了一个文件的时候,我们可以看到 .git/objects/ 文件下已经有了新的数据。这个 1d0aaf744db6fea2b31826dc11a36ade43fdfdd9 是文件计算的 SHA-1 结果,存放在 1d 文件夹下是方便进行索引。我们可以使用 git 命令查看这个文件类型和文件内容。

Git 原理简谈

使用 git cat-file -t {SHA-1 名} 可以用来查看文件类型, git cat-file -p {SHA-1名} 可以用来查看文件内容。
查看结果如下

Git 原理简谈

可以看到这个记录是 blob 类型,也就是记录了原始的数据。原始的数据内容我们也可以看到。

在进行 git commit 命令之后,我们继续看下文件夹的变化。

Git 原理简谈

此时,多了两个新的文件,分别是 a918c…. 和 41131a….,这两个文件对应的是 tree 类型的文件和 commit 类型的文件,通过 commit 信息,我们可以知道 a918c… 是 commit 类型的文件,而 41131a… 是 tree 类型的文件。
根据 git cat-file 命令,我们可以看到具体的 tree 文件的内容。指向了 blob 类型的文件,文件名是 1d0a… 真实对应的文件名是 foo.txt 。具体的 commit 文件记录了 Author 信息,comment 信息,并指向了一个对应的 tree 文件。

Git 原理简谈
Git 原理简谈

接下来,我们进行新的一次 commit,继续看看对应的 commit 文件信息和 tree 的信息。
Git 原理简谈
Git 原理简谈

可以看到,新的 commit 信息记录了上次的 commit 文件的名称,方便进行切换版本,也记录了这次的 tree 文件的信息。tree 文件记录了对应两个 blob 实体的名称。

如果新创建了一个文件夹,然后在文件夹中添加新的文件,就会出现 tree 指向新的 tree 文件的情况。而另一个tree 指向自己对应的文件信息

Git 原理简谈

如果创建了新的 branch,那么会在对应的 .git/refs/heads 目录下创建新的 branch 文件,并指向此时的 commit 文件。
如果在新的 branch 中,改变了原来的文件,那么会直接创建一个新的 blob,记录这个文件信息,并且改变 tree 原来指向的位置,即两个文件是两个完全不同,但都存在的文件。
如在 new_branch 中,改变了 foo.txt 内容,那么此时 tree 指向的文件也发生了变化,有了在这个分支中新添加的文件,也有了改变的文件。
Git 原理简谈
而在原先的 master 分支中,tree 仍然记录的是之前的信息。
Git 原理简谈

相关推荐