Domanda

We have a problem with the new 1.8 subversion clients (we use TortoiseSVN 1.8.5 & SlikSVN 1.8.5). It seems that the new SVN 1.8 feature of being able to keep using your feature branch after reintegration is not working in some cases.

It is not working when the trunk contains local mergeinfo (Mergeinfo on files or sub-trees). This may cause a problem for branch reuse after the reintegrate. This wasn't a problem with 1.7 clients if branch reuse was done using the 'keep alive dance' (using the record only option).

I have made a script that illustrates this problem from scratch. It can be run against an empty repository using a 1.8 client.

The script below has 10 steps. Step 1-5 are used to create the starting situation of having local mergeinfo in the trunk. Steps 6-9 simulate changes being made to the trunk during the life of a feature branch2. Step 10 is the failing step which simulates the first step of reuse of the feature branch after reintegrate.

This is the error in step 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

This is the (Windows) script.

@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

I do not understand why this happens. Also the error reports missing ranges of file1.txt while it seems to be file2.txt that is missing mergeinfo. While not a solution, deleting the local mergeinfo on file2.txt in the trunk also seems to fix the problem. This also hints that the error message is reporting something on the wrong file.

Edit: response to @gbjbaanb This problem is more subtle than the one you are pointing to even though the error message is the same. In my case it is not the reintegrate to the trunk that is failing but the reuse of the branch afterwards.

Also if I look at the mergeinfo of both file1.txt and file2.txt it seems file2.txt is missing the mergeinfo record of featurebranch2 so the problem is with file2.txt not file1.txt as the error suggests. Because file1.txt was changed in the trunk during the life of featurebranch2 and file2.txt wasn't the mergeinfo about the trunk wasn't set on file2.txt during the merge in step 8. I believe this is the spot where it starts to derail. This will not impact the reintegrate to the trunk but it does prevent feature branch reuse afterwards.

Edit: response to @David W I've tried the --record-only -c 11 and this also works on the Windows side. I had already tried it without -c (normaly you shouldn't, I know, but in this case there are no other changes) and then it reports:

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

For good measure I also tried --record-only -c 1-11 which what I expected would be the same as not using -c (as 11 is HEAD). My initial expectation was that it would fail the same way as not using -c, but it didn't. It succeeded the same way as -c 11.

But the whole point of my post is that with SVN 1.8 we don't need to do keep alive trickery. The (DRAFT) documentation says:

If you choose not to delete your branch after reintegrating it to the trunk you may continue to perform sync merges from the trunk and then reintegrate the branch again[37]. If you do this, only the changes made on your branch after the first reintegrate are merged to the trunk. (http://svnbook.red-bean.com).

And from the Subversion 1.8 release notes:

Merging to-and-fro between two branches in any order is possible using the automatic reintegration merge (the "keep-alive dance" is no longer necessary). For best results, it is recommended to always merge all eligible revisions, i.e. not using the -r or -c options of svn merge. Merging just a subset of eligible revisions increases the likelihood of problems during future merges.(https://subversion.apache.org/docs/release-notes/1.8.html)

So my point is that this branch reuse without the keep alive trickery clearly doesn't work in the face of local mergeinfo and my script seems to show that.

If you still feel that the warning about the missing ranges could be correct, except for maybe the reported range numbers, please show me where in my script I cause a missing range. My script is a simple back and forth between trunk and branch without parallel work on both of them.

Also could you explain why also modifying file2.txt by adding: "echo Additional file contents created in the trunk. >> trunk\file2.txt" to step 7, will result in not having an error in step 10. Modifying an aditional file on the trunk can't solve a missing ranges problem.

È stato utile?

Soluzione

On the Subversion mailing list: users@subversion.tigris.org it was decided that this problem was worthy of creating an issue report for. For more info see: Issue report and Subversion user mailing list.

Edit:

As of version 1.8.9 it has been fixed (issue #4481). Thanks!

Altri suggerimenti

I don't believe version 1.8 solves the branch reuse problem. The problem has to do with the revision numbering and how Subversion tracks what revision is where.

Let's start with Revision 100. I have done changes on trunk, and I want to merge all of these changes into my branch. I do a standard merge and create Revision 101 (on my branch). On my branch, the svn:mergeinfo shows that all changes on trunk up to and including revision 100 are now on my branch. So far, my last trunk revision is Revision 100. All is fine and good.

Now, I want to reintegrate my changes back into trunk. I do a reintegration merge which does a two-way merge, so after the merge, my trunk will now look like my branch. This is revision 102, and it's on my trunk. So far, I've merged Revision 100 onto my branch, Revision 101 is not on my trunk, but I now have Revision 102 on my trunk.

I now make another change on trunk. This is revision 103. I decide that this is also needed on my branch.

My branch says that all revisions on trunk up to Revision 100 have been merged onto my branch. So far, so good. I now will do another merge, and there are now two new revisions on my trunk: Revision 102 and Revision 103. According to svn:mergeinfo, the changes in both of these revisions need to be merged into my branch.

But wait! Revision 102 was the reintegration merge from my branch to trunk. This information is already on the branch. Merging Revision 102 again will mess up my branch. I'll probably get a ton of merge conflicts.

There's no real way for Subversion to detect this issue. There are two ways of solving this problem:

  1. Never ever reuse the branch or
  2. Do a svn merge --record-only -r102 to record that revision 102 is already on the branch. This makes no changes in the file (except for the value of the property svn:mergeinfo).

If you did #2, you can now merge your changes from trunk back onto the branch because, svn:mergeinfo will state that all changes on your trunk up to and including Revision 102 are on your branch. Only the changes in Revision 103 needs to be put onto your branch.

So what is your issue?

Subversion now can detect whether you need to do a regular (three way) merge and a reintegration (two-way) merge. You no longer need to use the --reintegration parameter.

However, you cannot do a reintegration merge unless you've previously merged all of the changes that are on the trunk into your branch.

Let's say you have merged all revisions from trunk onto your branch except for revision 95. Your trunk contains the change in Revision 95, but your branch doesn't have this change. If I do my reintegration merge, I am doing a two-way merge. I am going to make my trunk match my branch -- my branch which doesn't have the change you did in Revision 95.

If I merge my branch into my trunk, I lose the changes in Revision 95 I made on my trunk.

You do not want that to happen. Therefore, Subversion will warn you if you're doing a reintegration merge, but haven't merged all of your trunk changes back into the branch.

Let's look at your message again:

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

This is telling you that you want to reintegrate all of your changes up to Revision 11 back into your trunk. However, Revision #9 was never merged onto the branch. If you do a reintegration merge, you will lose this change on your trunk.

In order to proceed, you either need to use --force (a bad idea), or do another merge from trunk back into branch to get the changes in Revision 9 onto your branch.

Once this is done, you can do your branch-to-trunk merge.

I hope this clarifies the situation.


Unix Version of your script

Here's my version of the script. It was more or less translated from Windows Batch to Bash shell. The main difference is:

  • Step 9.5: I find the last change on trunk. This is the revision you have to record on your feature branch in order to reuse it.
  • Step 10: I use --record-only on the feature branch with the -c because you have to in order to reuse your feature branch. It works just fine in Subversion 1.8. This works just fine on both Mac OS X Mavericks and RHEL 6. I haven't tried it on 6.5.

The main difference between SVN 1.7 and SVN 1.8 in this scenario is that SVN 1.7 would have done the merge without any warning while SVN 1.8 attempts to warn you about the issue. I'm not sure why Revision 9 was reported. It was the last merge from this branch onto trunk, it seems the message should have stated Revision 11 which is the revision that was reintegrated. I take that the error is due to engineering language skills more than any sort of error.

By the way, instead of running:

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

If I ran this:

svn merge  --force $URL/trunk featurebranch2

The merge happens just as it would in Subversion 1.7. I this case, the merge happens correctly, but it's because you didn't change the files on trunk or the branch before you did the final merge. It was just luck

#! /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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top