We use SVN merging in the Open MPI project, particularly with a /tmp tree that we created at the same level as /trunk. If a developer needs to de-stabilize the trunk for a while, they usually copy the /trunk into a private branch in /tmp (e.g., /tmp/jeff-stuff). Then the developer can go develop there for a while, and merge over updates from the trunk as necessary to start current with the trunk HEAD. Then, when done, /tmp/jeff-stuff can be merged back into the /trunk.

Hence, we do merges in 2 directions -- from the trunk to a branch, and then from that branch back to the trunk. The process is actually identical -- it's just a question of swapping the *from* and *to* arguments on the command line, so to speak.

Merging is *significantly* better than patching when you're adding/removing files, and it helps eliminate potential for human error if trying to replay actions in multiple SVN trees (e.g., commit on the trunk, and then try to replay the same actions on a different tree). Plus, SVN tracks the history accurately (the fact that it was a merge, etc.). Repeat after me: accurate version control history is good.

So how to do this w.r.t. OSCAR?

As with anything, there's a dozen ways to do this.  Here's one way...

Let's take a concrete example -- Dave's recent commits to the trunk that need to be ported over to the branch-4-2. There are three general forms of "svn merge":

1. merge [EMAIL PROTECTED] [EMAIL PROTECTED] [WCPATH]
2. merge [EMAIL PROTECTED] [EMAIL PROTECTED] [WCPATH]
3. merge -r N:M [EMAIL PROTECTED] [WCPATH]

I normally use the 3rd form. Keep in mind that you can *only* merge things that have previously been committed. Put differently: if you want to merge, it must be committed somewhere in the repository already.

Dave's stuff had previously been committed on the trunk, so it meets the criteria.

The first step is to determine exactly what changeset (or changesets) you want to merge. "svn log -v" is your friend here. Dave's stuff is on the trunk, so get a log of the trunk. I have a trunk checkout, so:

$ cd svn/oscar-trunk
$ svn log -v > log.txt

Now examine log.txt and determine which r number(s) that you want to snarf. I'm thinking that we want to grab the following commits:

r3490
r3483-3486

The next step is to get into the *target* tree. So in the OSCAR case, get a checkout of the branch-4-2 tree. If you don't already have one:

$ svn co https://svn.oscar.openclustergroup.org/svn/oscar/branches/branch-4-2 oscar-4.2
$ cd oscar 4.2

So now we're in the branch checkout. The first thing you want to do is ensure that you're not going to try to merge an r number from the trunk that was from before the branch was created. Again, "svn log" is your friend:

$ svn log -v --stop-on-copy

This will show the log on the branch, but it will stop when the branch was created (--stop-on-copy is a cool feature). In this example, the last entry it will show is r3482 -- when John created the branch.

So we can see that all the r numbers above (r3490, r3483-3486) are all after the branch was created, so we're good.

Now we want to apply the revisions. You can either apply them en-masse (only works for contiguous revisions), or you can apply them one at a time -- but only if the commits are non-overlapping (more on this below). We'll do 2 commits here in this example: first we'll merge 3483-3486 and then commit that, and then we'll merge 3490 and commit that.

So let's look at the 3rd form of the merge command and apply it here. It's easiest to show the command and then explain it:

$ svn merge -r3482:3486 https://svn.oscar.openclustergroup.org/svn/oscar/trunk

What this does is pull down the changes from r3482 through 3486 from the trunk URL into the current working directory. NOTICE that I used 384***2***, which is one less than the first r number that we wanted to grab (384***3****). This is because we're dealing with deltas. So to get 3483, we have to ask for the difference between 3842 and 3483. Make sense?

If you run "svn status", you'll see that you have a lot of changes in your working copy:

$ svn st
M      scripts/generic-setup
M      lib/OSCAR/MAC.pm
D packages/sis/distro/common-rpms/systeminstaller-1.04-10oscar.noarch.rpm A + packages/sis/distro/common-rpms/systeminstaller-1.04-11oscar.noarch.rpm D packages/sis/distro/common-rpms/systeminstaller-x11-1.04 -10oscar.noarch.rpm A + packages/sis/distro/common-rpms/systeminstaller-x11-1.04 -11oscar.noarch.rpm
D      packages/sis/SRPMS/systeminstaller-1.04-10oscar.src.rpm
A  +   packages/sis/SRPMS/systeminstaller-1.04-11oscar.src.rpm

So this pulled over all the changes from r3482 through r3486 and put them as local changes in your tree. Now you have to commit them:

$ svn ci
...editor comes up...

I typically put in a message indicating that this is a merge, and I include the specific "svn" command that I used to pull them down, and then all the log messages for the r numbers that I committed. For example:

-----
This commit is a merge of several commits from the trunk:
svn merge -r3482:3486 https://svn.oscar.openclustergroup.org/svn/oscar/trunk

Commit message for r3486:
Type on help

Commit message for r3485:
Bug: 1258729; 'Assign All' doesn't enable properly

Commit message for r3484:
Fix systeminstaller BuildRequires and Requires

Commit message for r3483:
Fix generic-setup
------

So the first merge is committed and done. But we still have one more commit that we want to pull from the trunk -- r3490. So we do another "svn merge" command:

$ svn merge -r3489:3490 https://svn.oscar.openclustergroup.org/svn/oscar/trunk

Again, notice that we have to give a *delta* specification here, so we're grabbing the difference between 3489 and 3490 from the trunk.

Now commit it:

$ svn ci
...editor comes up...

-----
This commit is a merge of several commits from the trunk:
svn merge -r3489:3490 https://svn.oscar.openclustergroup.org/svn/oscar/trunk

--
{+} Jeff Squyres
{+} [EMAIL PROTECTED]
{+} http://www.lam-mpi.org/Commit message for r3490:
RFE 1052496; file choosers in Build Image only show appropriate files
------

Let's have a quiz to see if you were really paying attention. Would the following have worked?

$ svn co https://svn.oscar.openclustergroup.org/svn/oscar/branches/branch-4-2 oscar-4.2
$ cd oscar 4.2
$ svn merge -r3482:3486 https://svn.oscar.openclustergroup.org/svn/oscar/trunk $ svn merge -r3489:3490 https://svn.oscar.openclustergroup.org/svn/oscar/trunk
$ svn ci

What do you think? All we did here was do both merges before committing (as opposed to merge/commit/merge/commit).

The answer is *no* -- it would not have worked.

But why?

It's because there were overlapping, conflicting changes between the two merges. Specifically, in the first merge, we added file A. Then, in the second merge, we removed file A. This is Bad -- don't do this without an intervening commit. SVN will give you warnings during the merge if this kind of situation arises (actually, SVN may have the wherewithal to make this all Just Work, but in general, it's bad practice -- don't do it). In fact, the only reason we could apply 3482-3486 together is because there were no overlapping adds/removes (multiple, non-exclusive patches to a single file are fine, of course -- by definition, you wouldn't really run into this kind of problem by pulling a contiguous series of commits from a single tree, of course, but if you try to do complex merges by pulling in non-contiguous revisions or from multiple sources, you can run into conflicting patches to a single file).

For those looking at the fine print, file A was /trunk/packages/sis/distro/common-rpms/systeminstaller-x11-1.04 -11oscar.noarch.rpm.

There you go.  SVN merging in simplicity.  :-)

--
{+} Jeff Squyres
{+} The Open MPI Project
{+} http://www.open-mpi.org/



-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
Oscar-devel mailing list
Oscar-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oscar-devel

Reply via email to