如何在不丢失之间的提交记录的情况下撤销已经合并了很多其他提交记录的提交 (Azure DevOps)

3
我的GIT经验几乎为零,所以我提出的问题可能听起来有些奇怪。我们有一个Azure Devops仓库,每天都有提交记录。
9月3日,在我们的Azure Devops存储库中发生了一次更改提交,但从未被推送。该开发人员当时不在场,在过去的两个月中发生了很多提交。然后,在10月21日,9月3日的提交与所有之间的提交合并,并最终被推送。
有没有办法撤销合并的提交(发生在10月21日)和提交本身(发生在9月3日),同时不丢失其中所有的提交记录?
这是在Azure Devops中发生的,提交和推送主要通过Visual Studio 2019进行。

1
听起来像是使用 git revert 的典型工作。查看文档。但是,您不必撤消提交 合并。根据您的工作流程,仅撤消“错误”的提交本身(或仅撤消合并提交,但通常更棘手,请注意)可能已经足够了。 - Romain Valeri
谢谢您的回答@RomainValeri。但是,撤销提交(从9月3日开始)不会撤销此后发生的任何事情吗? - Filip5991
1
不,这并不会。这正是git cherry-pickgit revert(实际上是一种“负”cherry-pick)的意义所在:提取某个提交差异(通过与其父项的差异)以将这些更改移植到其他地方,而不附加任何其他历史记录。 - Romain Valeri
1个回答

4

正如@RomainValeri在评论中指出的那样git revert命令是您在这里寻找的。

首先,让我们可视化一下这种情况:

o---o---o---o---o---X---M
     \                 /
      A----------------

这里,提交A是9月3日的提交,而M是10月21日的合并提交。

你提到想要恢复包含M的分支中A引入的更改。您可以通过还原合并提交M来实现:

git revert -m 1 M

M是指向合并提交的引用。

现在,由于合并提交有两个或多个父项,您还需要告诉Git应该使用哪个父项作为基线来确定它应该撤消什么更改。这就是-m (--mainline) 选项的用途。在本例中,我们希望目标分支(即将A合并到其中的分支)成为基线,因此我们说使用first parent,即-m 1

这将在新的提交W中应用M的第一个父项(在此示例中为X)和A之间的差异的反向操作:

o---o---o---o---o---X---M---W
     \                 /
      A----------------

通常将合并提交的反向操作称为W,因为它看起来像倒过来的M

请注意,撤销合并提交会撤消更改,但它不会撤消历史记录。换句话说,在W之后,Git仍然会认为与M合并的分支已经合并。如果你尝试再次合并它,Git会告诉你everything is up-to-date

因此,如果你想在将来再次合并同一分支,你必须先撤销上一次撤销。详细了解如何执行此操作,请查看Git文档中的how-to


1
撤销合并的 -m 选项的解释非常好。 - Romain Valeri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接