我正在处理一个存储库,它的应用程序发布到三个不同的环境(开发、UAT和生产)。建立存储库的咨询公司有三个分支换句话说,uat
分支包含构建并部署到UAT环境的代码,dev
具有开发代码,main
具有生产代码。
此外,顾问还创建了一个工作流,以便合并主题分支(压缩提交)到dev
上,然后通过从dev
合并到uat
将代码提升为UAT(无快进合并),最后,通过从uat
合并到main
,将其提升为生产(无快进合并)。主题分支在合并到dev
时被删除。偶尔的修补程序通过直接提交到dev
,然后挑选相关的直接提交到main
来处理。
这种方法会导致一些问题。主要的缺点是所有的东西都必须在一个批次中进行升级,否则你需要挑选。如果我们在UAT中有三个更改,其中一个没有被批准升级,那么我们就不能升级另外两个,除非我们挑选,这很容易出错,而且坦白说很难看:当我们实际上想"挑选"掉被拒绝的10%时,为什么我们必须"挑选" 90%的更改呢?2这已经迫使我们推迟部署和发布,这并没有得到很好的接受。
此外,所有这些挑选修补程序的做法使得日志更难阅读,并且它跳过了拉取请求工作流,从而减少了文档和控制。另外,即使忽略挑选,提升uat
和main
的更改的拉取请求实际上也没有什么意义,因为它们只是将几个不相关的更改聚集到一个"提升"拉取请求中。
我的任务是找到一个延迟发布问题的解决方案,这个问题变得越来越阻塞,因为存储库托管了几个项目,而其中一个项目中失败的UAT测试实际上阻止了所有其他项目接收新批准的更改。并将它们独立地合并到每个环境分支中。这样,在UAT中被拒绝的项目A的变更将不会移动到生产中,但是项目B的变更仍将被允许合并到UAT中,独立地进行测试、批准并提升到生产中。
当然,热修复程序也应该用主题分支来处理,它们只会更快地提升。
几周前,当我与顾问们随意讨论这个问题时,他们说要找到一个好的解决方案"很复杂",因为存储库中的项目相互依赖(有一个UI项目、几个服务和几个库)。我认为这不是我提出的解决方案的问题,因为每个主题分支都是自包含的,并处理必要的依赖关系,但他们似乎并不倾向于这样做,尽管他们拒绝详细说明原因。
我的方法还可以改进拉取请求文档:虽然会有比我们现在拥有的更多的PR,但是可以打开将主题分支合并到main
中的PR,并立即了解生产中发生了什么。
顾问们的抵制和我自己在企业级Git工作流方面的经验让我犹豫是否支持我的提议。什么是在Git中管理多个环境的好(安全、易于记录、灵活)**方法?**我提议的解决方案的主要缺点是什么?
- 或者**,我会使用我在几个地方看到讨论过的模型,在该模型中,通过从目标环境分支进行分支来处理升级,从而形成类似于发布分支的东西,这样做的好处是不会因一项可能无法进一步提升的改变而污染环境部门(就像我前面的例子中项目A被拒绝的变更),但是对我来说它似乎更麻烦,我不确定它是否值得付出努力。
在我最初的提议中,分支my-feature
将合并到dev
,然后合并到uat
,最后合并到main
,这三个环境分支最终共享相同的历史(但是我不确定在非升级变更情况下会发生什么,在这个模型中,我必须从uat
分支出一个promotion/uat/my-feature
,然后从my-feature
合并到promotion/uat/my-feature
--但是我能做到吗?
1条答案
按热度按时间wn9m85ua1#
我想如果你足够勇敢,你可以通过暂时删除你不需要的10%,而不是樱桃采摘你需要的分支,使之更容易。
假设您要将
dev
提升为uat
,但不包含topicX
,后者已合并到dev
中,在
dev
上执行git revert -m1 <commit(s)-id-of-topicX-merge>
,以移除topicX
的变更。将
dev
合并为uat
。git revert <revert-commit-ids...>
在dev
上还原上一步中产生的rever-commit,以便在dev
上还原topicX
。这样,这些更改将在将来的潜在促销中可用。
您建议的工作流程(主题分支不会消亡并被合并,而不是精心挑选或压缩)实际上是我每天都在使用的。我认为值得一提的一些缺点是:
否则它们在合并时可能引入外部提交。
我们通过在
main
上创建新的主题分支来解决这个问题。另外,我们在发布后将
main
合并回uat
和dev
--这通常应该是一个无操作--以重新统一代码库/提交历史,并使未来的合并对git和我们来说更容易。另外:如果
topicX
需要的变更还没有在main
上,它必须将引入这些变更的topic-branches合并到自己的分支中。例如,它可能需要topicY
和topicZ
提供的类。然后,应将该依赖关系记录在票证系统中。
合并
topicX
也将合并其所有依赖项,这意味着必须记录在topicY
和topicZ
升级之前不能升级topicX
。应该用同样的方法解决。
由于您必须更频繁地进行合并,因此也会有更多的合并冲突需要解决。在
dev
上进行合并时发生的冲突可能会在uat
和main
上进行合并时再次发生。最糟糕的是:这些合并应该在
uat
上以与dev
相同的方式解决。* main * 也是如此。否则,您将在将来遇到更多的合并冲突,或者在此类升级过程中发生意外的行为更改。经验表明,人们偶尔没有给予足够的关注(或者只是基于主题分支的合并顺序,合并冲突的数量或内容不同)。
有时,一个被合并到 * dev * 中的topic-branch会被以不同的方式合并到 * uat * 中,等等。
特别是在压力下,人们喜欢忽视自己的勤奋。
然而,如果你 * 通常 * 只是将整个
dev
分支合并到uat
(如果这样的合并是一个开始的选项),而不是单个主题分支,那么我想这不是一个大问题。这可能导致混乱、性能问题和其它问题。
每个分支都有一个完整的合并历史记录是很好的,但是这是有代价的。合并图可能会变得相当宽(基于并行/长期开发的程度)。
向下滚动时,您可能会看到
git log --graph
比屏幕宽。这也会导致像git-kraken这样的程序在试图显示(或理解)提交历史时很挣扎,在这个过程中速度变慢,慢慢地蚕食你的灵魂。
这不是什么大问题,因为您可以始终指定
-Xno-renames
或将默认值设置为不考虑它们。但是,如果您 * 确实 * 需要跟踪重命名(因为文件名/文件夹经常在一个分支中更改,而其内容在另一个分支中更改),那么这可能不实用。
话虽如此,我个人确实喜欢 * 我们 * 的上下文中的工作流,其中问题和主题分支通常是单独提升的。此外,在main上有一个完整的历史记录,并且能够直接在上面
git bisect
到单独的提交是 * 偶尔 * 一种不错的选择。然而,它确实导致了更高层次的卷积和复杂性,因此需要更多的时间、勤奋、理解和(尽管我不喜欢这么说)代表与它一起工作的人的智慧。
这就是为什么我们最终可能会改变使用压扁的樱桃挑选促销。或者尝试想出其他的东西,在实践中不那么头痛。
毕竟,我想,git工作流不应该需要那些使用它的人那么多的注意力和精力。
特别是如果真的不值得。
附言:我相信我会重新审视这个答案,并修改它,因为随着时间的推移,更多的问题和想法会出现在脑海中。