Today I was asked how to create a branch for someone’s project. Branches are good for projects that take a little longer and involve a bit of trial and error, because you can commit your changes to the branch without disturbing the trunk. Committing often, with only small changes makes everyone’s life easier, because you can revert to a certain point, and of course the repository also serves as a backup of your code.
On the other hand, branches are separate from the trunk, so changes other developers make to the trunk do not automatically appear in the branch. If you use a branch, you have to do some work to keep up with the changes.
To create the branch,
cd into the directory you’re working in (the topmost directory that has a
.svn directory inside), e.g. if you’re working in
/home/mgricken/drjava/drjava.autorefresh is the topmost directory with a
.svn subdirectory, then
Copy the files into a branch by using
Note: I’m using a backslash (
\) at the end of a line and then indent the next line to format the command lines so that they display well on this blog. The backslash indicates that the entire command line should be typed as one line, without the backslashes at the end of the line.
svn copy . https://drjava.svn.sourceforge.net/svnroot/drjava/branches/<branch name> \ -m "Created <branch name> branch"
As branch name, I suggest something like
drjava-autorefresh. For example:
svn copy . https://drjava.svn.sourceforge.net/svnroot/drjava/branches/drjava-autorefresh \ -m "Created drjava-autorefresh branch"
Whether you should name the branch
drjava-autorefresh or just
autorefresh depends on whether you have checked out the entire trunk with all the projects in it, like docs, platform, dynamicjava, etc. (entire trunk) or just the DrJava project (just DrJava). If you have checked out the entire trunk, then name the branch just
autorefresh. If you have checked out only the DrJava project, name it
Subversion will automatically commit this change. When its done, you can go to http://drjava.svn.sourceforge.net/viewvc/drjava/branches/ and you should see a directory with the branch name you chose.
Now you need to do a fresh check out from that branch. You cannot continue to work with the files you have, because they use the trunk. So create a new directory, e.g.
drjava.autorefresh.branch and check out from the branch:
cd .. mkdir drjava.autorefresh.branch cd drjava.autorefresh.branch svn co https://drjava.svn.sourceforge.net/svnroot/drjava/branches/drjava-autorefresh
Subversion will now check out the files from the branch. Now you’re free to commit as often as you like, because you are just working with the branch, not with the trunk. Your changes won’t be visible to other
developers working with the trunk. Just remember to always check out from your branch. To see whether you’re working with a branch or the trunk, you can run
svn info. If you’re working with the trunk, among other things, it will output
If you’re working with a branch, it will output
More information about creating a branch can be found in the Subversion manual.
Every once in a while, you will probably want to merge changes to the trunk into your branch, just so that when you’re finished with the project, your DrJava won’t look completely different from the others’ DrJava. To find out how your branch differs from the trunk, use
svn diff https://drjava.svn.sourceforge.net/svnroot/drjava/branches/drjava-autorefresh \ https://drjava.svn.sourceforge.net/svnroot/drjava/trunk/drjava
If you want to compare your branch to a certain revision, you can add an
@<revision number> after the trunk URL:
svn diff https://drjava.svn.sourceforge.net/svnroot/drjava/branches/drjava-autorefresh \ https://drjava.svn.sourceforge.net/svnroot/drjava/trunk/drjava@4412
To actually merge the changes to the trunk into your branch, use
svn merge https://drjava.svn.sourceforge.net/svnroot/drjava/trunk/drjava .
That merges the differences between your branch and the most recent revision of the trunk into your working copy on your hard drive. If you want to a certain revision of the trunk, you can add
@<revision number> after the trunk URL again. Since the changes are only merged into your working copy, not into the repository, you still have to do a commit.
When you run
svn merge, it will output the files that were changed:
U src/edu/rice/cs/drjava/DrJava.java U src/edu/rice/cs/drjava/DrJavaRoot.java
In some cases, Subversion isn’t able to merge the changes automatically. In that case, it will show that there was a conflict:
In case of a conflict, Subversion will create three files in addition to the original file that has a conflict. In the above example, you will get:
src/edu/rice/cs/drjava/ui/MainFrame.java src/edu/rice/cs/drjava/ui/MainFrame.java.mine src/edu/rice/cs/drjava/ui/MainFrame.java.r<oldrev> (e.g. MainFrame.java.r4415) src/edu/rice/cs/drjava/ui/MainFrame.java.r<newrev> (e.g. MainFrame.java.r4417)
The actual file in conflict,
MainFrame.java, will contain all
versions, separated by lines filled with
====. You can be pretty sure that it won’t compile.
MainFrame.java.mine is the file you had in your working copy before you ran
MainFrame.java.r<oldrev> corresponds to the file in your branch before you changed it in your working copy.
MainFrame.java.r<newrev> is the file from the trunk.
You’ll have to manually compare the three files and edit the file in conflict to produce a file that makes sense. This might involve talking to other developers to figure out what their changes do and how they work. After you have edited the file,
MainFrame.java in this example, so that it compiles and is consistent with both your work and other developers’ work (don’t just copy
MainFrame.java.mine over to
MainFrame.java; that would dismiss the changes by other developers and probably make them angry , you need to run
svn resolved src/edu/rice/cs/drjava/ui/MainFrame.java
Again, since merging happens in your local working copy, if you have any conflicts and you resolved them, you still have to make a commit (which will go into your branch) to move the changes into the repository.
When you have finished your project and you want to merge your branch into the trunk, you pretty much do the same as described above. This time, you check out the trunk, and then specify the URL of your branch for the merge:
svn co https://drjava.svn.sourceforge.net/svnroot/drjava/trunk/drjava cd drjava svn merge https://drjava.svn.sourceforge.net/svnroot/drjava/branches/drjava-autorefresh . svn commit
More information about diff’ing and merging can be found in the Subversion manual.
This was a pretty long post, and some
svn commands are a little complicated. I pretty much always forget how to do things and have to look them up again. Sometimes I accidentally create a branch or merge and then have to delete or revert. But don’t worry, you cannot permanently screw things up, and we’re here to help.
In general, we as the DrJava team probably do not use branches as often as we should. We all know how good it feels to make a commit: It gives you a sense of security, the ability to roll back to that point, and the repository serves as a backup of your code. Branches allow these kinds of “micro-commits” that we should be making. Instead of embarking on a long journey with many changes and no stops in between, we can commit to our branch many times, every time we have reached a nice place to stop, not the top of the mountain, the end of our project, but a plateau, if you will.