Git 中的工作机制?冲突是如何产生的?如何解决?
·
一、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查看哪里产生了冲突,并进行选择保留。
更多推荐




所有评论(0)