一、blob、文件哈希值、tree、commit?

在一个 git 项目中,必然会包含这四个对象,那么这四个对象到底是什么呢?包含关系又是什么?所占用空间到底多大?

1、概念

  • blob:是一个二进制对象。在计算机中,所有的东西都是由 0 和 1 组成,而这些 0 和 1 组成的一串数字被称为 字节序列。一个 blob 对象就是一个字节序列,即 git 存储的是一个文件底层用 0 和 1 存储的字节序列,在工作区看到的文件是 git 通过解析这个二进制文件而呈现出来的。包含具体文件内容,体量很大。
  • 文件哈希值:通过计算这个二进制文件得到一个唯一的哈希值,这个哈希值会唯一对应这个文件,因为不同的文件所计算出的哈希值是不同的,因此可以将这个哈希值作为唯一识别这个文件的数字指纹。只是一串数字与字母的组合,体量很小。
  • tree:在 git 中,必然会包含一个 tree 对象,它记录了这个项目中每个文件的 权限所属类型对应哈希对应文件名。不存储具体的文件内容,每个 tree 也有对应的哈希值。是一个对象,体量也很小。
  • commit:在 git 中,必然会包含一个 commit 对象,它记录了当前的 tree 哈希值,父 commit 哈希值,作者名。每个 commit 也有一个哈希值。是一个对象,体量也很小。

2、包含关系?

可以将 commit 对象 理解为一个寻找 tree 对象 的图纸,而 tree 对象 是寻找具体文件对应 文件哈希值 的图纸。而 哈希值 是寻找具体的文件的图纸,是一个层层包含的关系。

二、具体的流程?

当有了一个 commit 号 即 commit 哈希值 的时候,就可以通过这个哈希值,在仓库中找到对应的 commit 对象,通过读取 commit 对象 中的 tree 哈希值,再次寻找到对应的 tree 对象。通过读取 tree 对象中的 blob 对应的文件哈希值,再次找到真正的对象 blob

三、修改的时候具体哪些发生了变化?

  • git 保存的时候所有被跟踪状态的文件。当我们克隆一个仓库的时候,所有的文件均已处于被跟踪状态。而新添加的文件就必须使用 add 使其处于被跟踪状态。
  • 当我们具体对一个文件内容进行修改的时候,其底层的字节序列已经发生了改变,是一个全新的 blob 对象。因此会产生对应的全新的 文件哈希值。同时会生成一个新的 tree 对象 记录当前整个项目中所有文件对应的哈希值。而同样的每一次的 commit 都会进行更新,因为每次的commit 对象记录的 tree 哈希值 是不同的。
  • 值得注意的是,当对一个文件具体修改之后并 add 进暂存区,就会产生新的 blob 文件,而旧的 blob 文件不会覆盖。因此,即使是改动了一个逗号,也是会产生两个基本完全相同只是有一处逗号不同的两个文件。
  • 所以在改动一个文件的时候,这些所有的对象全部都会更新,但要注意的是:是会产生新的对象,而非对原先的覆盖

四、push 的机制?

需要清楚的是,我们所有的 add - commit 都是保存到了本地仓库上。而 push 是将本地 Git 仓库中 远端没有的对象传输给远程仓库,并请求远程将分支指针更新为新的 commit 哈希。

五、分支的机制?

  • 分支的本质是一个存储某一个 commit 哈希值 的文本文件。创建分支就是生成了一个记录当前 commit 哈希值 的文本文件。
  • git 中有一个指针称为 HEAD 指针,指向了当前所处分支。
  • 所以分支的切换就是让这个 HEAD 指针指向某个分支。
  • 值得注意的是,每个分支之间的 commit 是互不影响的,而一个分支上可以有多个 commit

六、仓库、分支、四个对象之间的包含关系?寻址流程?

  • 由此我们可以理解到,仓库 包含大量 分支 -> 每个分支内容是一个具体的 commit 哈希值 -> 每个 commit 哈希值 对应一个 commit 对象 -> 每个 commit 对象包含了 tree 哈希值 -> 每个 tree 哈希值 对应一个 tree 对象 -> 每个 tree 对象 包含了整个项目中所有被追踪文件的 blob 哈希值 -> 每个 blob 哈希值对应了某一个具体的 blob 对象 -> 每个具体的 blob 对象是一个字节序列。
  • 通过读取仓库存储分支的文件中的分支内容,找到 commit 哈希值;再通过 commit 哈希值 在仓库存储 commit 对象 的文件中找到 commit 对象;再读取这个对象找到 tree 哈希值;再在仓库存储 tree 对象的文件中刚找到 tree 对象;再读取这个对象找到 blob 哈希值;再在仓库存储 blob 对象的文件中找到对应的 blob 文件;再通过解析这个二进制文件,呈现内容。

七、合并?冲突?

  • 合并的意思是,找到两个分支中所记录的相同的最近共同祖先 commit,查看对应的文件是否兼容,如果兼容,那么就会产生一个新的 特殊 commit 哈希值、commit 对象 tree 哈希值、tree 对象 。
  • 产生冲突的原因就在于,在产生的这个特殊 tree 对象不知道要记录哪个具体 blob 文件对应的哈希值。
  • 可以通过 git rebase 查看哪里产生了冲突,并进行选择保留。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐