拉取合并本地feature分支后无法git push至Gerrit的问题
咱们先拆解下你遇到的问题根源——这其实是Gerrit的工作机制和常规Git推送逻辑不一样导致的。
问题到底出在哪?
你本地用git merge拉取远程develop并生成了合并提交(m),但Gerrit的refs/for/develop这个推送目标,本质是用来提交待审核的变更集,它不是直接接受你本地的分支状态,而是会尝试把你提交里的「原始变更」(也就是你的(1)(2)这两个提交),重新应用到远程develop的最新版本上。
Gerrit默认不喜欢合并提交(除非团队特意配置允许),它希望每个待审核的变更都是基于远程最新分支的线性提交。所以当你推送时,Gerrit并不会去检查你的合并提交(m)和远程的兼容性,反而会去对比你的原始提交(1)(2)和远程刚更新的(3)(4),自然就会提示冲突了。
更适配Gerrit的处理方式
既然知道了原因,咱们换个更顺的姿势来处理:
1. 优先用rebase替代merge同步远程代码
以后要同步远程develop时,别用merge,改用rebase:
git fetch origin develop git rebase origin/develop
这个操作会把你的(1)(2)提交「搬」到远程develop的最新版本(包含(3)(4))上面,生成两个新的提交(1')(2'),你的本地分支历史会变成完全线性的,没有合并提交。这时候再推Gerrit,它就会直接检查这两个新提交和远程的兼容性,不会再揪着旧提交(1)(2)找冲突了。
2. 已经做了merge?这样补救
如果你已经不小心做了merge生成了(m),也不用慌:
执行git rebase -i origin/develop进入交互式rebase界面,把合并提交(m)那一行删掉,然后保存退出。Git会自动帮你把(1)(2)重新应用到远程最新分支上,你再解决可能出现的冲突(如果有的话),最后推Gerrit就行。要是你的(1)(2)是相关的小变更,还可以在交互式界面里把它们squash成一个提交,减少审核的负担。
3. 允许合并提交?不推荐!
如果你的团队真的有特殊需求要保留合并提交,可以去Gerrit的项目设置里开启「Allow Merge Commits」。但我得提醒你,这样会让分支历史变得乱糟糟的,后续代码审核、问题追溯都会变麻烦,所以除非必要,别这么干。
最后总结下
Gerrit的推送逻辑是「重新应用变更集」,不是直接接受本地分支状态,所以merge出来的合并提交不会被它优先处理。用rebase保持分支线性,才是最适配Gerrit工作流的方式,既能避免你遇到的这种冲突提示,还能让代码历史更清晰好懂。
内容的提问来源于stack exchange,提问作者shelper

