近期服务端这边出现了几次代码合并丢失的问题,结果导致一次线上P1故障,一次推迟试验结果出数据,问题很严重。所以回顾一下,期望以后不要再躺在了同样的坑里面。
近期丢代码事件
- A同学误操作将测试中dev分支合并到master,然后在master上revert该mr,然后该mr前的dev分支上的所有commit丢失,合并不回master、
- A同学 误导操作,将hot fix c1合并到master,然后在master revert该mr,然后将c1合并到dev分支,B同学操作合并master到dev,这个时候没有任何冲突,但是导致c1代码丢失,导致线上获取session失败,产生did替换uid,导致推荐画风突变故障
- A同学 revert操作idl,B同学master合并到dev, 代码丢失
- A同学 合并master代码时候,conflict冲突,选择了accept master,导致线上试验一直没有数据故障
- A同学 thrift 生成的代码,合并到master后,发现丢弃部分自动生成的client代码
- A同学 误操作、删除了很多idl接口定义、
问题原因
revert_13">1. revert操作
原因:revert操作的语义
这里上面的master分支、下面的是dev分支,dev合并到M后,发现错误,在W做revert操作、然后在C、D修复这个错误,这个时候,A、B的代码是没办法合并回master的。
revert操作W后,不管是master->dev 、dev->master操作,A、B这部分被revert的commit都会丢失、
revert 其实是一次反向 commit 的提交,并没有改动原有的 commit,直接提交的话,git 能看到这个 commit 的 hash 已经被 merge 过了,所以就 merge 不进去了。
A -> B -> C -> RB ->D,Revert B 其实是新增了一次 RB,并没有改动 B
Linus大神对revert的语义解析:
Reverting a regular commit just effectively undoes what that commit
did, and is fairly straightforward. But reverting a merge commit also
undoes the data that the commit changed, but it does absolutely
nothing to the effects on history that the merge had.
So the merge will still exist, and it will still be seen as joining
the two branches together, and future merges will see that merge as
the last shared state - and the revert that reverted the merge brought
in will not affect that at all.
So a "revert" undoes the data changes, but it's very much _not_ an
"undo" in the sense that it doesn't undo the effects of a commit on
the repository history.
So if you think of "revert" as "undo", then you're going to always
miss this part of reverts. Yes, it undoes the data, but no, it doesn't
undo history.
结论:谨慎revert操作; revert操作会导致该revert涉及到的代码再次合并到目标分支的时候,丢失代码
参考文献:https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
解决方案:
- 当出现误操作后,应该怎么办?
-
- 如果改动量比较小,可以使用hot fix替代revert操作,解决其中出现错误的commit,然后合并回
这里Y是对“Revert操作W”的 revert,也就是revert to revert ;然后在原来dev分支做继续修复工作,然后合并到master分支。
更多讨论,请参考这个文档:https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
总之:谨慎使用revert操作,除非你确实知道你在做什么。
- 删除未远程合并到其他分支的,个人开发分支commit
使用:rebase -i <删除某个commit>
其他删除某个commit的命令:
git reset: (等待补充)
2. Merge conflict误操作
- 当代码合并冲突后,需要原来代码开发者在场确认,选择最终需要的代码
3. 生成代码:
- thrift本地不是最新版本、导致丢弃client代码
- idl和代码文件需要在测试完后,同时提交到远程
- idl生成代码前需要预先拉取对应分支、线上idl代码、
4. 未完全测试的dev分支合并master
- 所有主干代码合并需要其他同学review、不允许自己review、合并自己分支代码 todo
5. 为什么合并过程没有发现丢代码?
单次合并代码太多,MR时、Review量太大,难以发现丢失代码的问题
- hot fix的代码:
- 不是很紧急的hot fix到dev分支,和dev分支一起发布上线
- 如果需要紧急上线的hot fix,hot fix合并到master后,需要同时合并到dev分支、
- 自动生成的代码:
- lift版本号统一,从而控制统一kitool工具、统一生成的代码和格式化代码、减少diff代码行数;请大家升级lift工具
MR时需要确认检查diff情况,包含自动生成代码中删除和冲突部分、
- lift版本号统一,从而控制统一kitool工具、统一生成的代码和格式化代码、减少diff代码行数;请大家升级lift工具
- 自动生成的代码,需要检查是否确实是自己修改idl生成的新代码,如果是因为工具版本不一致、fmt设置格式不一致,请找对应同学确认,然后大家对齐工具版本和fmt设置
6. 为什么Commit提交代码误删除操作没有发现
改进:提交代码前要求必须查看diff情况、
7. 代码冲突的几个建议:
- 接口定义放在合理的位置、
- 代码组织结构合理性、
以后改进建议:
- 以后谁在丢代码请大家喝饮料!!
参考文献:
https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
https://www.cnblogs.com/kwzm/p/10288684.html