git merge合并后自己/别人代码丢失原因分析及解决方案

1.问题

最近合并代码时发生了几次“不明确行为”,有时候发现自己的代码莫名的丢了,有时候发现合并后别人的代码静悄悄的丢了,

  • 代码丢失本身就是比较严重的问题;
  • 更让人捉急的是这种情况是静悄悄的发生的,可能当时还发现不了,等到发布到线上几天后使用时才可能发现错误!然后再追踪定位问题,颇费周折;
  • 为什么自己/别人的代码静悄悄的丢掉了?真的是“不明确行为”吗?

2.原因分析

2.1.先来看一个场景

当local和remote中文件file1的line270内容不一样时会发生什么?

  • 自动合并?保留local的还是保留remote的?
  • 提示冲突?

我们好像知道在进行合并时,如果local和remote都修改了同一个地方,那么会发生冲突,

是的,那么怎么判断两个分支的某一个地方都修改了呢?是需要一个参考分支的,在git中这个参考分支是两次提交的最通用的祖先节点,即base分支(可用git-merge-base local remote获取),

有了参考分支就可以进行three-way比较和合并了,想一想一些对比软件为什么提供了三路对比?我只需要对比两个文件啊!?

2.2.继续分析

经过上述背景中场景的了解后,我们知道了git合并时需要三路对比的,即base、local、remote对比,根据不同的对比情况进行不同的处理:自动合并还是提示冲突,

我们带着这个问题来看,merge的结果是git会自动合并,因为相对于base来说,只有local分支修改了file1/line370的内容,自动合并的结果是“fine1/line370:这是小强干的”,

当然,如果base的内容是“fine1/line370:这是小强干的”,那么自动合并的结果会变成“fine1/line370:这是小度干的”,这是为什么?

2.3.合并原理

  • 对于base来说,local和remote都是派生出来的分支,都可能会修改base的内容,这个意义上来说,local和remote是同优先级别的,也就是程序员A合并程序员B的代码(B先手提交了)和程序员B合并程序员A的代码(A先手提交了)行为是一样的。
  • 如果local的file1/line370的内容和base一样,remote却不一样,那么即可认为是remote对该内容进行了更新,合并时候以remote的file1/line370内容为准进行自动合并。反之亦然。
  • 如果local和remote都对file1/line370进行了修改,那么这时候不知道要保留谁的修改了,就会提示合并冲突,让用户自己决定要保留哪个修改。

在正常情况下这个自动合并规则没有问题,多个人开发,你开发你的功能,我开发我的功能,合并之后就是咱们的,不论是你先提交还是我先提交。

但是某种意外的情况就不一样了,出现的结果是local合并remote的代码,发现local自己的修改被覆盖掉了(local丢代码)!或者发现自己把remote的功能给“回退了”(remote丢代码)!

这种意外回事什么样的?直接分析,就是base分支出问题了,更直白点就是分支管理出现了混乱,导致了不明确行为:local丢代码或者remote丢代码。

那么出现这种现象后该怎么处理来保证local和remote各自开发的的代码都保留下来?

3.解决方案

发生上述丢代码的场景了,那么怎么办?

3.1.方案一:通用方案

此方案可读性及可控性高,实施起来效率高,并且自己心里踏实~,如果你想让自己心情愉快平稳一些,那么推荐此方案。

  1. 先终止合并;
  2. 这个时候就不要再次用git自动合并了,因为还是和之前一样,因为base分支有问题了(比如local或remote基于错误的分支进行的开发,计算出了不可预想的base分支);
  3. 可以借助第三方工具来进行三路比较与合并,如vsDiffMerge.exe、WinMerge等,方法就是绕过自动合并过程,自主的去选择要保留哪些;推荐用vs自带的vsDiffMerge.exe;
  4. 首先下载base、local、remote的冲突的各自文件,为三路比较和合并做准备;
  5. 使用vsDiffMerge.exe时注意命令形式:vsdiffmerge.exe "File1" "File2" "Base file" "Result file" /m
  6. WinMerge也有类似的功能;

3.2.方案二:手动方案(不推荐使用)

如果发生了代码丢失,但自己本次开发的代码量很小,则可以基于最新的分支checkout新的feature分支,将自己开发的代码再次在新的feature分支上CV修改一遍;

这个过程也可利用上述对比工具参考自己修改的内容进行CV。

4.其他

tips:

  • checkout origin branch;git checkout origin/develop -b develop

  • Compare files
  • git比较不同和vs比较不同是不一样的,vs的更详尽一些,方便用户对比
  • visual studio自带了一些工具来方便工作,当然也有第三方开发的VS插件,可以合理利用;

5.结论

  • 出现上述原因明确的“不明确行为”的根本原因还是分支管理不规范或是实施不规范,为了让大家心情愉快,按时交付,开心工作,平稳输出...吃喝玩乐,有时间找对象/陪对象,那么还是建立起完善的分支管理和开发规范吧,磨刀不误砍柴工,退而结网~;
  • 如果出现了上述行为,那么采取上述方案也能把风险控制到可控且在解决问题的过程中感觉自己又学会了一招,经验增长了,美哉~;