git merge原理

快照

git merge原理_第1张图片

这是项目的三个版本,版本1中有两个文件A和B,然后修改了A,变成了A1,形成了版本2,接着又修改了B变为B1,形成了版本3。

如果我们把项目的每个版本都保存到本地仓库,需要保存至少6个文件,而实际上,只有4个不同的文件,A、A1、B、B1。为了节省存储的空间,我们要像一个方法将同样的文件只需要保存一份。这就引入了Sha-1算法。

可以使用git命令计算文件的 sha-1 值。

echo 'test content' | git hash-object --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4

SHA-1将文件中的内容通过通过计算生成一个 40 位长度的hash值。

Sha-1的非常有特点:

  • 由文件内容计算出的hash值
  • hash值相同,文件内容相同

对于上图中的内容,无论我们执行多少次,都会得到相同的结果。因此,文件的sha-1值是可以作为文件的唯一 id 。同时,它还有一个额外的功能,校验文件完整性。

有了 sha-1 的帮助,我们可以对项目版本的存储方式做一下调整。

git merge原理_第2张图片


Conflicts

git 中的分支十分轻量,因此我们在使用git的时候会频繁的用到分支。不可不免的需要将新创建的分支合并。

在 git 中合并分支有两种选择:merge 和 rebase。但是,无论哪一种,都有可能产生冲突。因此我们先来看一下冲突的产生。

git merge原理_第3张图片

图上的情况,并不是移动分支指针就能解决问题的,它需要一种合并策略。首先,我们需要明确的是谁和谁的合并,是 2,3 与 4,5,6的合并吗?说到分支,我们总会联想到线,就会认为是线的合并。其实不是的,真实合并的是 3 和 6。因为每一次提交都包含了项目完整的快照,即合并只是 tree 与 tree 的合并。

我们可以先想一个简单的算法。用来比较3和6。但是我们还需要一个比较的标准,如果只是3和6比较,那么3与6相比,添加了一个文件,也可以说成是6与3比删除了一个文件,这无法确切表示当前的冲突状态。因此我们选取他们的两个分支的分歧点(merge base)作为参考点,进行比较。

比较时,相对于 merge base(提交1)进行比较。

首先把1、3、6中所有的文件做一个列表,然后依次遍历这个列表中的文件。现在我们拿列表中的一个文件进行举例,把在提交1、3、6中的该文件分别称为版本1、版本3、版本6。

  1. 版本1、版本3、版本6的 sha-1 值完全相同,这种情况表明没有冲突
  2. 版本3或6至少一个与版本1状态相同(指的是sha-1值相同或都不存在),这种情况可以自动合并。比如1中存在一个文件,在3中没有对该文件进行修改,而6中删除了这个文件,则以6为准就可以了
  3. 版本3或版本6都与版本1的状态不同,情况复杂一些,自动合并策略很难生效,需要手动解决。我们来看一下这种状态的定义。

你可能感兴趣的:(版本管理)