Table of Contents
Working with branches
NOTE: The rosegarden svn URL on sourceforge has changed. This page has only been partially updated to reflect that. Usually it is simply a matter of replacing all
Keep this in mind while reading this page…
When to branch?
To branch or not to branch?
The decision whether to branch or not is not really something that follows a strict formula, but you should consider doing your work in a branch if it:
Of these, the only really critical and absolute rule is that you must always exercise all possible caution to try to avoid breaking trunk/, and if you ever anticipate committing half-working code, you should almost certainly do this in a branch.
Moving existing code into a branch
The best practice is to think everything out before you begin, realize that you will need to work in a branch, create that branch, and do all your work in there from the beginning.
In reality, it is very common for a developer to begin some project without thinking all of this through for one reason or another. Perhaps what was supposed to be simple has turned out to be much more complicated than expected. Maybe a quick hour of code to knock something out is going to turn into a week or more before all the unexpected problems can be sorted out. Sometimes, you will even begin working from and committing to trunk/ without realizing that your work really should have been done in a branch first, and someone will ask you to branch and complete your work there; merging it after whatever controversy is resolved to everyone's satisfaction.
This is simple to deal with, if this every happens to you. Simply take a patch of your current working copy before you proceed with creating a branch and checking it out.
svn diff > <patch_my_branch>
Note: Replace <patch_my_branch> with a real filename of your choosing
To avoid causing yourself problems down the line, now that you have taken this patch to use later, you should revert these changes from your working copy of trunk/ before continuing.
patch -R -p0 < <patch_my_branch>
You can double check that everything worked properly by running
This should produce no output.
Note This technique works very well if all of your modifications were to files that were already under version control. If you have already started adding new files, but have not yet put any of them under version control, they will not be included in your patch, and you will need to keep up with them and move them into your working copy of your new branch later on. Unfortunately, svn diff is of no help in this situation.
Creating a new branch
Whether you are beginning completely from scratch, or you are creating a branch out of existing work you began in trunk/, the next step in this process is to create the branch itself in the Subversion repository.
Create a new branch by copying trunk/. For example, for a branch called <my_branch>, do the following (as a single one-line command):
svn copy svn+ssh://<user>@svn.code.sf.net/p/rosegarden/code/trunk/rosegarden \ svn+ssh://<user>@svn.code.sf.net/p/rosegarden/code/branches/<my_branch>
You can see what branches already exist (so as to get ideas for a new name, perhaps) using
svn ls http://svn.code.sf.net/p/rosegarden/code/branches/
(Or you can browse the online Subversion repository at http://sourceforge.net/p/rosegarden/code/)
Note: Replace <user> with your SourceForge username and <my_branch> with your branch name.
Checking out a branch
svn co <my_branch>
The full command to checkout my_branch using username is:
svn checkout svn+ssh://<user>@svn.code.sf.net/p/rosegarden/code/branches/<my_branch> <my_branch>
Note: Replace <user> with your SourceForge username and <my_branch> with your branch name.
After the checkout completes, take note of the revision number for later, so you don't have to dig it back up when it comes time to merge. The last message from Subversion will tell you this piece of information, for example:
Checked out revision 10745.
Applying your patch
If you took a patch of the work you began in trunk/ then now is the time to apply that patch to your new working copy of your new branch. Simply use
patch -p0 < <patch_my_branch>
Note: Be sure not to use the -R option in the patch command this time. Replace <patch_my_branch> with the real filename you selected earlier.
If you created any files that were not yet under version control, and were not included in that patch, now is the time to move them across into this directory.
Now you are ready to commit the beginning of your new branch, and get to work in here!
Committing changes to the branch
Working with branches is as easy as working with the trunk. Commit the changes from the root directory of the branch.
cd <my_branch> svn commit -m "Text which describes the updates."
Merging changes from a branch to trunk
For most branches, you want to keep the merge as simple as possible, and only do this once. Chris Cannam recommends ignoring trunk/ until you are ready to merge, and then doing the merge starting by taking a temporary working copy of trunk/ to get started:
$ svn co https://rosegarden.svn.sourceforge.net:/svnroot/rosegarden/trunk/rosegarden \ tmp-working-copy
Then change into tmp-working-copy/, and using the revision at which you branched (which you took note of earlier) and the name of your branch, do something like:
$ cd tmp-working-copy $ svn merge -r<10208>:HEAD https://rosegarden.svn.sourceforge.net:/svnroot/rosegarden/branches/<my_branch>
Note: Replace <my_branch> with your branch and and <10208> with revision number of the branch noted earlier. Resolve conflicts, build, test… Then run
to make sure what you're about to commit looks sane. Then fire away with
Merging changes from trunk to the branch
If you are going to be working on the branch for a long time, you may wish to reduce the number of conflicts you may eventually have to resolve by periodically merging from trunk/ into your branch, and then merging the branch back at the end of its life cycle.
You may check the Last Changed revision of the branch with command
Let us suppose that the last changed svn version was 8114. Then you would like to merge all changes since svn version 8115. You may do it with command
svn merge -r 8115:HEAD https://rosegarden.svn.sourceforge.net/svnroot/rosegarden/trunk/rosegarden
If there are no conflicts, you may continue by committing the changes to the branch.
svn commit -m "merge from trunk"
Note that such a committing does not work if you had conflicts, therefore, resolve conflicts before committing changes.
A conflict occurs when you try to update your working copy from a repository that has conflicting changes in it. This can happen during the normal course of development, when two different people happen to work in the same place. (One common circumstance is that developer C commits broken changes, and both developers A and B rush in with two slightly different, conflicting fixes.)
During a merge, this happens when your branch changes some part of the code that also changed in trunk/, and Subversion cannot decide how to put all the pieces together.
When you experience a conflict (such as the real conflict upon which I'm basing this example), recent versions of Subversion will prompt you what to do:
Conflict discovered in 'data/rc/rosegardenui.rc'. Select: (p) postpone, (df) diff-full, (e) edit, (h) help for more options:
Chris recommends that you just choose p to postpone conflict resolution. (For binary conflicts, you will also get tf and mf for “theirs full” and “mine full” respectively. Which to choose will depend entirely on the circumstances.)
(h) help for more options: p --- Merging r10774 through r10874 into 'data/rc': C data/rc/rosegardenui.rc
After the conflict, you wind up with several files, similar to these:
Chris works with the plain .c file, which is the original file with the conflicts given in an “alternatives” diff-like form, such as this excerpt:
<Action name="file_revert"/> </enable> </State> <<<<<<< .working <State name="have_project_packager"> <enable> <Action name="file_import_project"/> <Action name="file_export_project"/> </enable> </State> ======= >>>>>>> .merge-right.r10874 <State name="have_segments"> <enable> <Action name="move"/>
In this case, I apparently removed some code from part of the file that simultaneously changed in trunk/ and Subversion got confused. I can't remember what I did where, or who did what, so while Chris recommends working only with the plain .c file, I have found I can't figure out what I'm looking at in this case.
I decided to have a look with Kompare.
kompare rosegardenui.rc.merge-left.r10773 rosegardenui.rc.merge-right.r10874
I find the visual presentation easier for getting a real sense of what's going on, although the particular example I happened to have chosen to present here (because it was the first one I had at hand) is not particularly good. This conflict is easy to resolve.
In any case, once you have discovered what is going on to your satisfaction, edit the file until you're happy with it, then run
svn resolved <filename>
to tell Subversion that you have resolved the conflict.
Test and commit.
Closing a branch
When a branch is finished with, we usually either delete it if it was very short-lived and uninteresting,
svn rm https://<user>@rosegarden.svn.sourceforge.net/svnroot/rosegarden/branches/uninteresting
or else move it to the branches/obsolete directory on the Subversion server. If in doubt, do the latter:
svn mv https://<user>@rosegarden.svn.sourceforge.net/svnroot/rosegarden/branches/my_branch \ https://<user>@rosegarden.svn.sourceforge.net/svnroot/rosegarden/branches/obsolete/
Example of a planned and focused branch