当有本地mergeinfo时,SVN 1.8合并(分支重用)似乎被破坏了

时间:2014-03-06 14:47:31

标签: svn version-control svn-merge mergeinfo svn-merge-reintegrate

新的1.8 subversion客户端存在问题(我们使用TortoiseSVN 1.8.5& SlikSVN 1.8.5)。似乎在重新集成后能够继续使用功能分支的新SVN 1.8功能在某些情况下无效。

当trunk包含本地mergeinfo(文件或子树上的Mergeinfo)时,它不起作用。这可能会导致重新集成后分支重用的问题。如果使用'keep alive dance'进行分支重用(使用仅记录选项),这对1.7客户端来说不是问题。

我制作了一个从头开始说明这个问题的脚本。它可以使用1.8客户端针对空存储库运行。

下面的脚本有10个步骤。步骤1-5用于创建在主干中具有本地mergeinfo的起始情况。步骤6-9模拟在功能分支2的生命周期内对主干进行的更改。步骤10是失败的步骤,它模拟重新集成后重用特征分支的第一步。

这是第10步中的错误:

svn: E195016: Reintegrate can only be used if revisions 8 through 11 were pre
viously merged from svn://svn2010/practice/branches/featurebranch2 to the reinte
grate source, but this is not the case:
  trunk/file1.txt
    Missing ranges: /trunk/file1.txt:9

这是(Windows)脚本。

@ECHO OFF
ECHO ------------------------------------------------------------------
ECHO STEP 0: Create a repository
ECHO ------------------------------------------------------------------
if exist repo rmdir repo /S/Q
if exist trunk rmdir trunk /S/Q
if exist featurebranch1 rmdir featurebranch1 /S/Q
if exist featurebranch2 rmdir featurebranch2 /S/Q
svnadmin create repo --compatible-version 1.8
REM Make url based on current directory and replace backslashes by forward slashes
set url="file:///%cd:\=/%/repo"
ECHO url=%url%

ECHO ------------------------------------------------------------------
ECHO STEP 1: Create a trunk with 2 files
ECHO ------------------------------------------------------------------
svn mkdir -m "Create trunk" %url%/trunk
svn checkout %url%/trunk
echo Original file contents created in the trunk. > trunk\file1.txt
echo Original file contents created in the trunk. > trunk\file2.txt
svn add trunk\file1.txt
svn add trunk\file2.txt
svn -m "Added 2 files" commit trunk

ECHO ------------------------------------------------------------------
ECHO STEP 2: Create a copy (feature branch) from the trunk
ECHO ------------------------------------------------------------------
svn mkdir -m "Create branches dir" %url%/branches
svn copy -m "Create featurebranch1" %url%/trunk %url%/branches/featurebranch1

ECHO ------------------------------------------------------------------
ECHO STEP 3: Modify both files in the feature branch
ECHO ------------------------------------------------------------------
svn checkout %url%/branches/featurebranch1
echo Additional file contents created in featurebranch1. >> featurebranch1\file1.txt
echo Additional file contents created in featurebranch1. >> featurebranch1\file2.txt
svn -m "Modified 2 files in featurebranch1" commit featurebranch1

ECHO ------------------------------------------------------------------
ECHO STEP 4: Merge both files from featurebranch1 to the trunk to 
ECHO         create local mergeinfo on both files
ECHO ------------------------------------------------------------------
svn update trunk
svn merge %url%/branches/featurebranch1/file1.txt trunk/file1.txt
svn merge %url%/branches/featurebranch1/file2.txt trunk/file2.txt
svn -m "Merged 2 files from featurebranch1 to trunk" commit trunk

ECHO ------------------------------------------------------------------
ECHO STEP 5: Delete featurebranch2, we only needed it for the
ECHO         initial setup
ECHO ------------------------------------------------------------------
svn delete -m "Delete featurebranch1" %url%/branches/featurebranch1

ECHO ------------------------------------------------------------------
ECHO STEP 6: This is the start of the problematic scenario
ECHO         Create a new featurebranch2 from the trunk and a wc for it
ECHO ------------------------------------------------------------------
svn copy -m "Create featurebranch2" %url%/trunk %url%/branches/featurebranch2
svn checkout %url%/branches/featurebranch2

ECHO ------------------------------------------------------------------
ECHO STEP 7: Modify the contents of file1.txt in the trunk and leave
ECHO         the contents of file2.txt unchanged (this is important)
ECHO ------------------------------------------------------------------
echo Additional file contents created in the trunk. >> trunk\file1.txt
svn -m "Modified file1.txt in the trunk" commit trunk

ECHO ------------------------------------------------------------------
ECHO STEP 8: Sync merge the trunk to featurebranch2
ECHO ------------------------------------------------------------------
svn update featurebranch2
svn merge %url%/trunk featurebranch2
svn -m "Sync merged the trunk into featurebranch2" commit featurebranch2

ECHO ------------------------------------------------------------------
ECHO STEP 9: Reintegrate featurebranch2 back into the trunk
ECHO ------------------------------------------------------------------
svn update trunk
svn merge %url%/branches/featurebranch2 trunk
svn -m "Reintegrated featurebranch2 back into the trunk" commit trunk

ECHO ------------------------------------------------------------------
ECHO STEP 10: Try to reuse featurebranch2 after it was reintegrated
ECHO          Sync merge it from the trunk. THIS FAILS with SVN 1.8 
ECHO ------------------------------------------------------------------
svn update featurebranch2
REM on SVN 1.7 we would use --record-only
svn merge %url%/trunk featurebranch2

:EOF

我不明白为什么会这样。此错误报告缺少file1.txt的范围,而它似乎是缺少mergeinfo的file2.txt。虽然不是解决方案,但删除trunk中file2.txt上的本地mergeinfo似乎也解决了这个问题。这也暗示错误消息是在错误的文件上报告某些内容。

修改:对@gbjbaanb的回复 即使错误消息相同,此问题也比您指向的问题更微妙。在我的情况下,不是重新整合到主干,但是后来重新使用了分支。

另外,如果我查看file1.txt和file2.txt的mergeinfo,似乎file2.txt缺少featurebranch2的mergeinfo记录,所以问题出在file2.txt而不是file1.txt,如错误所示。因为在featurebranch2和file2.txt的生命周期中在trunk中更改了file1.txt,所以在步骤8的合并期间没有在file2.txt上设置关于trunk的mergeinfo。我相信这是它开始的地方脱轨这不会影响重新集成到主干,但它确实阻止了功能分支的重用。

修改:对@David W的回复 我已经尝试了 - record-only -c 11 ,这也适用于Windows端。我已经尝试过了没有 -c (通常你不应该,我知道,但在这种情况下没有其他的变化)然后报告:

svn: E200004: The required merge is reintegrate-like, and the record-only option
 cannot be used with this kind of merge

为了更好的衡量,我还尝试了 - record-only -c 1-11 ,我所期望的与不使用 -c 相同(因为11是头)。我最初的期望是,它会以不使用 -c 的方式失败,但事实并非如此。它的成功方式与 -c 11 相同。

但我的帖子的重点是,使用SVN 1.8,我们不需要保持活力。 (草案)文件说:

  

如果您选择在将分支重新集成到分支后不删除分支   trunk可以继续从trunk执行同步合并然后   再次重新整合分支[37]。如果您这样做,只有更改   在第一次重新整合后合并到你的分支上   树干。 (http://svnbook.red-bean.com)。

从Subversion 1.8发行说明:

  

可以使用任何顺序在两个分支之间进行合并   自动重新融合合并(不再是“保持活力的舞蹈”)   必要)。为获得最佳效果,建议始终合并所有结果   符合条件的修订,即不使用svn merge的-r或-c选项。   仅合并一部分符合条件的修订会增加可能性   未来的问题   汇合。(https://subversion.apache.org/docs/release-notes/1.8.html

所以我的观点是,没有keep alive trickery的这个分支重用显然不适用于本地mergeinfo,我的脚本似乎表明了这一点。

如果您仍然觉得有关丢失范围的警告可能是正确的,除了可能报告的范围编号,请告诉我在我的脚本中我导致丢失范围。我的脚本在主干和分支之间来回简单,没有并行处理它们。

您也可以通过添加以下内容来解释为什么还要修改file2.txt: “echo在主干中创建的其他文件内容。>> trunk \ file2.txt” 到第7步,将导致步骤10中没有错误。在主干上修改aditional文件无法解决丢失范围问题。

2 个答案:

答案 0 :(得分:2)

在Subversion邮件列表上:users@subversion.tigris.org,确定此问题值得为此创建问题报告。有关详情,请参阅: Issue reportSubversion user mailing list

修改

自版本1.8.9起,它已得到修复(问题#4481)。谢谢!

答案 1 :(得分:1)

我不相信版本1.8 解决分支重用问题。问题与版本编号以及Subversion如何跟踪修订版本在哪里有关。

让我们从修订版100开始。我已经对trunk进行了更改,我想将所有这些更改合并到我的分支中。我进行标准合并并创建修订版101(在我的分支上)。在我的分支上,svn:mergeinfo显示主干上包括修订版100的所有更改现在都在我的分支上。到目前为止,我的最后一个主干版本是修订版100.一切都很好。

现在,我希望将我的更改重新集成回到主干。我做了一个 reintegration 合并,它进行双向合并,所以在合并之后,我的主干现在看起来像我的分支。这是修订版102,它在我的主干上。到目前为止,我已将Revision 100合并到我的分支机构,修订版101不在我的主干上,但我现在在我的主干上有修订版102.

我现在在行李箱上再做一次改动。这是修订版103.我认为我的分支也需要这个。

我的分支机构表示,修订版100的主干上的所有修订都已合并到我的分支机构上。到现在为止还挺好。我现在将进行另一次合并,现在我的主干上有两个新版本:修订版102和修订版103.根据svn:mergeinfo,这两个版本的更改需要合并到我的分支中。

但等等! 修订版102是 reintegration merge 从我的分支到主干。此信息已在分支机构上。再次合并修订版102会弄乱我的分支。我可能会遇到大量的合并冲突。

Subversion没有真正的方法可以检测到这个问题。有两种方法可以解决这个问题:

  1. 永远不要重复使用分支
  2. 执行svn merge --record-only -r102以记录修订102已在分支上。这不会对文件进行任何更改(属性svn:mergeinfo的值除外)。
  3. 如果你做了#2,你现在可以将你的更改从trunk合并到分支上,因为svn:mergeinfo将声明你的主干上包括修订版102的所有更改都在你的分支上。只有修订版103中的更改需要放在您的分支上。

    那你的问题是什么?

    Subversion现在可以检测您是否需要进行常规(三向)合并以及重新集成(双向)合并。您不再需要使用--reintegration参数。

    但是,您无法执行重新整合合并 ,除非 您之前已合并 所有 主干上的更改进入您的分支。

    假设您已将主干的所有修订版合并到您的分支上,但修订版95除外。您的主干包含修订版95中的更改,但您的分支机构没有进行此更改。如果我执行 reintegration merge ,我正在进行双向合并。我将使我的树干与我的分支相匹配 - 我的分支机构没有你在修订版95中所做的更改。

    如果我将我的分支合并到我的主干中,我将失去我在主干上修改的95版本中的更改。

    你不希望这种情况发生。因此,如果你正在进行重新整合合并,Subversion会警告你,但是还没有将你所有的主干变化合并回分支。

    让我们再次查看您的消息:

    svn: E195016: Reintegrate can only be used if revisions 8 through 11 were previously merged from svn://svn2010/practice/branches/featurebranch2 to the reintegrate source, but this is not the case:  
        trunk/file1.txt
            Missing ranges: /trunk/file1.txt:9
    

    这告诉您,您希望将所有更改重新整合到修订版11中,然后重新进入主干。但是,修订版#9从未合并到分支上。如果您进行重新整合合并,您的主干上将丢失此更改。

    为了继续,您需要使用--force(一个坏主意),或者从主干进行另一个合并回到分支,以将修订版9中的更改发送到您的分支。

    完成此操作后,您可以进行分支到中继的合并。

    我希望这能澄清情况。


    脚本的Unix版本

    这是我的脚本版本。它或多或少地从Windows Batch转换为Bash shell。主要区别在于:

    • 步骤9.5:我在行李箱上找到最后一次更改。这是您必须在功能分支上记录的修订版本,以便重复使用它。
    • 步骤10:我使用--record-only在功能分支上使用-c,因为您必须重新使用功能分支。它在Subversion 1.8中运行得很好。这适用于Mac OS X Mavericks和RHEL 6.我没有在6.5上尝试过。

    SVN 1.7和SVN 1.8在这种情况下的主要区别在于SVN 1.7会在没有任何警告的情况下完成合并,而SVN 1.8会尝试警告您这个问题。我不确定为什么要修改第9版。这是从该分支到trunk的最后一次合并,似乎该消息应该声明版本11是重新集成的修订版。我认为错误是由于工程语言技能而不是任何错误。

    顺便说一下,而不是跑步:

    svn merge  --record-only -c$last_changed $URL/trunk featurebranch2
    

    如果我跑了这个:

    svn merge  --force $URL/trunk featurebranch2
    

    合并就像在Subversion 1.7中一样。在这种情况下,合并正确发生,但这是因为在最终合并之前,您没有更改主干或分支上的文件。这只是运气

    #! /bin/bash
    # svnscript.sh
    #
    # ECHO STEP 0: Create a repository
    echo "Create Repository"
    [[ -d "repo" ]] && rm -rf repo
    [[ -d "trunk" ]] && rm -rf trunk
    [[ -d "featurebranch1" ]] && rm -rf featurebranch1
    [[ -d "featurebranch2" ]] && rm -rf featurebranch2
    svnadmin create repo --compatible-version 1.8
    URL="file://$PWD/repo"
    echo "URL=$URL"
    ########################################################################
    # STEP 1: Create a trunk with 2 files
    ########################################################################
    echo "Step 1: Create a trunk with 2 files"
    svn mkdir -m"Create trunk" $URL/trunk
    svn checkout $URL/trunk
    echo Original file contents created in the trunk. > trunk/file1.txt
    echo Original file contents created in the trunk. > trunk/file2.txt
    svn add trunk/file1.txt
    svn add trunk/file2.txt
    svn -m "Added 2 files" commit trunk
    
    ########################################################################
    # STEP 2: Create co copy (feature branch) from the trunk
    ########################################################################
    
    echo "STEP 2: Create a feature branch from the trunk"
    svn mkdir -m "Create branches dir" $URL/branches
    svn copy -m "Create featurebranch1" $URL/trunk $URL/branches/featurebranch1
    
    ########################################################################
    # STEP 3: Modify both files in the feature branch
    ########################################################################
    
    echo "STEP 3: Modify both files in the feature branch"
    svn checkout $URL/branches/featurebranch1
    echo "Additional file contents created in featurebranch1." >> featurebranch1/file1.txt
    echo "Additional file contents created in featurebranch1." >> featurebranch1/file2.txt
    svn -m "Modified 2 files in featurebranch1" commit featurebranch1
    
    ########################################################################
    # STEP 4: Merge both files from featurebranch1 to the trunk
    ########################################################################
    
    echo "STEP 4: Merge both files from featurebranch1 to the trunk to "
    echo "        create local mergeinfo on both files"
    
    svn update trunk
    svn merge $URL/branches/featurebranch1/file1.txt trunk/file1.txt
    svn merge $URL/branches/featurebranch1/file2.txt trunk/file2.txt
    svn -m "Merged 2 files from featurebranch1 to trunk" commit trunk
    
    ########################################################################
    # STEP 5: Delete Feature1 branch: No longer needed
    ########################################################################
    
    echo "STEP 5: Delete featurebranch2, we only needed it for the"
    echo "        initial setup"
    svn delete -m "Delete featurebranch1" $URL/branches/featurebranch1
    
    ########################################################################
    # STEP 6: This is the start of the problematic scenario
    ########################################################################
    echo "STEP 6: This is the start of the problematic scenario"
    echo "        Create a featurebranch2"
    svn copy -m "Create featurebranch2" $URL/trunk $URL/branches/featurebranch2
    svn checkout $URL/branches/featurebranch2
    
    ########################################################################
    # STEP 7: Modify the contents of file1.txt. in trunk
    ########################################################################
    
    echo "STEP 7: Modify the contents of file1.txt in the trunk and leave"
    echo "        the contents of file2.txt unchanged (this is important)"
    
    echo "Additional file contents created in the trunk." >> trunk/file1.txt
    svn -m "Modified file1.txt in the trunk" commit trunk
    
    ########################################################################
    # STEP 8:Sync merge the trunk to featurebranch2
    ########################################################################
    
    echo "STEP 8: Sync merge the trunk to featurebranch2"
    svn update featurebranch2
    svn merge $URL/trunk featurebranch2
    svn -m "Sync merged the trunk into featurebranch2" commit featurebranch2
    
    ########################################################################
    # STEP 9: Reintegrate featurebranch2 back into the trunk
    ########################################################################
    
    echo "STEP 9: Reintegrate featurebranch2 back into the trunk"
    svn update trunk
    svn merge $URL/branches/featurebranch2 trunk
    svn -m "Reintegrated featurebranch2 back into the trunk" commit trunk
    
    ########################################################################
    # STEP 9.5: Get the last change info on Trunk
    ########################################################################
    
    svn update trunk
    last_changed=$(svn  info  $URL/trunk | sed -n '/Last Changed Rev/s/.*: //p')
    
    ########################################################################
    # STEP 10: Try to reuse featurebranch2 after it was reintegrated
    #          This time, we'll use the --record-only with the change on trunk
    ########################################################################
    echo " STEP 10: Try to reuse featurebranch2 after it was reintegrated"
    echo "          Sync merge it from the trunk. THIS FAILS with SVN 1.8 "
    
    svn update featurebranch2
    svn merge  --record-only -c$last_changed $URL/trunk featurebranch2
    svn commit -m"It works on MY machine!" featurebranch2