1

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

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

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

4

1 回答 1

8

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

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

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

现在,我说(有点)做一个标准的 3-way merge。编写 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,除非您执行 asvn 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 并合并到主干中,而不会出现任何问题。

于 2014-04-10T15:57:06.197 回答