在 Git 的资料结构中,「物件」是一种「不可变的」 (immutable) 档案类型,所有储存在「物件储存区」的档案通常只进不出,也不会被修改内容。原因在于,如果你窜改了档案了内容,新的内容所运算出来的 SHA1 杂凑值将会与原有物件的档名不一样,这导致 Git 无法继续执行,相对地也对 Git 储存库产生了一定程度的保护作用。本篇文章,将更加仔细地介绍 Git 的物件结构,最后也会透过一则影片,详细解说整个物件被产生的过程与逻辑。
前一篇文章有提到,无论 blob 物件与 tree 物件,这些都算是物件,这些物件都会储存在一个所谓的「物件储存区」 (object storage) 之中,而这个「物件储存区」预设就在「储存库」的 objects 目录下,如下图示:
然而 Git 储存库中的每一个「物件」,都是以「档案内容」进行 SHA1 杂凑运算出一个 hash 值,并用这个 hash 值当作物件的名称 (档名)。我们以 8a6b275638f3cf164395e65066a1132bb36b7896 为例,Git 会先拿前两个字元(8a)当作目录,然后把剩下的 hash 值当成档名 (6b275638f3cf164395e65066a1132bb36b7896),这些物件的实体目录与档案也都会放在 .git\objects 目录下,如下图示:
在这些「物件资料库」裡面,又包含了 4 种物件类型,分别是:
Git 会将每一个版本中的档案建立一个对应的 blob 物件,一样的,该 blob 物件的档名就是用上述的方式计算出来的,从这些 blob 档案,你看不出跟版本有任何关系,你必须透过 tree 物件 (资料夹的快照) 与 commit 物件 (每一个版本的快照) 才能关联出这些 blob 与版本的关系。
所有的物件都会以 zlib 演算法进行压缩,不但可以有效的提升档案存取效率,在日后进行封装(pack)的时候也可以利用差异压缩(delta compression)演算法来节省空间。他会自动找出相似的 blobs,并自动计算出 blob 之间的变化差异,再将这些差异储存在一个名为 packfile 的档案中,这样就可以大幅节省磁碟空间的耗用)。通常 packfile 会置于 .git\objects\pack 目录下,如下图示:
上述这四种物件之间的关系,可参考以下图示:
然而,光是观看文字与图示,或许还是难以看出这几种物件类型之间的关系,没关系,笔者特别录製了一段教学影片,试图用 git 指令的方式解释 Git 的物件结构与产生物件的过程,也让各位更清楚的了解到底 Git 如何产生与管理这些档案。
YouTube 影片链接:认识 Git 资料结构中的物件资料库与物件之间的关系
你应该可以渐渐了解 Git 的「物件」设计是如此的漂亮,我们在第一篇文章曾经提到几个 Git 重要的设计,我们重新列出几点与「物件」特性有关的设计来看看:
Git 裡的「物件」十分重要,其特性也十分重要,虽然我们在操作 Git 指令的过程中通常不太需要直接接触这些档案,不过了解这些物件的存在,也确实有助于让你更加理解 Git 的运作模式,与 Git 独到的设计概念。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8