Git 的十年变化(六)|学习笔记

简介: 快速学习 Git 的十年变化(六)。

开发者学堂课程【Git 从入门到进阶Git 的十年变化(六)】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/1194/detail/18120


Git 的十年变化(六)


通过一次线上故障,了解 git 合并的三路合并原理,git 合并提供了多种合并开关:快进式、非快进式、压缩等。想要清晰的合并历史,非快进式可能是你想要的,由一次网络上面的线上故障,开始给大家讲解一下3路合并原理,然后再展开讲一下 git 的几种合并方式,分别包括快进式合并压缩合并以及非快进式合并最后再给大家做一下总结

image.png

这里有一个线上事故的一个示例。就是某一个特性上线之后呢,发现和的代码并不完整,有部分代码没有河流的主线,最终导致了一些非预期的问题。这里的代码合并是这么操作的,首先,代码的提交历史如右图所示,特性分支是 dev 是 master 开发同学在A3的时候把 dev 合入到了 master。然后过了一段时间发现dev上面的A1 A2 A3 AN3时提交有 bug,这时候负责 Musk的同学在B8的时候撤回了A1 A2 A3的提交,使用的命令是 git revere ,然后开发同学基于在第一批分支上面做迭代开发,最终在A6的时候。又再次合并到的 master,这时候就出现问题了,b10上没有A1 A2 A3的改动,正常来讲A1 A2 A3都在第一批分支上面,为什么合并到 master 后反而没了呢?这个问题需要从 git 的3路合并原理来分析。那什么是3路合并呢?3路合并的山路指的是基线、对方、我。“对方”指的是打算要合并的提交或者分支。指的是要合并的目标提交或分支,基线则是两者的共同的父级提交。

image.png

对于文件一如果三者都没有改变的话,那结果就是没有改动的。对于文件二和文件三,如果只是有一方改动,那结果就是改动后的,对于文件四,如果两者都有改动,但改动的不是同一个地方或者同一行,那这时候 git 会自动做合并,保留2的改动。对于文件五和文件六。如果一方删除的文件,另一方改动文件,这时候就会产生合并冲突。git 他会显示的标记重复代码,然后提示开发同学解决冲突。对于文件7两者新建了2个路径相同的文件,这种也算是冲突,也需要开发同学去解决,这就是这个合并规则,回过头来看,这个线上事故,对于A6“我”是B9,他们的基线是A3,套用刚才讲的3路合并的规则就可以发现问题,比如如果有一个文件,A3上市X1 ,A6上也是X1,他B9,因为撤销了A1、A2、A3上的改动导致没有的问题。同理,对于文件二最终合并结果也是采用B9的感动,也就是说合并的结果确实是没有A1 A2 A3这3个提交的,总的来讲记得是不会出错的,错的还是使用git的方式不正确。

那这种情况该如何避免呢?有很多种方式,比如在第一分支上面做 revent, 将dev合入主干撤销 dev 之前的改动,然后在 dev 上面继续开发,或者 dev 分支基于B8提交重建,然后 cherry-pick dev 提交。

(2)git合并方式

git有3种和平方式分别是快进式合并非快进式合并以及压缩合并,快进式合并是git默认的合并方式,如果这次合并,可以做快进城合并的话,记得就采用快进式合并快进式。可以看到这时候合并。并不产生新的提交,而是做简单的指针移动。

对于快进式合并,另外一种情况,两个分支上都有新的提交,这种情况下不能做快进合并,这时候给他会找到它们的共同祖先设节点,然后再坐三路合并。可以看到最终会产生一个新的提交M分别指向源分支和目标分支。这时候,如果你输入git log命令看提交结果,也可以直观的看到合并的结果。对于快进式合并会出现两种合并结果,这个怎么理解呢?打个比方,比如我们要合作协议一大篇文档,然后有个叫张三同学在15号和17号这2天分别写了两小张,管理员要把这两小张合并到文档里面,这时候就会出现两种情况了,如果发现15号之后没有人更新文档,那管理员就直接把账上写的挑战放到文档里面,不会去做过多的说明。

如果发现15号之后有人去更新文档的,那管理员除了把张三写的两小张放到文档里面还会额外备注一下,这是做了合并操作的。然后这里面呢?那两张是张三写的,这就是快进式合并的逻辑。然后是压缩合并,顾名思义,压缩合并,也就是说会去做压缩处理。

压缩合并需要显示的指定刚刚 squash 的这个参数。

image.png

可以看到 git 会把源分支和目标分支不一样的提交都压缩成一个提交M。通过 git log也可以看到结果。这里还是套用刚才合作写文档的例子来讲,管理员使用压缩合并的方式,会把张三写的两小张合并成一张,然后放到文档里面,最后再做一下备注。整个来讲的话也比较简单,但是在 git 里面和压缩合并其实并不常用。

因为他不会把你的历史提交会丢弃掉很重要的一些提交说明,这也是不推荐大家使用压缩合并的原因。那压缩合并适合什么样的场景呢?比如说某个产品要开原通过压缩合并,可以隐藏较历史的敏感提交信息,或者开发分支,有一些没有意义的提交。

也可以使用压缩合并来进行整理。另一方面,有些人使用压缩合并可能只是为了让提交历史看起来简洁高效。我这里推荐 git log 命令的一个参数“--first parent”它可以达到相同的效果,比如拿给的源码距离下边的 git log 看起来一团乱麻,下边是使用--first parent 参数看起来是不是清晰很多第3种合并方式非快进式合并需要显示的指定—no-ff 这个参数,它会始终创建合并节点,不管能不能做,跨境式合并。

合并过程跟刚才讲的第2种快进式合并方式是一样的,可以看到最终生成一个新的提交

image.png

从 git log 命令也能看出来,合并结果非快进式合并是代码平台常用的一种合并方式,因为它会创建合并节点,很容易去追溯这个代码的合并历史

总结

第一个就是通过一次线上故障的分析,给大家讲解了一下 git 的3路合并原理,第2个就是给大家讲解了 git 的3种合并方式,分别是快进式合并非快进式合并以及压缩合并,然后压缩合并会。

丢弃掉你的提交历史信息,大家需要谨慎使用。那么如果你想要清晰的合并历史,推荐使用非快进式合并,因为它会产生合并节点。最后还有一个彩蛋啊,大家在使用新版本的git,如果没有设置 pull.rebase 或者 pull.ff 的话,运行期的 git pull 总是会出现这样的一个告警。

image.png

这是因为 git 希望你告诉他使用什么方式来进行合并,那如何去掉这个警告呢?设置pull.rebase为 false 就好了就是让 git 使用默认的和平方式

相关文章
|
3月前
|
Shell 网络安全 开发工具
Git学习笔记
Git学习笔记
79 1
Git学习笔记
|
7月前
|
Linux 网络安全 开发工具
Git学习笔记
Git学习笔记
57 0
|
8月前
|
Linux 网络安全 API
git常用命令学习笔记
git常用命令学习笔记
45 0
|
9月前
|
程序员 开发工具 git
搭建博客可能会用到的 Git 命令|学习笔记
搭建博客可能会用到的 Git 命令|学习笔记
|
10月前
|
算法 安全 Linux
git第n次学习笔记
git第n次学习笔记
71 0
|
项目管理 开发工具 git
Git学习笔记(三) git submodule
Git学习笔记(三) git submodule
125 0
|
缓存 开发工具 git
Git学习笔记(二) git stash
Git学习笔记(二) git stash
861 0
|
开发工具 git
Git学习笔记(一) 常用命令
Git学习笔记(一) 常用命令
104 0
|
缓存 Linux 程序员
【学习笔记之Linux】工具之make/Makefile与git
【学习笔记之Linux】工具之make/Makefile与git
177 0
|
开发工具 git 索引
Git学习笔记-详细使用教程
Git学习笔记-详细使用教程
Git学习笔记-详细使用教程