develop
分离出一个发布分支,最终将合并到main
和develop
中。
在release
分支上,只有质量改进。大部分需要部署到集成阶段,因此它们在多个pom.xml
(多模块)和package.json
中的版本都会被更新,并在release
分支上进行标记。在
develop
分支上,有未来版本的常规(不稳定)功能开发,并相应地设置了版本号。
偶尔,从release
中合并的改进会回到develop
分支。这时会出现合并冲突,在下图中用X标注。main ----------------------o----
/
release o---o-----o-o-o
/ \ \ \
develop ----o---o---x--o--x-o-x----
^
we are here |
示例:
- 在
release
时,版本号为1.0.0-SNAPSHOT
。 - 在从
develop
分支出来后,版本号变为1.1.0-SNAPSHOT
。 - 新功能添加到
develop
中,版本号保持不变。 release
中的版本会偶尔增加(并打标签)到1.0.1
、1.0.2
、1.0.3
等。- 当我想将版本1.0.x合并到1.1.0时,由于公共祖先是1.0.0,所以会产生冲突。
- (我们完全理解发生了什么,不需要解释。)
$ git checkout develop
$ git merge --no-commit --no-ff release
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
...
Auto-merging client/package.json
CONFLICT (content): Merge conflict in client/package.json
Automatic merge failed; fix conflicts and then commit the result.
我们正在寻找处理这种情况的想法。一些研究表明这不是一个罕见的问题,所以我找到了几个建议。大多数情况下建议手动解决冲突。但我仍然渴望找到一种可以在脚本中自动化的方法。也许有一些 Git 魔法可以帮忙?也许我们一开始就做得不好?
以下讨论更好地说明了这个问题,我们处于“仅错误修复!”状态:
方法0 -- 不要这么做?
自从我们团队开始采用这种版本增量和标记的方式,我一直不确定这是否是一个好的实践。但基本上它是有效的,我们一起定义了工作流程的细节,并且我们的客户、合作伙伴和测试团队要求我们发布候选版本,就像它们是实际发布的一样。当版本x.y.z经过成功测试后,它不会被改变地发布到生产环境中,然后将release
合并到main
中。但问题仍然存在:一旦在main
中进行了热修复,并且需要将其回滚到develop
中,我们又会遇到版本冲突。
方法1 -- 挑选代码?
抱歉,我不会这样做。 我太经常看到挑选代码的坏处了。 而且它们是违反Gitflow规范的。
- http://www.draconianoverlord.com/2013/09/07/no-cherry-picking.html(链接1)
- Git - Is cherry-picking a bad practice if I want to have a consistent workflow?(链接2)
- https://medium.com/@vitalishcharbin/danger-of-cherry-pick-42a56141577f(链接3)
- Why does cherry-picking make the repo unstable?(链接4)
方法2--接受手动解决?
这就是我们现在所做的。该过程并未自动化。每次更改release
中的版本号时,以下合并都会出现冲突,必须手动解决。我们接受它,但对此感到不满意。
方法3--不要那么频繁地合并?
我想这将是不好的做法。我们希望将质量改进合并到所有分支中。
方法4--使用合并选项--ours
或类似选项?
问题在于自动“解决”合并冲突是基于文件的,从我所了解的情况来看,并非基于行或块。
我们需要保留develop
中的版本号,但是这些文件pom.xml
或package.json
中的其他更改可能在任一侧,不能盲目地覆盖这些更改,因此这些类型的冲突我们希望手动查看和解决。
我虽然愿意接受任何关于此方面的建议!
方法5--将版本号移至单独的文件中?
这样一来,我们就可以将冲突减少到一个单一的位置,可以使用 --ours
轻松解决。
虽然较新的 Maven 版本似乎可以实现,但我不知道如何在 package.json
中引用外部定义的版本号。
有人尝试过这种方法并且推荐继续走下去吗?
方法六 -- 在develop
中准备和重置版本?
我看到了 jgitflow-maven-plugin
的这种行为,该插件已经超过6年没有维护了。我们可以在 develop
中提交一个写入文件的 release
版本的提交,然后合并,并将版本更改回原始版本。
所以这将是一个有趣的后续问题:我知道我可以将D变基/压缩成C,但我不知道如何将A或B变基/压缩成C。还有其他人知道吗?
-----B---------
\
---A---C---D---
方法七 -- 在release
分支中准备版本?
类似于之前的方法,我们可以在release
分支上提交一个版本号,然后将其合并到develop
分支中,避免冲突。这样,我们就不需要在release
分支中进行还原提交,只需使用git reset --hard HEAD^
命令将分支指针移回即可,或者干脆不推送该提交,这样准备提交就位于两个分支之间。
-----B-----------
\
B'
\
---A-----C---D---
以下文章描述了使用中间分支来完成拉取请求的类似事情,但这需要几个手动步骤,不能解决我的问题。
- https://medium.com/@jshvarts/dealing-with-conflicts-when-merging-release-to-develop-da289a572f0d
- https://www.reddit.com/r/git/comments/e7zwl6/dealing_with_conflicts_when_merging_release_to/
方法8 -- 准备未提交的版本?
我最喜欢的解决方案是在本地 develop
分支中编写目标版本,但不进行提交,然后将 release
分支合并到该分支上... 但是 git merge
不允许这样做。我没有看到任何开关可以覆盖此行为并忽略未合并的内容。
error: Your local changes to the following files would be overwritten by merge:
client/package.json
...
pom.xml
Please commit your changes or stash them before you merge.
Aborting
我在网上搜索发现需要隐藏本地更改,但这当然不是一个选项。
方法九 -- 编写程序解决冲突?
我考虑这些冲突是有结构的,甚至可以完全预测,因此应该可以编写一个小的shell脚本来grep/sed冲突以自动解决并提交合并。但我犹豫是否要在这里付出大量努力,希望其他人能给我启示!
git merge -X ours
或类似的方法(不确定-X ours
是否适用于Rerere)。对于自定义合并策略,请注意我提供的链接已经为pom.xml
提供了解决方案。大多数项目只在1或2种不同的文件格式(例如package.json
)中存储版本,因此如果您只需要第二个实现,那么这似乎是可以接受的。 - Didier L