在开发过程中,我们的版本管理方式是,一版本一分支。之所以这样,是因为随着开发的进行,版本随时会分叉(这里分叉是指,两个版本都需要后续开发,但是对同一模块的功能需要不一样的微调)。
随着分叉之后的持续开发,就会导致多个分支之间差别越来越大。因此,如果所有版本都添加同样功能或修改同一个Bug时,是不可以采用git merge的方式来进行的。因为很难找到他相同的父节点。这时patch会是一个很好的工具。
而这次事故正是git patch功能使用不当引起的,下面来模拟出一个完整的事故现场。
在最开始我们有一段原始代码如下,可以明显看到,在第18行代码中,将dst错打成了src。
以此次commit为节点,分切出分支ver1和ver2。
然后在ver1分支上修改上述错误并使用git commit提交,由于也许有很多并行版本都有这个问题,一个一个去改很消耗时间还容易错。因此可以使用`git formatch-patch HEAD~1`来制作一个patch文件,我们得到的patch文件内容如下:
切到ver2分支后,先手动将18行修改提交一次,再使用`git am 0001-bugfix.patch`来重复修复这个Bug。
预期中,执行完git am之后,只有两种情况。一是这个文件完全没有变化,二是会出现conflict。
然而,事实并没有想象中的那么美好,执行完git am之后,第7行的src被改成了dst。
以上基本就是整个事故的全部还原过程。
这种事故很难发现,一旦发现却很容易就知道原因。
分析一下patch文件,就会立即发现,整个patch行为是靠以下7行代码来定位的。
恰巧,由于在git am之前,我手动修改了这一行,导致在执行git am时,不可能会匹配到这一块出错的代码。更巧的是,git可以使用个patch中的代码块匹配到第4行的代码,即然匹配成功了,git自然就会将修改应用。
从这个事故中,可以得到几点启示。
patch并不是100%可靠的,执行之后最好查看一下结果
2. 大扩号另起一行,对版本管理工具不友好:D
3. DRY原则 不但对人适用,对版本管理工具同样适用
ps. 如果实在没有办法,就尽量扩大git diff输出的代码块大小,`git config –global diff.context 30`即可把代码块增加致30行
领取专属 10元无门槛券
私享最新 技术干货