【问题标题】:Branch from branch, reintegrate merge and mergeinfo从分支分支,重新整合merge和mergeinfo
【发布时间】:2014-04-10 14:03:09
【问题描述】:

我有一个从主干开始的分支 A 和一个从 A 开始的分支 B。 定期进行从主干到 A 的合并,然后也执行从 A 到 B 的合并。 当我想将A和B合并到主干时,我认为遵循这种方式:

  • 重新整合从 B 到 A 的合并
  • 重新整合从 A 到主干的合并

正确吗?或者它会导致合并信息或其他问题的问题?在这种情况下,最佳做法是什么?

【问题讨论】:

    标签: svn merge branch mergeinfo svn-merge-reintegrate


    【解决方案1】:

    Subversion 因合并不当而受到(有时是不公平的)批评。事实上,Subversion 非常擅长合并。要了解您需要做什么,您需要了解 Subversion 如何进行合并。

    Subversion 通常(我稍后会解释)进行标准的 3 路合并。它将被合并的两个文件与这两个文件共享的最后一个祖先文件进行比较。这样,它就可以知道文件中的哪些更改来自它所在的分支,以及哪些更改来自另一个分支。

    因为分支“B”来自分支“A”,而分支“A”来自主干。您可以从主干合并到 B 或从主干合并到 A。这些合并应该可以正常工作。如果您将一组特定的更改从 wither 分支 B 或分支 A 合并到主干或另一个分支,一切都应该正常工作。

    现在,我说 (有点)进行标准的 3 路合并。编写 Subversion 是为了允许您指定您在一个分支中所做的一组特定更改以与另一个分支合并。当您合并时,Subversion 不会查看您正在合并的文件,它从基文件开始,即最后一个共同祖先,然后应用正在考虑进行合并的那些更改。在这种情况下,当您明确指定要合并的内容时,Subversion 会出色地完成合并。

    因此,如果您指定分支“A”具有特定更改,并且您希望将此更改合并到分支“B”或主干,Subversion 在合并方面做得很好。

    当 Subversion 开始跟踪以前合并到分支或主干中的存储库修订时,Subversion 1.5 开始发生变化。这阻止了我合并以前合并到分支中的更改,但它也让我变得懒惰。懒惰没什么不好。我非常赞同。

    想象一下,我在主干的修订版 100 处创建了一个功能分支。我在修订版 100 处创建了分支。假设这是我的仓库中所做的修订列表:

    • 分行:103 105 108
    • 干线:101 102 104 105 106 107

    当我从主干合并到我的功能分支时,我没有指定要合并的修订版,Subversion 会为我挑选樱桃。它知道最后一个共同祖先是修订版 100。然后它查看并看到修订版 101、102、104、105、106 和 107 的主干上的更改尚未应用于我的分支。然后它会挑选这些特定的更改并将它们合并到我的分支中。

    • 分行:103 105 108 109
    • 干线:101 102 104 105 106 107

    修订版 109 是我合并的结果。为了跟踪更改,Subversion 在修订版 109 上添加了一个 svn:mergeinfo 属性,表示 trunk:101-107 已合并到分支:。让我们做更多的工作:

    • 分行:103 105 108 109 110 111
    • 干线:101 102 104 105 106 107 112 113

    我想再次从我的主干合并到我的分支。如果我不懒惰,我会指定我希望将修订版 112 和 113 合并到我的分支中。然而,因为懒惰,我让 Subversion 来完成这项工作。 Subversion 从svn:mergeinfo 看到从 101 到 107 的所有主干修订版都已合并到我的分支中。因此,Subversion 为我选择了修订版 112 和 113:

    • 分行:103 105 108 109 110 111 114
    • 干线:101 102 104 105 106 107 112 113

    Subversion 创建修订版 114,并设置 svn:mergeinfo 表示主干上从修订版 101 到修订版 113 的所有更改都已合并到我的分支中。

    现在,我已经完成了我的功能,我想将我在分支上所做的所有更改合并回我的主干。如果我不是这样一个懒惰的流浪汉,我会指定我希望将修订版 103、105、108、110 和 111 合并到我的主干上。如果我这样做了,那绝对没有问题。 Subversion 在合并方面做得很好。

    请注意,我没有指定要合并更改 109 和 114(这两个更改以粗体显示)。为什么?因为这些不是我分支上的更改,它们是我合并到我的分支上的主干更改。如果我指定了这两个修订版,我会将我的主干更改重新应用到我的主干上。

    但是,我很懒惰,我希望 Subversion 为我完成这项工作。 Subversion 查看我的分支,看到所有这些更改,包括更改 109 和 114,并希望将它们合并到我的主干上。不好。

    所以,Subversion 在这里做了一些特别的事情。如果我们将文件和修订视为应用于文件的更改集,我基本上是将主干上发生的所有更改应用到我的分支上,并将我的分支上的所有更改应用到我的主干上。换句话说,当我完成这个分支到主干的合并时,我的分支和我的主干将匹配。

    这就是重新整合合并的作用。与将我的两个文件中的更改与基本修订进行比较然后仔细应用的正常合并不同,我分支上的所有更改都将应用于我的主干,而不会将其与基本修订进行比较。 重新整合合并是一种双向合并。分支和主干之间的任何差异都将被覆盖。

    让我们看看会发生什么:

    重新整合合并之前

    • 分行:103 105 108 109 110 111 114

    • 中继线:101 102 104 105 106 107 112 113

    • svn:mergeinfo 在分支上现在说trunk:101-113

    重新整合合并后

    • 分行:103 105 108 109 110 111 114

    • 中继:101 102 104 105 106 107 112 113 115

    • svn:mergeinfo 在分支上现在说trunk:101-113

    • 主干上的svn:mergeinfo 现在显示branch:103-114

    让我们在主干上做更多的工作,只是为了向您展示如果我继续使用我的功能分支会发生什么。我将在主干上再做两处更改:

    • 分行:103 105 108 109 110 111 114

    • 中继线:101 102 104 105 106 107 112 113 115 116 117

    • svn:mergeinfo 在分支上现在说trunk:101-113

    • 主干上的svn:mergeinfo 现在显示branch:103-114

    现在,我想将这些更改合并回我的功能分支。如果我自己采摘樱桃,我会指定我希望将修订版 116 和 117 放到我的分支上,因为这是我刚刚进行的两个更改。再一次,如果我勤奋好学,Subversion 合并就好了。但是,我很懒,会让 Subversion 来挑选。

    Subversion 查看svn:mergeinfo 并看到我已将更改 103 到 114 应用到我的分支上。它现在在我的主干上看到三个新的变化:变化 115、116 和 117。然而,变化 115 是我重新整合合并的结果! 115 中的所有更改都已经在分支上。让 Subversion 来挑选会导致灾难。

    这就是为什么告诉您在重新集成分支后不要重用它的原因。解决这个问题的方法是从主干到我的分支做一个svn merge --record-only -c 115。实际上不会发生合并,但现在 Subversion 将记录更改 101 到 115 在我的分支上。如果我这样做了,然后从主干合并到分支,Subversion 将跳过选择更改 115,只执行更改 116 和 117。


    现在您了解了 Subversion 如何进行合并跟踪以及重新集成合并是什么,我们可以看看您的情况:

    • 你从主干分支到分支 A
    • 您从分支 A 分支到分支 B
    • 您从主干合并到分支 A
    • 您从分支 A 合并到分支 B

    如果你是一个勤奋的年轻程序员,每天早上 5 点起床跑 5 英里只是为了让你有工作的心情,你会指定每个分支的哪些修订要合并到其他分支或主干中。如果您这样做,则完全没有问题,您可以进行标准合并,并为您在健身房进行剧烈锻炼后进行的每日 100 公里自行车骑行做好准备。

    如果你是一个典型的技术工作者(即懒惰的人)并且你希望 Subversion 为你处理选择的修订,事情就有些不同了:

    • 您将分支 A 中的所有更改合并到分支 B。现在,您的分支 B 将包含分支 A 上的所有修订。
    • 重新集成将分支 B 合并回分支 A。现在,您对分支 A 和分支 B 的所有更改都将同时出现在两个分支上。
    • 您定期将主干合并到分支 A。分支 A 包含您对分支 A 所做的所有更改。此外,还有对分支 B 和主干的所有更改。
    • 您将分支 A(已包含您的分支 B 更改)重新集成合并到主干上。现在主干、分支 A 和分支 B 都包含相同的更改集,并且所有三个都应该匹配。
    • 您现在不应再次使用分支 A 或分支 B,除非您执行 svn merge --record-only 记录分支 B 到分支 A 的重新集成更改到分支 B,以及分支 A 到主干的重新集成更改到分支 A。

    Subversion 1.8 中的重要变化

    知道是在 Subversion 中进行常规合并还是重新集成合并可能有点容易出错。这是一个手动过程,如果我作为一个正常人犯了错误(我会在最糟糕的时候这样做),这可能是一场灾难。

    在 Subversion 1.8 中,Subversion 现在尝试通过查看 svn:mergeinfo 来确定您执行合并的方式以及何时必须执行重新集成合并。因此,您不再需要在合并时指定 --reintegration 标志。 Subversion 还将确保如果您在重新集成到另一个分支或主干后重用一个分支,而不是重新应用重新集成期间发生的更改。

    如果你喜欢做很多功能分支,你应该使用 Subversion 1.8,它会为你处理合并跟踪中的很多错误倾向。如果您使用的是 Subversion 1.8,您应该可以毫无问题地从分支 B 合并到分支 A 和主干。

    【讨论】:

    • 感谢您快速而清晰的回答。我正在使用子版本 1.5.5。我尝试提出另一种方案:如果我必须在分支 B 的工作完成之前将分支 A 合并(或更好地重新合并)到主干,我该怎么办? 1)重新整合从A到主干的合并; 2)从主干到分支A的仅记录合并; 3)从A合并到B; 4) 重新整合从 B 到 A 的合并 5) 重新整合从 A 到主干的合并。这个程序正确吗?
    • 是的。您将假设分支“B”不存在,然后处理 A 和主干(合并主干 => A,重新集成 A => 主干)。然后,您别无选择,只能从主干合并到 A 以覆盖该重新集成修订。这将使您保持分支 A 的活力。然后,您处理 B 和 A(合并 A => B,重新集成 B => A),然后再次处理主干和 A(合并主干 => A,重新集成 A => 主干)。最后两条记录仅从 B => A 和主干 => A 合并是可选的,以保持分支活着。第一个(主干 => 仅 A 记录)是必需的,因为 A 仍处于活动状态
    • 再确认一次:我怀疑仅从 A 到 B 的简单合并是不够的:我是否还必须从 A 到 B 进行仅记录合并?或者简单的合并就足够了,因为它考虑了之前从主干到 A 的仅记录合并?再次感谢!
    • 如果您一直在合并 A=>B 以使 B 与 A 中的更改保持同步,那么您必须在重新集成合并之前执行常规合并 A=>B B=>A。一旦你进行了重新集成 B=>A 合并,你有两个选择:不再使用分支 B,或者对重新集成时创建的 Subversion 修订进行仅记录的 A=>B 合并。在您进行仅记录合并之前,您不能再次从 A=>B 合并。
    • 我看到:trunk=>A 合并,然后 Reintegrate A=>trunk。您现在必须为该 Reintegrate 修订执行一个trunk=>A record-only merge。否则,您将无法在 A 和中继之间进行任何合并。做你的 A=>B 合并和 B=>A 重新整合。此时,只有 A=>B 的记录是可选的。如果您不再使用 B,则不必这样做。接下来,合并trunk=>A,然后再次重新集成A=>trunk。同样,仅记录合并是可选的,仅当您计划再次在 A 和主干之间合并时才需要这样做。
    猜你喜欢
    • 2011-02-17
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多