You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by Joe <sv...@freedomcircle.net> on 2004/12/22 04:10:32 UTC

Common Use-Cases for Merging

Hi,

Chapter 4 of the SVN book doesn't seem to cover what I think is a common 
occurrence: branching back to the trunk a file added in a branch. The 
section discusses mostly the use of "svn merge", but that doesn't seem 
to allow such an operation. I assume the right command is to use "svn 
copy" to propagate the addition (it seems obvious, but maybe not to a 
newbie).

I also have a more complicated scenario. In the branch, I added a new 
file by branching it from an existing file in the branch and modifying 
it prior to committing. For example, svn copy foo.php bar.php and edit 
bar.php prior to svn commit. Now I want to merge bar.php into the trunk. 
One option would be to copy foo.php to bar.php in the trunk and then use 
svn merge to attempt to apply the changes made in the branch (don't know 
if this works). The second option would be to svn copy bar.php directly 
from the version in the branch. In the former case, the ancestry of the 
trunk bar.php would remain within the trunk, with changes merged from 
the branch. In the latter case, the ancestry of the trunk bar.php would be

bar.php (trunk) <- bar.php (branch) <- foo.php (branch) <- foo.php (trunk)

Is there any advantage to doing this one way or the other? Presumably, 
foo.php and bar.php will lead separate lives in the future, but since 
they still share some (redundant code) it's possible that a change in 
one file may have to be replicated to the other three versions.

Incidentally, is there an "error messages explained" somewhere? When I 
was trying some of the merge commands I got a "svn: Cannot replace a 
directory from within". I did a Google search but none of the results 
was very elucidating.

Joe


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: Common Use-Cases for Merging

Posted by Joe <sv...@freedomcircle.net>.
Christopher Ness wrote:

> Visually, it looks like this, time is left to right:
> 
>                          [changes made]
> /branch --------- bar.c@11 ------------------ bar.c@12
>               |[copy]                             |
>               |                                   |[merge]
> 
> /trunk/ --------- foo.c@10 ------------------------------------
>               |                                   |
>               |[copy]                             |
>               |-- bar.c@11 -------------------------- bar.c@13

Actually, my case is slightly different (the main point is foo.c was 
branched as foo.c, only later becoming bar.c).

                        [changes made]
  /branch ------- foo.c@5 ------- foo.c@8-------------------
                |[copy]           |[merge]  |
                |                 |         bar.c@10--------
                |                 |                |[merge]
  /trunk  ----- foo.c@4 --------- foo.c@9-------------------
                                  |                |
                                  |[copy]          |
                                  |-- bar.c@11-- bar.c@13---

> Thanks for the mental gymnastics.

You're welcome! And thanks for reminding me of these diagrams.

Joe


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: Common Use-Cases for Merging

Posted by Christopher Ness <ch...@nesser.org>.
On Wed, 2004-22-12 at 20:52 -0500, Joe wrote:
> $ svn copy file:///svn/repo/trunk/foo.php bar.php
> A        bar.php
> $ svn merge file:///svn/repo/branches/dev/foo.php@9 
> file:///svn/repo/branches/dev/bar.php@10 bar.php
> U        bar.php

Bingo!  I did the commands below on my test repo.  I don't know why svn
didn't create the file on the copy when someone tries to merge a
directory that has a copy in it.  

Some of the higher ups might be able to shed some insight as to why the
merge wouldn't create the file.  I would assume a delete would of a file
in a branch directory would remove that file.  
Maybe it was the fact you ended up renaming the file during the copy.

[nesscg@woman trunk]$ svn cp -r10 foo.c bar.c
A         bar.c
[nesscg@woman trunk]$ svn merge -r11:12 ../branch/dev/bar.c
U  bar.c

Visually, it looks like this, time is left to right:

                         [changes made]
/branch --------- bar.c@11 ------------------ bar.c@12
              |[copy]                             |
              |                                   |[merge]

/trunk/ --------- foo.c@10 ------------------------------------
              |                                   |
              |[copy]                             |
              |-- bar.c@11 -------------------------- bar.c@13

Thanks for the mental gymnastics.
Chris
-- 
Software Engineering IV,
McMaster University
PGP Public Key: http://www.nesser.org/pgp-key/
21:22:56 up 1 day, 9:28, 3 users, load average: 0.08, 0.13, 0.06 
http://www.fsf.org/philosophy/no-word-attachments.html

Re: Common Use-Cases for Merging

Posted by Joe <sv...@freedomcircle.net>.
Christopher Ness wrote:

> On Wed, 2004-22-12 at 18:13 -0500, Joe wrote:
>> [cut]
>>$ cd [trunk working copy directory]
>>$ svn copy file:///svn/repo/trunk/foo.php bar.php
>>$ svn merge ???
>>$ svn commit
> 
> 
> If I've got this right, the file `bar.php' does not exist in /trunk/ at
> all.
> 
> Technically in your second choice I don't think you should have to run
> `svn copy` since `svn merge` is more than just a patch program.  It also
> knows about changes to directory structures [aka additions and
> deletions].

I understand quite well that svn merge is more than patch. However, the 
problem is what two entities in the repository are to be merged. Since 
bar.php doesn't yet exist in the trunk, I believe I must do a copy first 
in order to let Subversion know that it is going to be added. For 
example, if I try

$ svn merge file:///svn/repo/trunk/foo.php 
file:///svn/repo/branches/dev/bar.php bar.php
svn: Use --force to override this restriction
svn: 'bar.php' is not under version control

When I add --force, it still gives me the same error. Here's what I 
ended up doing (although I haven't committed yet):

$ svn copy file:///svn/repo/trunk/foo.php bar.php
A        bar.php
$ svn merge file:///svn/repo/branches/dev/foo.php@9 
file:///svn/repo/branches/dev/bar.php@10 bar.php
U        bar.php

Figuring this out has been very educational. I'm glad that svn info and 
svn log -v provided the info necessary to "untangle the mystery".

Regards,

Joe


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: Common Use-Cases for Merging

Posted by Christopher Ness <ch...@nesser.org>.
On Wed, 2004-22-12 at 18:13 -0500, Joe wrote:
> The question now is: Is it better to
> 
> $ cd [trunk working copy directory]
> $ svn copy file:///svn/repo/branches/dev/bar.php bar.php
> $ svn commit
> 
> OR
> 
> $ cd [trunk working copy directory]
> $ svn copy file:///svn/repo/trunk/foo.php bar.php
> $ svn merge ???
> $ svn commit

If I've got this right, the file `bar.php' does not exist in /trunk/ at
all.

Technically in your second choice I don't think you should have to run
`svn copy` since `svn merge` is more than just a patch program.  It also
knows about changes to directory structures [aka additions and
deletions].

Reading this page should clear things up.  Take note of the box titled
"Why Not Use Patches Instead?".
          http://svnbook.red-bean.com/en/1.0/ch04s03.html

So as an experiment try to merge all the changes you made on the branch
into the trunk and see what happens.  Make sure you have no local
changes in your working copy so you will not lose changes if you want to
do a `svn revert`.  That is if things do not work out the way you would
like.

> After the commit, say at rev 11, in the first case, bar.php would show 
> its "roundabout" ancestry, i.e., from trunk/foo.php to 
> branches/dev/foo.php to branches/dev/bar.php to trunk/bar.php. In the 
> second case, trunk/bar.php would only show trunk/foo.php as its 
> ancestor. On the surface, this simplified ancestry appears preferable 
> but I haven't explored all the implications and that's why I was seeking 
> guidance from others. I'm presuming, perhaps incorrectly, that this is 
> not such an outlandish scenario.

No, I don't see it as an outlandish scenario.  It's always good to know
where a file came from.  Your commit message should say the file name
the new file is copied from and at what revision you took copied it as
well!  That way it's easier to discover months from now when you have
forgot.

This is a repository policy decision that you need to make.  There are
way more than one way to skin a cat but I think you are going about this
the correct way.

> Would it have been better to create bar.php without letting Subversion 
> know about foo.php as its ancestor? As it is, the real foo.php and 

My opinion is no.  It is the more difficult method (vi foo.php; :w
bar.php; svn commit bar.php; is easier, but you lose ancestry), but I
think you are getting more rewards by svn copy or svn merge.

It looks like you could have simply svn copy'd on the trunk without
making it in a different "branch" URL.

> bar.php files have about 450/460 lines each and a straight diff (not -u 
> or -c) has about 100 lines, so it seems reasonable to try to tie the two 
> together.

I agree, I think you should keep the ancestry of the file. 

You seem to have everything in order and a good start on the problem.
Let us know if you run into any more problems along the way.

HTH's
Chris
-- 
Software Engineering IV,
McMaster University
PGP Public Key: http://www.nesser.org/pgp-key/
19:20:39 up 1 day, 7:25, 3 users, load average: 0.35, 0.23, 0.12 
http://www.fsf.org/philosophy/no-word-attachments.html

Re: Common Use-Cases for Merging

Posted by Joe <sv...@freedomcircle.net>.
Christopher Ness wrote:

> What are the 3 versions again?  I got lost along the way.

I was afraid of that :-)  Let me try to explain better by providing a 
more complete example:

$ svn import project file:///svn/repo -m "initial import"
Adding project/trunk
Adding project/trunk/foo.php
...
Committed revision 1.
$ svn checkout file:///svn/repo project
A project/foo.php
...
Checked out revision 1.
[additional changes made and committed to foo.php]
$ svn copy file:///svn/repo/trunk file:///svn/repo/branches/dev -m 
"development branch"
Committed revision 5.

Additional changes were then made and merged to foo.php in both trunk 
and branches/dev such that svn diff between the two at rev 9 shows a 
single line difference--an extra error_reporting(E_ALL) in the 
development code. Now we decide to create bar.php, which is very similar 
to foo.php, so it seems like a good idea to copy foo.php and modify it.

$ cd [development working copy directory]
$ svn copy file:///svn/repo/branches/dev/foo.php bar.php
A       bar.php
$ [edit bar.php]
$ svn commit
Adding bar.php
...
Committed revision 10.

Now svn log bar.php shows the ancestry of branches/dev/bar.php all the 
way from the rev 1 import (as foo.php in trunk) through the branch in 
rev 5 (-v shows "from /trunk:4") and to the addition in rev 10 (-v shows 
"from /branches/dev/foo.php:9").

The question now is: Is it better to

$ cd [trunk working copy directory]
$ svn copy file:///svn/repo/branches/dev/bar.php bar.php
$ svn commit

OR

$ cd [trunk working copy directory]
$ svn copy file:///svn/repo/trunk/foo.php bar.php
$ svn merge ???
$ svn commit

The latter merge would apply to the trunk (working copy) bar.php the 
same set of changes that were applied to branches/dev/foo.php@9 to 
become branches/dev/bar.php@10. I haven't tried this option yet, so I'm 
not sure about the syntax.

After the commit, say at rev 11, in the first case, bar.php would show 
its "roundabout" ancestry, i.e., from trunk/foo.php to 
branches/dev/foo.php to branches/dev/bar.php to trunk/bar.php. In the 
second case, trunk/bar.php would only show trunk/foo.php as its 
ancestor. On the surface, this simplified ancestry appears preferable 
but I haven't explored all the implications and that's why I was seeking 
guidance from others. I'm presuming, perhaps incorrectly, that this is 
not such an outlandish scenario.

Would it have been better to create bar.php without letting Subversion 
know about foo.php as its ancestor? As it is, the real foo.php and 
bar.php files have about 450/460 lines each and a straight diff (not -u 
or -c) has about 100 lines, so it seems reasonable to try to tie the two 
together.

Regards,

Joe


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: Common Use-Cases for Merging

Posted by Christopher Ness <ch...@nesser.org>.
On Tue, 2004-21-12 at 23:10 -0500, Joe wrote:
> Chapter 4 of the SVN book doesn't seem to cover what I think is a common 
> occurrence: branching back to the trunk a file added in a branch. The 
> section discusses mostly the use of "svn merge", but that doesn't seem 
> to allow such an operation. I assume the right command is to use "svn 
> copy" to propagate the addition (it seems obvious, but maybe not to a 
> newbie).
> 
> I also have a more complicated scenario. In the branch, I added a new 
> file by branching it from an existing file in the branch and modifying 
> it prior to committing. For example, svn copy foo.php bar.php and edit 
> bar.php prior to svn commit. Now I want to merge bar.php into the trunk.

Interesting it looks like you branched in the same directory of the url
but with a different file name.  I'm not sure why, but that's ok.

Usually a branch from /trunk/ is copied to /branch/ using the same file
names but different "paths" or URL's in the repository.  But if you have
a base PHP template and you want to start from there on a new file this
is perfectly fine.
 
> One option would be to copy foo.php to bar.php in the trunk and then use 
> svn merge to attempt to apply the changes made in the branch (don't know 
> if this works). The second option would be to svn copy bar.php directly 

I don't think there is any need to "copy" the file back.  Try this using
your svn copy command above:

svn merge foo.c@HEAD bar.c@HEAD ./foo.c

I think that should do it.  See `svn help merge` example number 2.
I tested it and it "worked for me".

> from the version in the branch. In the former case, the ancestry of the 
> trunk bar.php would remain within the trunk, with changes merged from 
> the branch. In the latter case, the ancestry of the trunk bar.php would be
> 
> bar.php (trunk) <- bar.php (branch) <- foo.php (branch) <- foo.php (trunk)

Is this equivalent to what you have above?
/trunk/bar.php <- /branch/bar.php <- /branch/foo.php <- /trunk/foo.php

I'm not sure why you want to change the name, but that's up to you.

> Is there any advantage to doing this one way or the other? Presumably, 
> foo.php and bar.php will lead separate lives in the future, but since 
> they still share some (redundant code) it's possible that a change in 
> one file may have to be replicated to the other three versions.

What are the 3 versions again?  I got lost along the way.

> Incidentally, is there an "error messages explained" somewhere? When I 
> was trying some of the merge commands I got a "svn: Cannot replace a 
> directory from within". I did a Google search but none of the results 
> was very elucidating.

I think this link is relevant to your problem.
http://svn.haxx.se/users/archive-2004-11/1336.shtml

Cheers,
Chris
-- 
Software Engineering IV,
McMaster University
PGP Public Key: http://www.nesser.org/pgp-key/
12:08:50 up 1 day, 14 min, 4 users, load average: 0.08, 0.02, 0.01 
http://www.fsf.org/philosophy/no-word-attachments.html