【问题标题】:How can I do git merges in such a way that they are easy to roll back?如何以易于回滚的方式进行 git 合并?
【发布时间】:2011-06-12 02:12:58
【问题描述】:

有很多关于在 git 中“撤消”合并是多么不容易的话题。简短版本:如果您撤消合并提交,它还会告诉 git 将来永远不要合并这些更改。

在进行合并时我可以做些什么来缓解这个问题?在很多情况下,撤消合并非常非常有用,仅在软件开发的正常过程中,更重要的是,在需要回滚更改时控制发布分支的状态。

编辑

我在this article 中看到了解决方案,并没有真正将其视为解决方案,更多的是对问题的解释。它需要

  1. 始终使用 --no-ff
  2. 当您想要恢复依赖于它们的代码时,请记住所有未完成的合并(这可能是未来的几个小时、几天、一周或几个月……)

我想要什么

这是它在 Subversion 中的工作方式。假设我有一个名为“release-candidate”的分支,它是我们在登台服务器上运行的,也是我们尝试功能的地方。假设我合并到功能 A 分支中。在 Subversion 中,它是一个变更集,所有文件的所有历史都被合并。假设我们不喜欢它,所以我们想把它拿出来。我们只需撤消那个单一的变更集,而不必考虑其他任何事情。我们可以在将来的任何时候将功能分支 A 合并回来,而不必记住我们曾经将它合并并取出。

我希望能够尽可能接近该流程。我想优化“将来不必记住东西”,即使它使事情在某种程度上采取了更多步骤。 (这可能是不可能的......)

【问题讨论】:

  • 是否有理由不能使用 git reset --hard ORIG_HEAD 回滚提交?
  • 我的回答需要更多信息吗?
  • urschrei:如果我在服务器上的分支上执行此操作,那么要推送结果我必须使用--force,对吧?
  • 好的,所以我的问题的答案是“你不能这样做”,但是 adymitruk 已经很好地概述了事后的选项。
  • 我真的需要知道你的问题是什么。在 git 中没有什么是 svn 做不到的……或多或少。

标签: git merge rollback undo feature-branch


【解决方案1】:

更新:

这里有一个可以更轻松地使用每个功能的分支的工作流程:http://dymitruk.com/blog/2012/02/05/branch-per-feature/


(问题的SVN部分最后已经回答了)

是的,这是重新引入已取消合并的功能的方法。考虑以下历史(假设您已经“撤消”了合并):

x---x----x--x---x--M--U--L
     \            /
      x--x--x--x-F

F 是功能分支,M 是合并,U 是当您取消合并该功能时相反,L 是最新提交。

以下是您的选择:

  1. 还原 U(无需 --force 推送):

    x---x----x--x---x--M--U--L--^U
        \            /
         x--x--x--x-F
    
  2. 将 F 重新定位到 L 上(然后合并 --ff-only F')(无需 --force 推送):

    x---x----x--x---x--M--U--L
         \            /       \
          x--x--x--x-x         x'--x'--x'--x'--F'
    
  3. 将 F 重新设置到 L 上(然后合并 --no-ff F' - 保留您的新分支点)(无需 --force 推送):

    x---x----x--x---x--M--U--L-------------------M2
         \            /       \                 /
          x--x--x--x-x         x'--x'--x'--x'--F'
    
  4. rebase -i head^^ 并从列表中删除 U --force 是必须推送的)

    x---x----x--x---x--M--L
         \            /
          x--x--x--x-F
    
  5. rebase --onto M^1 L^ L 摆脱合并和取消合并。现在您可以稍后重新合并 F。

                      L'
                     /
    x---x----x--x---x--M--U--L
         \            /
          x--x--x--x-F
    

要压缩所有功能提交,请在初始合并时使用 --squash 修饰符。我会让你的想象力来研究历史上的样子。我不建议这样做是有原因的。了解您如何使某个功能发挥作用以及它采取了哪些步骤是有价值的。后续合并会更容易,因为 Git 可以检查某个文件为何看起来如此的历史记录。将提交压缩在一起会丢失该信息。

还有一些额外的缺点可能会或可能不会影响您利用 rerere 历史记录的能力。

我建议始终在 master 中使用空白合并标记发布的内容。这是通过与--no-ff 选项合并来完成的。您永远不会在 master 上工作,并且唯一完成的提交就是那些合并 - 没有代码更改提交。在 QA 分支中,您标记标记您发布时间点的提交。因此,当您执行git merge --no-ff rc-12.2 时,您将自动生成一个提交注释“merged rc-12.2”。

查看 git-flow。

希望能为您提供更多详细信息。

【讨论】:

  • 这是对我的选项的一个很好的概述,但我的问题是在原始合并时我是否可以做一些事情以使事情变得更简单。我刚刚用“我想要什么”部分更新了我的问题。
  • 在您的回答中:这是 4 个不同的选项,对吧?想给他们编号吗?另外,如果所有分支都已远程发布,其中哪些需要--force?如果您将它们标记为这样会很好..
  • “假设你已经“取消”了一个合并”——这是否意味着 git revert <merge hash>?
  • 还-- 想在你的答案中做一些关于--no-ff 的注释吗? (与它进行合并总是理想的,使它们更不可撤销,对吧?)
  • git-flow 看起来很酷,但似乎与取消合并和重新合并没有任何关系。我错过了什么吗?
猜你喜欢
  • 2012-07-28
  • 1970-01-01
  • 2020-02-18
  • 2017-08-30
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多