git 使用单独的PR进行部署滚动和回滚:未按预期工作

r9f1avp5  于 2023-01-19  发布在  Git
关注(0)|答案(1)|浏览(200)

我们有这样的场景:对于生产中的任何应用程序配置变更,我们创建2个PR:一个用于实施,另一个用于回滚。我们提前创建这些。然后,我们让它们经过审核和批准。
在变更窗口期间,我们没有任何人来审查请购单。因此,我们必须提前创建请购单并获得批准。
比方说,master分支包含一个配置文件www.example.com,具有以下2个属性:app.properties with below 2 properties: test.base.certificate=abcd
测试基础密钥= abcd
我们创建实施PR,如下所示:
1.从master创建实现分支。
1.使用新值更新属性,如下所示:
检测基础证书= efgh
测试基础密钥= efgh
1.提交更改。
1.将更改推送到远程。
我们创建回退请购单,如下所示:
1.从主体创建回滚分支。
1.使用新值更新属性,如下所示。
检测基础证书= efgh
测试基础密钥= efgh
1.提交更改。
1.还原为旧属性值:
测试基础证书= abcd
测试基础密钥= abcd
1.提交更改。
1.将更改推送到远程。
Rollback PR没有显示app.properties中的任何差异。这是因为在第二次提交之后,master分支和rollback分支中的文件之间没有任何差异。
在产品更改窗口中,我们首先合并实施PR和测试。如果在测试过程中出现任何问题,我们将合并回退PR以还原更改。
最近第一次做回滚活动,合并回滚PR后,发现master分支的www.example.com仍然有新的属性值:app.properties in the master branch still had the new property values:
检测基础证书= efgh
测试基础密钥= efgh

在高层次上,看起来这个方法应该是有效的。有人知道为什么它不起作用吗?在这种情况下如何创建回滚PR?
我知道git revert,但是我很好奇为什么上面的方法不起作用。
先谢了!

brccelvz

brccelvz1#

从高层次上看,这种方法似乎应该奏效。
我猜你认为git merge rollback会把rollback特有的两次提交回放到当前分支(main)上,如果git这么做了,那么第一次提交不会做任何事情,因为main已经有了修改,第二次提交会把属性文件恢复到原来的状态,这是你所期望的,但这不是git merge的工作方式。

git merge不重播提交

git merge默认情况下执行的操作称为三路合并,如an answer to another question中所述:
你最好去寻找一个3路合并算法的描述,一个高层次的描述应该是这样的:
1.找到一个合适的合并基B--一个文件版本,它是两个新版本(XY)的祖先,通常是最近的这样的基(尽管在某些情况下它将不得不回到更远的地方,这是git的默认recursive合并的特性之一)
1.执行XB以及YB的差异。
1.仔细检查两个差异中的变更块,如果双方在同一个地方引入了相同的变更,接受其中一个;如果一方引入了一项变更,而另一方不涉及该区域,则在期末考试中引入该变更;如果两者都在一个点上引入了更改,但它们不匹配,则将冲突标记为要手动解决。
git merge docs有一个不太详细的解释,但准确地解释了让您困惑的行为:
对于使用3路合并的策略(包括默认的ort),如果在两个分支上都进行了更改,但后来在其中一个分支上恢复了更改,则该更改将出现在合并结果中;有些人会觉得这种行为令人困惑。2这是因为在执行合并时只考虑了头文件和合并基文件,而不是单个提交。3因此合并算法会将恢复的更改视为没有更改,并替换更改后的版本。
我相信这样做的原因有几个:

  • 99%的情况下,合并是关于并行的开发线,处理不同的事情,而你想 * 合并 * 这两件事。因此,默认情况下,你不想让一个分支上的更改优先于另一个分支。如果rollback是一个特性分支,你不想让它覆盖impl所做的更改。
  • 99.9%当一个开发人员一个分支做了一个更改,然后又撤销了它,其意图是"假装我从来没有做过那个"。所以大多数时候让一些人困惑的行为确实是人们所期望的。
  • 您可以通过指定不同的合并策略(如git merge -s ort -X theirs rollaback)或使用其他命令(如cherry-pickrebase)来实现其他行为,具体取决于您的具体需要。

溶液#1:git revert

取消rollback分支,只使用git revert

git checkout main
git revert main..IMPL

这是最简单的

溶液#2:从impl分支rollback

如果出于某种原因,您 * 必须 * 通过PR执行此操作,或者出于任何原因 * 必须 * 具有rollback分支,则从impl分支rollback,而不是master

git checkout impl
git checkout -b rollback
git revert main..IMPL

它看起来像这样:
合并impl以进行部署:

1---4 main
 \ /
  2 impl
   \
    3 rollback

合并rollback以回滚:

1---4-------5 main
 \ /       /
  2 impl  /
   \     /
    3----  rollback

不仅app.properties会像你预期的那样被还原,而且git历史记录也更简单,更好地描述了发生的事情。将它与你当前方法的结果进行比较,你当前的方法有两个相同的冗余提交(2和3),并在开始时误导性地分裂成三个分支。

2  rollout
 / \
1---5---6 main
 \     /
  3---4  rollback

如果允许fast-forward合并,效果会更好。

部署结果如下所示:

1---2 main, impl
     \ 
      3 rollback

和回滚,如下所示:

impl 
1---2---3 main, rollback

相关问题