Hi,
I tested with a reproduction scenario and found this:
A) If I do an svn update on the top-level WC before the merge command,
the merge goes through OK and I can checkin.
B) If I don't do an svn update on the top-level WC before the merge
command, the merge goes wrong and svn complains about out-of-date when
I do the checkin. A following svn update seems to not change anything
and I can checkin the wrong merge without problems.
There are a few things still not clear to me:
1) Before this svn update, svn stat -u shows nothing out-of-date, so
it's strange that an update makes any difference.
2) svn update itself does not mention any updates, it just says "At revision 6."
3) If I check the relevant svn:mergeinfo properties before / after
this svn update, I see no changes at all. However, if I check with the
svn mergeinfo command, then I do see a change after the update. What
else is being used to calculate the actual mergeinfo?
4) If I don't do the update before svn merge, why does svn complain
about out-of-date at checkin instead of at the merge itself?
See attachment for reproduction script + output for both cases.
Kind regards and thanks for the help,
Pieter-Jan
On 3 November 2010 10:17, Johan Corveleyn <[email protected]> wrote:
> On Tue, Nov 2, 2010 at 11:29 AM, Pieter-Jan Busschaert
> <[email protected]> wrote:
>> Hello,
>>
>> Here is some more information:
>>
>>>> Inside branch1/subfolder, we do a merge from trunk/subfolder.
>>>
>>> Do you mean trunk/project/subfolder here?
>>
>> yes
>>
>>> Anyway, branch1/subfolder does not have any mergeinfo,
>>> since the previous merge was done on branch1. So Subversion
>>> does not know that you have already merged the changes to line 1.
>>
>> Correct, but isn't SVN supposed to crawl up the tree to find
>> mergeinfo? I thought this was the most simple usecase of inherited
>> mergeinfo, which is described in various places, for instance here:
>> http://help.collab.net/index.jsp?topic=/faq/mergeinfo.html
>
> Yes, you are absolutely right. Mergeinfo is normally inherited, so any
> mergeinfo set on the branch1 folder applies to the entire subtree (and
> svn indeed crawls up the tree to find all the mergeinfo that applies).
> Except if the mergeinfo is marked with an asterisk '*', which means
> "non-inheritable mergeinfo". For more in-depth information about
> mergeinfo, see [1].
>
>>> Merges from trunk to branch and vice-versa should always be done
>>> from the root of the project (in your case branches/project/branch1)
>>
>> I can not believe this is true. I can not control the other users and
>> I have had reports of similar issues from a few different users here,
>> so it seems a real use case.
>
> Well, it's *recommended* to do merges always from the project root,
> but it's not required. SVN supports so-called "subtree merges" (which
> have the potential to only merge part of a revision).
>
> The reason it's recommended to do merges from the project root, is
> that it avoids explicit mergeinfo all over your tree. For every
> subtree merge, SVN records explicit mergeinfo on that subtree root.
> This means that that subtree will no longer inherit mergeinfo from
> higher up the tree. For this reason, explicit mergeinfo needs to be
> maintained all the time by SVN (because it will no longer crawl up
> from that point). Every subsequent merge at the project root causes
> those explicit-mergeinfo-paths to have their mergeinfo properties
> updated, even if they are not affected by the merge, which can be
> quite confusing to users. Other than that, subtree merges work just
> fine in SVN, just because of the explicit mergeinfo on the subtrees.
>
> (the upcoming 1.7 release will improve the situation a bit, IIUC: the
> not-affected-subtrees will no longer have their mergeinfo updated all
> the time, only if they are affected by the merge).
>
>>> I don't think so, as I think Subversion did the correct thing, given the
>>> information it has.
>>
>> Well, I still think it did not do the correct thing, as it had more
>> info available than it actually used.
>>
>>> However, I recommend you to push for an upgrade of SVN, as I remember 1.5
>>> was not particularly good with merging.
>>
>> I have just tested with 1.6.13 on a test pc and it behaves exactly the same.
>>
>>
>>
>> By reading the details of inherited mergeinfo in the collabnet FAQ,
>> maybe the bug is because mergeinfo is not up to date in the working
>> copy and SVN uses that instead of contacting the repository. If this
>> is the case, I would expect SVN to give me a "please update" warning
>> when I do the merge command.
>
> Yes, maybe that's the problem. Can you retest this with an update at
> the right place, to see if the problem still occurs?
>
> Maybe you should check out the section "Mixed Revision Working Copies
> and Mergeinfo" in the above mentioned article [1], to see if it
> describes what you're seeing.
>
> If that's the case, you are probably right about the warning. I think
> this is being addressed in the upcoming 1.7 as well (see [2] and [3]).
>
> If the problem is something else, please try to come up with a simple
> reproduction recipe, starting with the creation of an empty repository
> (svnadmin create ...), demonstrating the problem.
>
> Cheers,
> --
> Johan
>
> [1] http://www.collab.net/community/subversion/articles/merge-info.html
> [2] http://svn.haxx.se/dev/archive-2010-10/0000.shtml
> [3] http://svn.apache.org/viewvc?view=revision&revision=1027970
>
$ svnadmin create repo
$ REPO=file://$PWD/repo
$ svn mkdir --parents $REPO/trunk/subdir -m mkdir
Commited revision 1.
$ svn co $REPO wc
A wc/trunk
A wc/trunk/subdir
Checked out revision 1.
$ cd wc
$ echo -e "line1 orig\n\nline2 orig\n\nline3 orig\n" > trunk/subdir/test.txt
$ svn add trunk/subdir/test.txt
A trunk/subdir/test.txt
$ svn ci -m orig
Adding trunk/subdir/test.txt
Transmitting file data .
Committed revision 2.
$ svn cp $REPO/trunk $REPO/branch -m createbranch
Committed revision 3.
$ svn stat -u
* branch/subdir/test.txt
* branch/subdir
* branch
* 1 .
Status against revision: 3
$ svn up
A branch
A branch/subdir
A branch/subdir/test.txt
Updated to revision 3.
$ echo -e "line1 orig\n\nline2 change1\n\nline3 orig\n" > trunk/subdir/test.txt
$ svn ci -m change1
Sending trunk/subdir/test.txt
Transmitting file data .
Committed revision 4.
$ cd branch
$ svn merge $REPO/trunk
--- Merging r3 through r4 into '.':
U subdir/test.txt
$ svn stat -u -v ..
4 4 pjbu ../trunk/subdir/test.txt
3 2 pjbu ../trunk/subdir
3 2 pjbu ../trunk
3 2 pjbu ../branch/subdir
M 3 2 pjbu ../branch/subdir/test.txt
M 3 3 pjbu ../branch
3 3 pjbu ..
Status against revision: 4
$ svn ci -m merge1
Sending branch
Sending branch/subdir/test.txt
Transmitting file data .
Committed revision 5.
$ svn stat -u -v ..
4 4 pjbu ../trunk/subdir/test.txt
3 2 pjbu ../trunk/subdir
3 2 pjbu ../trunk
5 5 pjbu ../branch/subdir/test.txt
3 2 pjbu ../branch/subdir
5 5 pjbu ../branch
3 3 pjbu ..
Status against revision: 5
$ cd ..
$ echo -e "line1 orig\n\nline2 orig\n\nline3 change2\n" > trunk/subdir/test.txt
$ svn ci -m change2
Sending trunk/subdir/test.txt
Transmitting file data .
Committed revision 6.
##############################################
## START : no svn update before merge -> bad
##############################################
$ svn stat -u -v
6 6 pjbu trunk/subdir/test.txt
3 2 pjbu trunk/subdir
3 2 pjbu trunk
5 5 pjbu branch/subdir/test.txt
3 2 pjbu branch/subdir
5 5 pjbu branch
3 3 pjbu .
Status against revision: 6
$ cd branch/subdir
$ svn propget svn:mergeinfo .
$ svn propget svn:mergeinfo ..
/trunk:3-4
$ svn mergeinfo $REPO/trunk --show-revs eligible
r1
r2
r4
r6
$ svn mergeinfo $REPO/trunk --show-revs merged
$ svn mergeinfo $REPO/trunk/subdir --show-revs eligible
r4
r6
$ svn mergeinfo $REPO/trunk/subdir --show-revs merged
$ svn merge $REPO/trunk/subdir
--- Merging r3 through r6 into '.':
U test.txt
$ cat test.txt
line1 orig
line2 change1
line3 change2
$ svn stat -u ../..
M 5 ../../branch/subdir/test.txt
M 3 ../../branch/subdir
Status against revision: 6
$ svn ci -m merge2
Sending subdir
svn: Commit failed (details follow):
svn: Directory '/branch/subdir' is out of date
$ svn up
At revision 6.
$ svn stat -u ../..
M 6 ../../branch/subdir/test.txt
M 6 ../../branch/subdir
Status against revision: 6
$ svn ci -m merge2
Sending subdir
Sending subdir/test.txt
Transmitting file data .
Committed revision 7.
##############################################
## STOP : no svn update before merge -> bad
##############################################
## START : svn update before merge -> good
##############################################
$ svn up
At revision 6.
$ svn stat -u -v
6 6 pjbu trunk/subdir
6 6 pjbu trunk/subdir/test.txt
6 6 pjbu trunk
6 5 pjbu branch/subdir
6 5 pjbu branch/subdir/test.txt
6 5 pjbu branch
6 6 pjbu .
Status against revision: 6
$ cd branch/subdir
$ svn propget svn:mergeinfo .
$ svn propget svn:mergeinfo ..
/trunk:3-4
$ svn mergeinfo $REPO/trunk --show-revs eligible
r1
r2
r4
r6
$ svn mergeinfo $REPO/trunk --show-revs merged
$ svn mergeinfo $REPO/trunk/subdir --show-revs eligible
r6
$ svn mergeinfo $REPO/trunk/subdir --show-revs merged
r4
$ svn merge $REPO/trunk/subdir
--- Merging r5 through r6 into '.':
U test.txt
$ cat test.txt
line1 orig
line2 orig
line3 change2
$ svn stat -u ../..
M 6 ../../branch/subdir
M 6 ../../branch/subdir/test.txt
Status against revision: 6
$ svn ci -m merge2
Sending subdir
Sending subdir/test.txt
Transmitting file data .
Committed revision 7.