5

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

当主干包含本地合并信息(文件或子树上的合并信息)时,它不起作用。这可能会导致重新集成后分支重用的问题。如果使用“keep alive dance”(使用仅记录选项)完成分支重用,这对 1.7 客户端来说不是问题。

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

下面的脚本有 10 个步骤。步骤 1-5 用于创建在主干中具有本地合并信息的启动情况。步骤 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 的范围,而似乎是缺少合并信息的 file2.txt。虽然不是解决方案,但删除主干中 file2.txt 上的本地合并信息似乎也可以解决问题。这也暗示错误消息报告了错误文件的内容。

编辑:对@gbjbaanb 的响应即使错误消息相同,此问题也比您所指的问题更微妙。在我的情况下,失败的不是重新集成到主干,而是分支之后的重用。

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

编辑:回复@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 是 HEAD)。我最初的期望是它会以与不使用相同的方式失败-c,但事实并非如此。它的成功方式与-c 11相同。

但我这篇文章的重点是,使用 SVN 1.8,我们不需要做保持活动的诡计。(草案)文档说:

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

从 Subversion 1.8 发行说明:

使用自动重新集成合并可以以任何顺序在两个分支之间来回合并(不再需要“keep-alive dance”)。为获得最佳结果,建议始终合并所有符合条件的修订,即不使用 svn merge 的 -r 或 -c 选项。仅合并符合条件的修订的子集会增加未来合并期间出现问题的可能性。(https://subversion.apache.org/docs/release-notes/1.8.html

所以我的观点是,这个分支重用没有保持活动的诡计显然在本地合并信息面前不起作用,我的脚本似乎表明了这一点。

如果您仍然认为有关缺失范围的警告可能是正确的,除了可能报告的范围编号,请告诉我我的脚本中导致缺失范围的位置。我的脚本是主干和分支之间的简单来回切换,没有对它们进行并行处理。

您还可以解释为什么还要通过在步骤 7 中添加: “echo Additional file contents created in trunk. >> trunk\file2.txt” 来解释为什么要修改 file2.txt,这将导致在步骤 10 中没有错误。修改附加文件在主干上无法解决缺失范围问题。

4

2 回答 2

2

在 Subversion 邮件列表中:users@subversion.tigris.org 决定这个问题值得为其创建问题报告。有关更多信息,请参阅: 问题报告Subversion 用户邮件列表

编辑:

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

于 2014-03-24T11:41:31.693 回答
1

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

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

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

我现在对主干进行另一项更改。这是第 103 版。我决定我的分支也需要这个。

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

可是等等!修订版 102 是从我的分支到主干的重新集成合并。该信息已经在分支上。再次合并 Revision 102 会弄乱我的分支。我可能会遇到很多合并冲突。

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

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

如果您执行了 #2,您现在可以将您的更改从主干合并回分支,因为这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 之前的所有更改重新集成到您的主干中。但是,Revision #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。这是从这个分支到主干的最后一次合并,似乎消息应该说明 Revision 11 这是reintegrated的版本。我认为错误是由于工程语言技能而不是任何类型的错误。

顺便说一句,而不是运行:

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
于 2014-03-19T18:39:45.717 回答