SVN1.8 merge(分支重用)在具有本地mergeinfo时似乎已损坏



我们在新的1.8 subversion客户端上遇到了问题(我们使用TortoiseSVN 1.8.5和SlikSVN 1.8.5)。似乎在某些情况下,重新整合后能够继续使用功能分支的新SVN 1.8功能不起作用。

当主干包含本地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. > trunkfile1.txt
echo Original file contents created in the trunk. > trunkfile2.txt
svn add trunkfile1.txt
svn add trunkfile2.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. >> featurebranch1file1.txt
echo Additional file contents created in featurebranch1. >> featurebranch1file2.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. >> trunkfile1.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,正如错误所示。因为file1.txt在featurebranch2的生命周期中在trunk中发生了更改,而file2.txt不是,所以在步骤8的合并过程中,没有在file2.txt上设置关于trunk的mergeinfo。我相信这就是它开始脱轨的地方。这不会影响重新集成到主干,但它确实防止了以后重用特性分支。

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

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

为了更好地衡量,我还尝试了-只记录-c 1-11,我所期望的与不使用-c相同(因为11是HEAD)。我最初的期望是,它会以与不使用-c相同的方式失败,但它没有。它的成功方式与-c 11相同。

但我的帖子的重点是,SVN1.8我们不需要做维持生命的把戏。(草案)文件说:

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

从Subversion 1.8发布说明来看:

可以使用自动融合("保持活力之舞"不再必要的)。为了获得最佳效果,建议始终合并所有符合条件的修订,即不使用svn-merge的-r或-c选项。只合并符合条件的修订的子集会增加可能性未来的问题合并。(https://subversion.apache.org/docs/release-notes/1.8.html)

所以我的观点是,在本地mergeinfo面前,这种没有保持生存策略的分支重用显然不起作用,我的脚本似乎表明了这一点。

如果您仍然认为关于缺失范围的警告可能是正确的,除了可能报告的范围编号之外,请告诉我在脚本中导致缺失范围的位置。我的脚本是在trunk和branch之间进行简单的来回切换,而不需要对它们进行并行处理。

您还可以解释为什么还要通过添加以下内容来修改file2.txt:"echo在trunk>>trunk\file2.txt">中创建的附加文件内容到步骤7,将导致步骤10中没有错误。修改中继线上的替代文件无法解决缺少范围的问题。

在Subversion邮件列表上:users@subversion.tigris.org我们决定,这个问题值得为其编写一份问题报告。有关更多信息,请参阅:发布报告和Subversion用户邮件列表。

编辑:

从1.8.9版本开始,它已被修复(问题#4481)。谢谢

我不相信1.8版本能解决分支重用问题。这个问题与修订编号以及Subversion如何跟踪修订的位置有关。

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

现在,我想将我的更改重新集成到trunk中。我做了一个重新整合合并,它进行双向合并,所以合并后,我的主干现在看起来像我的分支。这是102版,在我的行李箱上。到目前为止,我已经将修订版100合并到我的分支上,修订版101不在我的主干上,但我现在在主干上有修订版102。

我现在在行李箱上做另一个改动。这是103版。我决定这也是我的分支机构所需要的。

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

但是等等 修订版102是从我的分支到主干的重新整合。此信息已在分支上。再次合并第102次修订版会把我的分支机构搞砸。我可能会遇到大量的合并冲突。

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

  1. 永远不要重复使用分支
  2. 执行svn merge --record-only -r102以记录修订版102已在分支上。这不会对文件进行任何更改(属性svn:mergeinfo的值除外)

如果您做了#2,您现在可以将您的更改从主干合并回分支,因为svn:mergeinfo将声明主干上直到修订版102(包括修订版102)的所有更改都在分支上。只有修订版103中的更改需要放在您的分支上。

那么你的问题是什么

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

但是,您不能执行重新整合合并,除非您之前已将主干上的所有更改合并到分支中。

假设您已经将除修订版95之外的所有修订版从主干合并到分支上。您的主干包含修订版95中的更改,但您的分支没有此更改。如果我进行重新整合合并,则我正在进行双向合并。我将使我的主干与我的分支相匹配——我的分支没有你在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版本的脚本

这是我的剧本版本。它或多或少是从WindowsBatch翻译成Bashshell的。主要区别在于:

  • 步骤9.5:我在trunk上找到最后一个更改。这是您必须在要素分支上记录的修订,以便重用它
  • 步骤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次修订。这是从该分支到主干的最后一次合并,似乎消息应该说明修订版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

最新更新