回滚到旧提交,但应用回我的提交

Roll back to an old commit, but apply back my commits

我一直在处理合并到 dev 分支的功能分支 A。合并后,我对 dev 分支进行了多次提交。但是,我意识到 dev 分支的当前负责人已损坏,想通过回滚到 dev 分支中的某个提交并重新应用所有提交来测试我的 A 分支的 A 和合并后我做的额外的 dev。我怎么能做到这一点?

编辑:很多人都致力于 dev,我合并到我的分支 A 中,它仅由我的提交组成。基本上,我想删除所有其他人对某些旧提交的提交。

回滚仅用于测试目的,以查看分支 A 是否与分支 dev 在某种程度上兼容。它不需要是 "up-to-date",但需要 A 合并到代码实际用于工作的 dev 中的某个点。

使用临时分支。

让我们画出您现在拥有的,作为分支 dev 和您的 feature 分支上的一系列提交。让我们暂时假设您 还没有 将您的 feature 分支合并到 dev (即使您已经合并,也就是说,让我们从您之前 [= =23=]):

...--o--*--A--B--C--D--E--F      <-- dev
         \
          G---H--I--J--K---L     <-- feature

现在,您已经完成了 git checkout dev && git merge feature 或同等操作,所以让我们将合并提交添加到绘图中:

...--o--*--A--B--C--D--E--F--M   <-- dev
         \                  /
          G---H--I--J--K---L     <-- feature

"Your" 提交是分支 feature 上的那些在合并之前不在 dev 上的提交,即 GL,加上当然是你的新合并 M.

现在你说你还添加了几个提交,所以让我们把它们画进去:

...--o--*--A--B--C--D--E--F--M--N--O    <-- dev
         \                  /
          G---H--I--J--K---L            <-- feature

正是在这一点上,您意识到有什么东西被闯入了,比如说 E,也许还有 F。所以现在你想看看如果你测试 "commit O as it would be if we didn't have commits E and/or F".

会发生什么

方法一:创建临时分支并恢复错误提交

(这通常是最简单的方法。您已经进行了合并;另一种方法让您重新进行合并,并且合并往往比恢复更难一些。)

第 1 步是获取一个临时分支。在 dev 时,只需 git checkout -b temp,这样您现在拥有:

...--o--*--A--B--C--D--E--F--M--N--O    <-- dev, HEAD -> temp
         \                  /
          G---H--I--J--K---L            <-- feature

现在您可以 运行 git revert <id-of-E> <id-of-F> 恢复两个 "bad" 提交。这会做 git cherry-pick 所做的事情,除了反向:它找出从 EF 的变化(以便它可以重复,或者在这种情况下,未完成)和 "reverse applies" 更改为撤消它。然后它以同样的方式找出从 DE 的变化,并反向应用该变化以撤消它。

现在你有:

                                     f'-e'  <-- temp
                                    /
...--o--*--A--B--C--D--E--F--M--N--O        <-- dev
         \                  /
          G---H--I--J--K---L                <-- feature

其中 f' 是 "undoes" F 的提交,e' 是 "undoes" E.[=67 的提交=]

现在您可以 运行 您的测试了。

方法二:创建临时分支,然后重新合并和cherry-pick

同样,我们从 EF 是 "bad" 的想法开始。所以这一次,我们想要一个直接指向提交 D 的临时分支:dev 上的最后一个 "good" 提交。找到提交的 ID D 然后:

git checkout -b temp <id-of-D>

现在你有了这个——它和以前的绘图是一样的,但是我们为新的分支标签添加了一个凹凸 "up":

                   D                  <-- HEAD -> temp
                  / \
...--o--*--A--B--C   E--F--M--N--O    <-- dev
         \                /
          G--H--I--J--K--L            <-- feature

现在 运行 git merge feature。这使得 new 合并提交与 M 完全不同,它将提交 L 合并到提交 D 中。绘制结果图有点困难,因为合并线跨越了 dev 分支(我应该采取与将 D 提升一条线不同的方法),但这是一种尝试:

                   D-------m          <-- HEAD -> temp
                  / \     .
...--o--*--A--B--C   E--F--M--N--O    <-- dev
         \               ./
          G--H--I--J--K--L            <-- feature

现在使用 git cherry-pick 复制 提交 NO。这与我们之前的 revert 类似,除了它不会尝试 "undo" 更改,而只是复制它们。我们将这些副本称为 N'O'(大写,因为它们是副本,而不是反向副本):

                   D-------m--N'--O'  <-- HEAD -> temp
                  / \     .
...--o--*--A--B--C   E--F--M--N--O    <-- dev
         \               ./
          G--H--I--J--K--L            <-- feature

现在 运行 你的测试和以前一样。

如果测试失败怎么办?

如果仍然无法正常工作,则由您决定如何处理。但是,您可以继续在 temp 分支上进行 new 提交,直到您修复了问题,然后决定如何收集这些修复并返工 feature,或者在提交 O 之后添加它们,或者其他什么。这部分真的很简单,因为你有一个分支!