[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Problem with "Skipped missing target" after a merge

From: Ryan Schmidt <subversion-2008c_at_ryandesign.com>
Date: Fri, 3 Oct 2008 17:35:18 -0500

On Oct 3, 2008, at 4:39 PM, Babak S. H. wrote:

> On Fri, Oct 3, 2008 at 12:15 PM, Ryan Schmidt wrote:
>
>> On Oct 2, 2008, at 6:56 PM, Babak S. H. wrote:
>>
>>> before setting up a bug report in the svn bug database,
>>> we wanted to query this mailing list in the hope of getting an
>>> explanation
>>> for the following strange behaviour in a merge scenario:
>>>
>>> 1) A virgin repository is created (https://chucky:8443/svn/rep1)
>>> containing
>>> the directories "branches", "tags" and "trunk".
>>>
>>> 2) Repository is checked out in a working copy:
>>> svn co https://chucky:8443/svn/rep1 wc
>>>
>>> A wc\trunk
>>> A wc\branches
>>> A wc\tags
>>> Checked out revision 1.
>>>
>>> 3) Code project folder "proj" is copied into trunk. Folder "proj"
>>> contains merely the file test.cpp.
>>>
>>> 4) "proj" is added to be version managed via svn:
>>> svn add wc/trunk/proj
>>>
>>> A wc\trunk\proj
>>> A wc\trunk\proj\test.cpp
>>> -------------------------------------
>>> svn commit wc/trunk/proj -m "Genesis"
>>>
>>> Adding wc\trunk\proj
>>> Adding wc\trunk\proj\test.cpp
>>> Transmitting file data .
>>> Committed revision 2.
>>>
>>> 5) A private feature branch is created from trunk into branches:
>>> svn copy https://chucky:8443/svn/rep1/trunk/proj https://chucky:
>>> 8443/svn/rep1/branches
>>>
>>> Committed revision 3.
>>>
>>> 6) Working copy is sync'ed with repository:
>>> svn update wc
>>>
>>> 7) Now we rename in [wc/trunk/proj] test.cpp to xyz.cpp (off
>>> course via svn)
>>> svn mv test.cpp xyz.cpp
>>> A xyz.cpp
>>> D test.cpp
>>>
>>> svn commit -m "Moved test.cpp to xyz.cpp"
>>> Deleting proj\test.cpp
>>> Adding proj\xyz.cpp
>>>
>>> Committed revision 4.
>>>
>>> 8) Directory is changed to [wc/branches].
>>> We want to merge the recent changes in the baseline aka trunk
>>> (literally the diff between revisions 2 up to 4) into our
>>> private feature branch:
>>> svn merge -r 2:4 https://chucky:8443/svn/rep1/trunk/proj proj
>>>
>>> --- Merging r3 through r4 into 'proj':
>>> A proj\xyz.cpp
>>> D proj\test.cpp
>>>
>>> 9) In [wc/branches/proj] we modify the content of xyz.cpp and
>>> commit it
>>> creating svn revision 6.
>>>
>>>
>>> 10) Now we want to merge back the work in our branch into the
>>> baseline(trunk).
>>> Directory is changed to [wc/trunk].
>>>
>>> svn merge --dry-run -r 3:6 https://chucky:8443/svn/rep1/
>>> branches/proj proj
>>>
>>> --- Merging r4 through r6 into 'proj\xyz.cpp':
>>> C proj\xyz.cpp
>>> Skipped missing target: 'proj\test.cpp'
>>>
>>>
>>> We wonder about the skipped missing target (proj\test.cpp)
>>> message which
>>> actually shouldn't be any longer around neither in the private
>>> feature branch
>>> nor in trunk after the first merge and commit (steps: 8+9).
>>>
>>> Any hints ?
>>
>>
>> Wrong merge.
>>
>> You already merged changes from trunk into the branch. To now
>> bring the changes from the branch into the trunk, you should
>> therefore do this merge:
>>
>> svn merge https://chucky:8443/svn/rep1/branches/proj@6 https://
>> chucky:8443/svn/rep1/trunk/proj_at_6 proj
>>
>>
>> If you are not yet upgraded to at least Subversion 1.5 on both the
>> client and the server, you may want to do so. Then you can use the
>> new merge tracking features and don't have to worry about
>> specifying revisions to merge. Read about them here:
>>
>> http://svnbook.red-bean.com/en/1.5/svn.branchmerge.basicmerging.html
>
>
> Hello Ryan,
> I off course know that I have merged changes from trunk into the
> branch.
>
> You say "wrong merge" without proving your statement. What's wrong
> with it?

If you had not yet merged any changes from the trunk to the branch,
it would have been the right merge.

>>> svn merge --dry-run -r 3:6 https://chucky:8443/svn/rep1/
>>> branches/proj proj

If "proj" is a working copy of trunk/proj, and the branch contains
only changes that are unique to the branch, then this merge will
merge all those changes from the branch into the trunk working copy.

However, the branch does not contain only unique changes. In revision
5, you merged revisions from trunk into the branch. So now the above
is no longer the correct merge to get all changes from the branch
into the trunk.

Instead, you note that at revision 6, the trunk and branch are equal,
except for the unique changes made in the branch. Therefore the
correct merge is now to apply the differences between trunk_at_6 and
branch_at_6.

> I want my NEW work in the branch (containing the complete work from
> the baseline after merge)
> to be available in the trunk again.
> It is then logically to build up the difference between the
> revision where I created
> my branch (rev.3) up to the branch's head revision (rev.6) and
> apply that diff on the
> head of the baseline=trunk in a checked out working copy.
>
> I think it is nonsense that svn even mentions "proj/test.cpp",
> since that
> file was deleted from both the repository and my working copy.
>
> I read subversion has an issue during "merges and moves" as
> mentioned in
> the svn documentation.
>
> Citation form [http://svnbook.red-bean.com/en/1.5/svn-book.html]:
>
> "Merges and Moves
>
> A common desire is to refactor source code, especially in Java-
> based software projects.
> Files and directories are shuffled around and renamed, often
> causing great
> disruption to everyone working on the project. Sounds like a
> perfect case to
> use a branch, doesn't it? Just create a branch, shuffle things
> around, and then
> merge the branch back to the trunk, right?
>
> Alas, this scenario doesn't work so well right now and is
> considered one
> of Subversion's current weak spots. The problem is that
> Subversion's svn update
> command isn't as robust as it should be, particularly when dealing
> with copy
> and move operations.
>
> When you use svn copy to duplicate a file, the repository remembers
> where the new
> file came from, but it fails to transmit that information to the
> client which is
> running svn update or svn merge. Instead of telling the client,
> "Copy that file
> you already have to this new location," it sends down an entirely
> new file.
> This can lead to problems, especially because the same thing
> happens with renamed files.
> A lesser-known fact about Subversion is that it lacks "true
> renames"—the svn move
> command is nothing more than an aggregation of svn copy and svn
> delete."
>
> ----------------------------------------------------------------------
> -----------------------------------
>
> You suggest to do the following merge instead:
> svn merge https://chucky:8443/svn/rep1/branches/proj@6 https://
> chucky:8443/svn/rep1/trunk/proj_at_6 proj
>
> which builds the difference $DELTA from $A=[branches/proj_at_6] to $B=
> [trunk/proj_at_6]
> and applies it on a local working copy of proj in the trunk directory.
>
> Note that $DELTA is a diff that transforms $A into $B when applied
> on a working copy of $B.
>
> In our case, I think it is wrong to do this merge, since it looses
> information.
> $A has work ($W) that is new and hence not available inside $B yet.
> $DELTA would remove $W from $B when it were available there.
> Since it is not, nothing is deleted in $B, but,
> at the same time we fail to transfer our new work $W into $B.
> That's how information is lost.
>
> The vice versa merge into "proj" directory inside trunk works, though:
> svn merge https://chucky:8443/svn/rep1/trunk/proj@HEAD https://
> chucky:8443/svn/rep1/branches/proj_at_HEAD proj

Yes, I'm sorry; in my haste earlier I transposed the order of the
arguments. Merging is tricky business! :)

This is why you may want to look into the merge tracking in
Subversion 1.5+, since it takes care of some of this trickiness for you.

The correct merge is:

svn merge https://chucky:8443/svn/rep1/trunk/proj@6 https://chucky:
8443/svn/rep1/branches/proj_at_6 proj

You should restrict the merge to occur at revision 6 of both paths,
instead of HEAD, since that is the revision in which you made both
paths the same (except for the changes that you want on the branch),
so that any changes other developers may be simultaneously doing to
either the trunk or the branch don't throw off your merge.

> I am not sure, whether this merge is logically equivalent to my
> back merge described in
> step 10 of my first mail:
>
> ######################################################################
> ############
> 10) Now we want to merge back the work in our branch into the
> baseline(trunk).
> Directory is changed to [wc/trunk].
>
> svn merge --dry-run -r 3:6 https://chucky:8443/svn/rep1/branches/
> proj proj
>
> --- Merging r4 through r6 into 'proj\xyz.cpp':
> C proj\xyz.cpp
> Skipped missing target: 'proj\test.cpp'
> ######################################################################
> ############

They're not equivalent.

svn merge https://chucky:8443/svn/rep1/trunk/proj@HEAD https://chucky:
8443/svn/rep1/branches/proj_at_HEAD proj

computes the difference between trunk/proj_at_HEAD and branches/
proj_at_HEAD and applies it to the working copy proj.

svn merge -r 3:6 https://chucky:8443/svn/rep1/branches/proj proj

computes the difference between branches/proj_at_3 and branches/proj_at_6
and applies it to the working copy proj.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: users-help_at_subversion.tigris.org
Received on 2008-10-04 00:35:46 CEST

This is an archived mail posted to the Subversion Users mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.