恢复分支 A 上的提交,稍后将合并到 B。提交应该留在 B

Revert commit on branch A which is going to be merged to B later. Commit should stay on B

假设我在无效的分支 A 上进行了提交,这应该在分支 B 上进行。
提交被推送了,后来我发现了错误。

我知道分支 A 将很快合并到 B,我只想还原 A 上的提交并应用 B 上的提交。
分支 B 将在某个时候合并到 A,但要晚得多 - 至于现在,只需要在 B 上应用更改。

当我想避免通过合并在分支 B 上再次恢复时,正确的方法是什么?您可以假设合并将由另一个人进行,这很容易出错,只需将还原应用于 B.

这个方案需要合并告知,看来不可行

  1. 还原 A 上的提交。
  2. 在 B 上进行提交,正如您最初希望的那样。
  3. 正常合并(或让其他人完成合并)

我认为合并应该能够处理这种情况,结果是 A 不包含提交,但 B 包含提交。

I know that branch A will be soon merged to B and I want to only revert the commit on A and apply the commit on B.

这听起来和我的建议完全一样。在 A 上还原,在 B 上提交。正常合并,它将自动合并导致 B 保留更改,否则将需要手动解决冲突。

经过一番思考,我想我找到了解决办法。
让我们命名无效提交:X

A 提交:... Ya, X, revert_X, Za, ...
B-提交:... Yb, X, Zb, ...

为了避免在 B 上应用 revert_X,必须创建一个额外的 PR,在分支 B:[=24= 上提交 revertXX ]

git checkout B
git cherry-pick revert_X
git cherry-pick X

现在合并 A -> B revert_X 未应用,因为它已经在 B 上创建。


样本:

分支机构 A:
分支机构 B:

和提交历史:

没有魔法可以移除更改、合并到其他地方然后出现,接受这一点应该有助于理解实现所需最终状态所需的步骤。

考虑以下简化的历史,它符合问题中描述的场景:

$ git log --all --decorate --oneline --graph
* 9eb80d9 (b) Some change added to b only
| * c297cb5 (a) Should be on b, but not a
|/
* 3c5caf4 (main) Initial commit

首先,清理

I made a commit on invalid branch A, which was supposed to be made on branch B

以下操作将清理当前情况:

$ git switch a
$ git revert HEAD # Revert the mistake
[a 92f9287] Revert "Should be on b, but not a"

此时 'Should be on b, but not a' 的效果在 a 上被抵消并且在 b 上不存在。

二、建立共同历史

避免合并问题就是建立一个共同的提交历史 - 在这里,这意味着挑选有问题的提交到 b 恢复它:

$ git switch b
$ git cherry-pick 9eb80d9 # Reapply the mistake
$ git revert HEAD # AND revert it

这导致:

$ git log --all --decorate --oneline --graph
* 8d7c582 (b) Revert "Should be on b, but not a"   # Fixing Mistake
* ecf8f7c Should be on b, but not a                # Fixing Mistake
* 9eb80d9 Some change added to b only
| * 3339ef1 (a) Revert "Should be on b, but not a" # Clean up
| * c297cb5 Should be on b, but not a                
|/
* 3c5caf4 (main) Initial commit

此时'Should be on b, but not a'的效果在两个分支中都被否定了。

三、改对地方

所以我们有了一个干净的状态,现在所需要做的就是将提交重新应用到正确的分支:

$ git switch b
$ git revert HEAD

导致:

$ git log --all --decorate --oneline --graph
* fb744c1 (b) Revert "Revert "Should be on b, but not a"" # Re-apply
* 8d7c582 Revert "Should be on b, but not a"              # Fixing Mistake
* ecf8f7c Should be on b, but not a                       # Fixing Mistake
* 9eb80d9 Some change added to b only
| * 3339ef1 (a) Revert "Should be on b, but not a"        # Clean Up
| * c297cb5 Should be on b, but not a
|/
* 3c5caf4 (main) Initial commit

此时'Should be on b, but not a'的效果只在分支b上。

注意:重新应用更改的提交不一定是还原,同样可以是正常提交​​。

正在合并,没问题

Branch B will be at some point merged to A

现在没问题了:

$ git switch a
$ git merge b
Merge made by the 'recursive' strategy.

根据描述的 commits/reverts 将干净利落地应用,导致:

$ git log --all --decorate --oneline --graph
*   bf1ff12 (a) Merge branch 'b' into a
|\
| * fb744c1 (b) Revert "Revert "Should be on b, but not a""
| * 8d7c582 Revert "Should be on b, but not a"
| * ecf8f7c Should be on b, but not a
| * 9eb80d9 Some change added to b only
* | 3339ef1 Revert "Should be on b, but not a"
* | c297cb5 Should be on b, but not a
|/
* 3c5caf4 (main) Initial commit

现在 'Should be on b, but not a' 的效果在分支 ab 上。