【发布时间】:2021-10-16 05:51:46
【问题描述】:
假设我们使用Gitflow,我们从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,我们将再次遇到版本冲突。
方法一——樱桃采摘?
对不起,我不会这样做。 我经常读到樱桃采摘是邪恶的。 他们会反对 Gitflow。
- http://www.draconianoverlord.com/2013/09/07/no-cherry-picking.html
- Git - Is cherry-picking a bad practice if I want to have a consistent workflow?
- https://medium.com/@vitalishcharbin/danger-of-cherry-pick-42a56141577f
- Why does cherry-picking make the repo unstable?
方法 2 -- 接受手动解决?
这就是我们现在所做的。该过程不是自动化的。每次更改release 中的版本号时,以下合并都会出现必须手动解决的冲突。我们接受它,但对此不满意。
方法 3——不要那么频繁地合并?
我想那将是不好的做法。我们希望将质量改进合并到我们所有的分支机构。
方法 4 -- 使用合并选项 --ours 或类似选项?
问题是合并冲突的自动“解决”是基于文件的,据我所知,不是基于行或基于块的。
我们需要保留来自develop 的版本号,但是这些文件中的其他更改 pom.xml 或package.json 可能位于任一侧并且不能被盲目地覆盖,因此我们会处理此类冲突想要手动查看和解决。
不过,我愿意接受这方面的任何建议!
方法 5 -- 将版本号移动到单独的文件中?
通过这种方式,我们会将冲突减少到一个可以使用--ours 轻松解决的位置。
虽然使用较新的 Maven 版本似乎是可能的,但我不知道 package.json 引用外部定义的版本号的方法。
有没有人在这方面有很好的经验,并会推荐这种方式走得更远?
方法 6 -- 在 develop 中准备和重置版本?
我看到jgitflow-maven-plugin 的这种行为已经超过 6 年没有维护了。我们可以在develop 中提交,将release 版本写入文件,然后合并,将版本改回原来的版本。
我不喜欢有与实际开发无关的额外提交,而且我认为不可能清理 Git 历史记录。
所以这将是一个有趣的后续问题:我知道我可以将 D 变基/压缩为 C,但我不知道如何将 A 或 B 变基/压缩为 C。还有其他人吗?
-----B---------
\
---A---C---D---
方法 7 -- 在 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
搜索网络告诉我存储本地更改,但这当然不是一种选择。
方法 9 -- 编写程序来解决冲突?
我认为这些冲突结构良好,甚至可以完全预测,因此应该可以编写一个小的 shell 脚本来 grep/sed 冲突,以便自动解决并提交合并。 但我犹豫着在这里付出巨大的努力,希望得到其他人的启迪!
【问题讨论】:
标签: git merge version release merge-conflict-resolution