【问题标题】:Delete a feature merged and unmerged this feature in all following commits删除在所有后续提交中合并和取消合并此功能的功能
【发布时间】:2021-01-24 15:02:48
【问题描述】:

我是 git 新手,用我的术语在互联网上找不到这个问题的答案,但可能已经有人问过了。

假设我的默认分支是develop。我从develop创建了一个名为feature/test的分支,在这个分支上做一些提交,然后将它合并到develop

 ---1---2---3---4---M---5---6---7--- (develop)
             \     /                
              A---B    (feature/new)

在合并M 之后,我继续我的开发项目,并提交了几次。

但现在我想从分支之后的所有提交中取消合并功能分支,就像分支 develop 从未合并 feature/new 一样。

这就是我喜欢的:

 ---1---2---3---4---5'---6'---7'--- (develop)
             \                     
              A---B    (feature/new)

如您所见,M 之后的所有提交都被修改以撤消删除的合并带来的修改。

是否可以这样做,我应该使用哪个命令?

谢谢

【问题讨论】:

    标签: git git-flow revert


    【解决方案1】:

    有很多方法可以做到这一点。

    要获得您在图片中描述的历史记录,您需要重写历史记录。您应该知道,如果此 repo 与其他人共享,并且如果您要重写的历史记录已被共享(推送到远程),那么正确地执行此操作需要一些协调 - 因为重写共享历史记录会导致错误情况,如果解决不正确,将导致您的工作被撤消。

    也就是说,为避免重写历史记录,您将使用 git revert(或等效项)。恢复合并有成本,无论您是否与他人共享历史记录,这些成本都适用。

    因此,通常最好避免合并以后可能必须“取消合并”的分支。但无法改变过去,你必须充分利用现有的选择。

    要决定是否应该重写历史记录,我会参考“从上游 Rebase 恢复”部分中的 git rebase 文档 (https://git-scm.com/docs/git-rebase)。您还可以查看有关合并的 git revert 文档 (https://git-scm.com/docs/git-revert)。然后根据您的决定,您可以执行以下操作之一:

    改写历史

    所以:按照您的要求进行操作的最简单方法是

    git rebase --onto develop~4 develop~3 develop
    

    这会获取您想要保留的提交,为它们计算补丁,并将这些补丁应用到新的父节点;一些细节:

    develop~4develop~3 表达式特定于您的示例。

    develop~4 指的是您通过跟随“第一父”指针四次找到的提交,从develop 指向的提交开始。这导致4。通过将其作为--onto 参数,您告诉rebase 它计算的补丁应该从这里开始应用。

    同样develop~3 导致M,所以这是“上游”。这意味着MM(通过父指针)可访问的任何提交都不会用于创建补丁。 (如果您不使用--onto,upsteram 也会在应用补丁的位置发挥作用;但这里我们确实使用了--onto,所以这并不重要。)

    应用补丁时,可能会发生冲突。这是因为 567 中的某些内容可能会编辑已被 M 编辑的行(或“足够接近”M 编辑的行,它会导致 git不确定是否有问题)。任何按照您的要求进行操作的可靠方法都会产生相同的冲突,因此您只需要弄清楚如果从未发生合并,更改“应该”是什么样子。

    如果develop 存在于远程,并且如果M 已被推送到该远程,则默认情况下,git 将拒绝推送此更改的结果(因为它从分支历史记录中删除了M)。您可以使用push 命令的--force-with-lease 选项覆盖它。 (有人说使用-f 选项,虽然这样更容易输入,但也不太安全。-f 不会检查您不知道的新提交是否已推送到develop--force-with-lease 会。)

    不重写历史记录

    如果您不能(或不想)协调历史记录重写,那么您必须接受您推送的任何历史记录都是不可变的。在这种情况下,您可以恢复合并。

    git revert -m 1 develop~3
    

    -m 选项告诉 git 你正在“恢复到”合并的哪个父级;因此,通过说 -m 1,您可以有效地撤消分支中的更改。

    就像历史重写方法一样,这可能会发生冲突并需要手动解决冲突。最终结果是

    1 -- 2 -- 3 -- 4 -- M -- 5 -- 6 -- 7 -- !AB <--(develop)
               \       /
                A --- B <--(feature/new)
    

    其中!AB 反转了AB 的更改(已合并到M)。

    因为AB 仍在develop 的历史记录中,如果您以后想重新合并它们,这并不简单。您要么必须还原 !AB,要么使用 rebase -f 在 mreging 之前重写 feature/new 的历史记录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-31
      • 1970-01-01
      相关资源
      最近更新 更多