【问题标题】:Reintegrate a branch without merging in trunk changes重新集成分支而不合并主干更改
【发布时间】:2014-04-02 09:11:05
【问题描述】:

我使用乌龟svn。但总的来说,我对 svn 还是很陌生。不过我对 git 有一些经验。

在文档中说

重新整合一个分支

这个方法涵盖了当你做了 Subversion 书中讨论的功能分支。 所有中继更改都已移植到该功能 逐周分支,现在功能已完成 你想把它合并回主干。

据我了解: 功能分支的正常工作流程是,创建一个功能分支,在其上进行开发,经常合并来自主干分支上的错误修复的修订范围。功能完成后,对主干更改进行最终合并,然后将分支重新集成到主干中。

所以我有一些问题:

  1. 这个工作流程是否正确
  2. 如果我在重新集成功能分支之前不合并来自主干分支的更改,会发生什么情况
  3. 如果我从完全更新的功能分支到主干分支进行正常合并会发生什么
  4. 为什么这么复杂,svn 的本意是比 git 对用户更友好,但尤其是合并,你必须指定要合并到功能分支的修订,并且从不同的合并选项中进行选择似乎比等效的 git 功能(我必须在我的公司使用 svn,因为其他开发人员使用它,但他们没有分支),除非我做错了什么

【问题讨论】:

    标签: svn merge tortoisesvn feature-branch


    【解决方案1】:

    首先是关于合并如何工作以及几乎适用于所有版本控制系统的快速课程。

    标准的合并是三路合并。在此,您将两个版本与两个版本的最后一个共同祖先进行比较。例如,我从主干分支。分支之前主干上的版本是最后一个共同祖先。

    目的是能够查看一个流上的变化与另一个流上的变化。 (流可以是特定的分支或主干)。例如,如果我从主干合并到分支,我想确保不会用主干上的那些行覆盖我的特定分支更改。

    与最后一个共同祖先的比较允许您仅查看自该分支点以来在主干上发生的更改。

    当我从以前的合并中倒退时,这会出现问题。例如,我完成了我的功能分支,并希望所有功能更改都回到主干上。这是一个问题,因为我已将所有主干更改合并到分支上。这意味着我的分支的 stream 表明我对分支进行了更改,这些应该合并到主干中。但是,这些变化已经在主干上!要处理此问题,您可以强制进行双向合并。在这种情况下,您只是将两个单独流的头部相互比较,并将所有差异从一个流复制到另一个流。


    现在 Subversion 如何处理合并:

    首先,Subversion 喜欢cherry pick mergin。 Subversion 允许您指定要合并的版本。例如,我有一个分支,发现了一个错误并在分支上修复了它。我现在可以合并包含我的错误修复的特定修订或修订集。当您在 Subversion 中挑选樱桃时,您正在执行三向合并,但您只考虑那些特定 樱桃挑选 版本中表示的更改,而不是主干或分支上的所有更改。

    事实上,Subversion 几乎总是会进行 Cherry Pick 合并,即使您没有指定 Cherry Pick 修订版。 Subversion 通过svn:mergeinfo 属性跟踪合并了哪些修订。假设我在修订版 100 处分支,现在我将主干更改合并到我的分支中。主干上的最后一个修订版现在是修订版 150。Subversion 认为您正在从修订版 100(但不包括版本 100)到修订版 150 的所有主干版本中进行挑选。下次我从我的主干合并到我的分支(假设我的主干上的最后一个更改现在是 175),Subversion 将 cherry pick 从(但不包括 150)到修订 175 的主干上的更改。

    请注意,当我为合并指定cherry pick 修订时,我可以在分支和主干之间来回切换而不会出现任何问题。如果我从我的功能分支合并到我的主干,我可以在我实现该功能的功能分支上指定修订,并跳过我的功能分支上的更改,这些更改是从主干合并的结果。

    只有当我让 Subversion 处理樱桃采摘时,问题才会出现。当我从我的主干合并到我的分支时,Subversion 会跟踪我的主干在我的分支上的修订。但是,Subversion 无法知道我的功能分支上的哪些修订是我的主干合并的结果。

    因此,当我将功能分支合并回主干时,Subversion 将考虑所有未合并的修订——包括那些作为主干到分支合并结果的修订,并尝试将所有这些修订合并回我的主干。

    为了处理这个问题,Subversion 有一个特殊的合并,称为 reintegration 合并。我将我在主干上的最后一组更改合并到我的分支中,然后当我将我的分支合并到我的主干中时,我希望我的主干和分支是相同的。因此,Subversion 想要进行双向合并并使主干和分支匹配。

    在旧版本的 Subversion 中,我必须手动指定我正在使用 svn merge 命令上的 --reintegration 参数进行这种双向合并。

    Subversion 的合并跟踪也会导致重用功能分支的有趣问题。假设我做了最后一组从主干到分支的合并。主干上的最后一个修订版和 Subversion 中的最后一个修订版是修订版 100。当我将主干上的更改合并到我的分支上时,我现在在我的分支上创建了修订版 101。该分支上的 svn:mergeinfo 属性显示我已将所有更改从主干合并到修订版 100 仅我的分支。

    现在,我进行重新集成合并,提交更改,并在我的主干上创建修订版 102。

    现在,我在我的主干上做了更多的工作(假设是修订版 103),我想将这些更改合并到我的功能分支中。

    我从主干合并到功能分支的最后一个修订是什么?查看svn:mergeinfo,我看到它是修订版 100。自从上次从主干合并到分支以来,主干上现在有两个新修订版尚未合并到我的功能分支中:修订版 102 和修订版 103。

    所以,Subversion 会像 樱桃采摘 一样尝试将修订版 102 和修订版 103 中包含的更改合并到我的功能分支中。但是等等……修订版 102 是我所有的功能分支更改都被合并到主干上!我将在我的功能分支上重新应用这些功能更改!

    有两种方法可以处理这个问题: 方法一:一旦你做了一个重新集成合并,你就永远不要再使用那个特性分支了。删除它。把它锁在尼姑庵里。永远不要再说出它的名字。如果我再次需要那个特性分支,我应该从主干创建一个新的特性分支。

    另一种方法是在特性分支上输入svn:mergeinfo 以使Subversion 知道主干上的修订版102 已经合并到我的特性分支中。您可以使用--record-only 参数执行此操作:

    $ svn co $REPO/branches/feature/myproj
    $ cd myproj
    $ svn merge --record-only -r102 $REPO/trunk/myproj
    

    如您所见,所有这些手动工作(知道何时使用 --reintegration 开关并了解在进行 重新集成 合并时会发生什么)都会造成混乱。因此,新版本的 Subversion(我相信自 1.8 版以来)现在会尝试为您处理这个问题。

    如果您使用 Subversion 1.8 作为客户端,则无需指定 --reintegration 参数。 Subversion 将以编程方式确定您是在进行典型的三向合并还是重新集成合并并采取相应的行动。

    如果我尝试执行 Subversion 认为的重新集成合并,并且我尚未将所有主干修订合并到我的功能分支中,Subversion 会警告我并且不允许我进行合并。如果我在完成 reintegration 合并后重用功能分支,Subversion 会检测到这一点并在重新集成后自动处理分支重用问题。 (有时它不能很好地工作。但是,Subversion 不会让您在重新集成合并后重用功能分支,但可能会给您一个错误,您可能必须手动执行 --record-only 合并。)


    那么在 Subversion 中,你应该如何做你的工作流程?

    与 Git 不同,Git 中每个错误和功能都应该在自己的分支上,至少您需要将该错误修复或功能合并到多个分支上,您几乎可以在主干(或您喜欢的任何分支)上完成几乎所有工作。在大多数 Subversion 商店中,仅针对候选版本进行分支。也就是说,我即将发布一个版本,我为该版本分支。一些开发人员致力于发布,其他开发人员继续他们的主干工作。

    如果在主干上发现错误,则可以在主干上修复它,并且可以将修复了该错误的修订或修订集合并到发布分支中。或者,如果您在功能分支上发现需要在主干上修复的错误,您可以在功能分支上修复该错误并将该修订或一组修订合并到主干。

    它简单、直接且易于实施。

    这并不意味着您不能为某个功能分支。事实上,有时你必须这样做。想象一个在未来深入实施的功能。您不希望在主干上进行这些更改。在这种情况下,创建特性分支,并定期将主干更改合并到该特性分支上。请记住,当您将该功能合并回主干时可能会出现问题。只要你明白发生了什么。没问题。

    而且,如果您想疯狂地为每个功能和错误创建大量分支,您也可以这样做。不过,我建议您使用 Subversion 1.8,它会为您做到这一点。

    【讨论】:

    • 该死。你可以写一本 svn 书。
    【解决方案2】:
    1. 或多或少

    2. 从主干到功能分支的频繁合并的要点是它零碎:小且易于管理。当冲突出现时,可以通过你脑海中的新鲜变化来解决它们。如果您在重新集成之前不将更改从主干合并到功能分支,则不会发生任何“坏事”。只是您将不得不同时处理所有更改的合并,这可能会产生很多冲突,您甚至可能不记得其中的部分导致冲突的代码,使您重新学习该代码并花费更多时间解决冲突。如果您的主干和功能分支每天同步,那么每天执行同步和清除冲突可能只需额外 5 分钟。如果你把它留到特性分支结束,你可能会花一两天时间一次性解决所有冲突。

    3. 见Reintegrate a branch vs merge a range of revision、What are the differences between merging a range of revisions vs. reintegrate in SVN?和Consequences of not using --reintegrate with svn merge back to trunk

    4. SVN 比 git 更加用户友好。它是集中的,具有 TortoiseSVN 形式的出色 Windows GUI。最新版本的 TortoiseSVN 删除了“重新集成”选项,因为它会在您这样做时自动计算出来。当您选中要合并的修订时,它将将此信息存储在 SVN 中,因此下次您可以轻松地直观地查看哪些修订已被签入,等等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 2010-11-22
      • 2019-06-11
      • 2011-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多