我使用乌龟svn。但总的来说,我对svn还是比较新的。我对git有一些经验。
在文件中说
重新整合分支
此方法涵盖您完成的情况 Subversion书中讨论的一个功能分支。 所有主干更改都已移植到该功能 分支,一周一周,现在功能已完成 你想把它合并回主干。
据我所知: 功能分支的正常工作流程是,为了使功能分支,在其上进行开发,经常在主干分支上的错误修正的修订范围内合并。功能完成后,最后合并主干更改,然后将分支重新集成到主干中。
所以我有一些问题:
答案 0 :(得分:8)
首先快速学习合并如何适用于几乎所有版本控制系统。
标准合并是三向合并。在此,您将两个版本与两个版本的最后一个共同祖先进行比较。例如,我从trunk分支。分支前的主干上的版本是最后一个共同祖先。
目的是能够查看一个流上的更改与其他流上的更改。 (流可以是特定分支或主干)。例如,如果我从主干到分支合并,我想确保我不会用主干上的那些行覆盖我的特定分支变化。
与上一个共同祖先的比较使您只能看到自该分支点以来在主干上发生的更改。
当我从之前的合并中退后时,这会出现问题。例如,我完成了我的功能分支,并希望所有功能更改回主干。这是一个问题,因为我已将所有主干更改合并到分支上。这意味着我的分支 stream 表明我在分支上进行了更改,这些应该合并到trunk中。但是,这些变化已经在行李箱上!要处理此问题,您可以强制进行双向合并。在这种情况下,您只需将两个独立流的头部相互比较,并将所有差异从一个流复制到另一个流。
现在Subversion如何处理合并:
首先,Subversion喜欢樱桃选择mergin。 Subversion允许您指定要合并的修订版本。例如,我有一个分支,发现了一个错误并将其修复在分支上。我现在可以合并包含我的错误修复的特定修订版或修订版集。当您在Subversion中挑选时,您正在进行三向合并,但您只考虑在那些特定的 cherry pick 版本中表示的更改,而不是在主干或分支上的所有更改。
事实上,即使你没有指定樱桃挑选版本,Subversion几乎总是会选择合并。 Subversion跟踪通过svn:mergeinfo
属性合并的修订版本。让我们说我在修订版100中分支,现在我将我的主干更改合并到我的分支中。 trunk的最后一个版本现在是版本150.Subversion认为你正在从版本100(但不包括版本100)到版本150上的所有版本的樱桃选择。下次我从我的主干进行合并到我的分支机构(让我们说我的主干上的最后一次更改现在是175),Subversion将在主干上 cherry pick 更改(但不包括150)到版本175.
请注意,当我指定合并的樱桃选择修订版时,我可以在我的分支和我的主干之间来回切换,没有任何问题。如果我从我的功能分支合并到我的主干,我可以在我的功能分支上指定我实现该功能的修订,并跳过我的功能分支上的更改,这些更改是从主干合并的结果。
问题出现在我让Subversion处理 cherry picking 的时候。当我从我的主干合并到我的分支时,Subversion会跟踪我的分支上的主干的修订。但是,Subversion无法知道我的功能分支上的哪些修订是我的主干合并的结果。
因此,当我将我的功能分支合并回主干时,Subversion将考虑所有未合并的修订 - 包括那些由主干到分支合并的结果的修订,并尝试将所有这些修订合并回我的主干。 / p>
为了解决这个问题,Subversion有一个名为 reintegration 合并的特殊合并。我将我的主干上的最后一组更改合并到我的分支中,然后当我将我的分支合并到我的主干中时,我希望我的主干和分支是相同的。因此,Subversion想要进行双向合并,使主干和分支匹配。
在旧版本的Subversion中,我必须手动指定我正在使用--reintegration
命令上的svn merge
参数进行双向合并。
Subversion的合并跟踪也会导致重用功能分支的一个有趣问题。让我们说我做了从trunk到我的分支的最后一组合并。主干上的最后一个版本和Subversion的最后一个版本是修订版100.当我将我的更改从主干合并到我的分支上时,我现在在我的分支上创建修订版101。该分支上的svn:mergeinfo
属性显示我已将所有更改合并到仅来自中继分支的修订版100中。
现在,我执行 reintegration 合并,提交更改,并在我的主干上创建修订版102.
现在,我在我的主干上做了更多的工作,(让我们说修改版103),我想将这些更改合并到我的功能分支上。
我从trunk到我的功能分支合并的最新修订是什么?查看svn:mergeinfo
,我看到它的修订版100.自从上一次从主干到分支合并之后,现在有两个尚未合并到我的功能分支的主干上的新版本:修订版102和修订版103。
因此,Subversion将执行 cherry picking 并尝试将修订102和修订版103中包含的更改合并到我的功能分支上。但是等等......修订版102将我的所有功能分支更改合并到主干上!我将重新将这些功能更改重新应用到我的功能分支中!
有两种方法可以解决这个问题:方法一:执行重新集成合并后,您再也不应该使用该功能分支了。删除它。把它锁在一个尼姑庵里。再也不说出它的名字了。如果我再次需要该功能分支,我应该从trunk创建一个新的功能分支。
另一种方法是在功能分支上使用svn:mergeinfo
以使Subversion知道trunk上的修订版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不同,每个bug和功能都应该位于自己的分支上,你需要将这个bug修复或功能合并到多个分支上,你几乎可以完成所有的工作(或者你喜欢的任何分支)。在大多数Subversion商店中,分支仅针对候选版本进行。也就是说,我即将发布一个版本,我为该版本分支。一些开发人员负责发布,其他人继续他们的工作。
如果在主干上发现了一个错误,它可以在主干上修复,修复该错误的修订版或修订版可以合并到发布分支上。或者,如果您发现需要在主干上修复功能分支上的错误,您可以在功能分支上修复该错误,并将该修订版或修订集合并到主干上。
它简单,直接且易于实施。
这并不意味着您无法为某项功能进行分支。事实上,有时你必须这样做。想象一下,这个功能将在未来深入实施。你不希望在主干上进行这些更改。在这种情况下,请创建功能分支,并将主干更改定期合并到该功能分支上。请记住,将该功能合并回主干时可能会出现问题。只要你明白发生了什么。这没问题。
而且,如果你想疯狂地为每个功能和bug创建一个巨大的分支,你也可以这样做。但是,我建议你使用Subversion 1.8,它会为你做到这一点。
答案 1 :(得分:0)
或多或少
从主干到您的功能分支的频繁合并点是零食:小而且易于管理。当出现冲突时,可以通过新的想法修复它们。如果在重新集成之前没有将更改从主干到功能分支合并,则不会发生任何“坏”。只是你必须同时处理所有变化的合并,这可能会产生很多冲突,你可能甚至都不记得导致冲突的代码,使您重新学习该代码并花费更多时间来解决冲突。如果您的主干和功能分支每天同步,则可能只需每天额外的5分钟即可执行同步并清除冲突。如果您将其保留到功能分支的末尾,则可能需要花费一两天的时间来解决所有冲突。
请参阅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
SVN比git更友好。它是集中式的,具有TortoiseSVN形式的大窗口GUI。 TortoiseSVN的最新版本删除了“重新集成”选项,因为它会在您执行此操作时自动显示出来。当您勾选用于合并的修订时,它会将此信息存储在SVN中,因此下次您可以轻松地直观地查看已经签入的修订版本,等等。