When I started talking about the ways which SVN can enable collaboration, my goal was to show how you can replicate some of the best features of a paper based workflow and then supplement them with the power of digital tools. We’ve already looked at some techniques for doing this, using file locks to promote idea ownership and leveraging the SVN log for communications. In this article, we’ll take a look at one more feature that makes it easier to work with others: using SVN snapshots (or branches) to facilitate the review of your work.
Here, I want to reiterate one important point: creating drafts that can be consumed by others is extremely important. It forces you as an author to find break points where you can send something definitive. Finding these points, where you can draw a line in the sand and say “draft …”, causes you to solidify your thinking and take an important step toward completion. You may end up throwing the whole thing away because it was ineffectual, but that doesn’t mean the exercise was futile. The process of creating something, a draft, is an enormous step toward completion. You’ll likely take many such steps, but each one results in a better manuscript.
SVN branches can be a huge help in drawing your lines in the sand.
Version Control Branches
In software development, a branch is used when you want your development process to go into two different directions. For example, let’s say you’ve been working on a program that makes it easier to layout ideas and write a draft of a novel. You’ve finished working on all of the major features and would like to get feedback on how they work. To do this, you might create a branch of your project called “testing” that can be compiled and released to users. But at the same time, you’re not completely finished with the software. So, you keep working on new features in the branch called “trunk.”
Both “testing” and “trunk” have a life of their own. Though they share a common history, at the time that you create the branch, that history splits. This gives you a separate log for each, the ability to check-in separate changes for each. In effect, a separate future for each.
The “testing” branch gets compiled and sent to the users. They’ll find problems with it and submit reports. As these reports come in, you can correct the problems and make commits to the “testing branch.” While that’s happening, though, you can continue your work in the main branch to develop your “big ideas.” When it’s time for the two to come together, you can import the changes in the “testing” branch back into the “trunk” using an operation called “merge.””
Writing projects can also benefit from branches. To see how, let’s consider a simple example.
Let’s say that you’re working on a novel, but you’re not quite sure where to take the plot. You’ve already written one draft of it, but aren’t completely satisfied with the direction it’s going. For that reason, perhaps you want to solicit comments from friends and family. At the same time, you want to begin working on an alternative ending.
To solve this problem, you can branch your work for others to review. In essence, you create a “testing” or “review” branch. Your friends, editor, or co-authors can check out the files, read through the novel, provide feedback, correct typos, and think about the work you’ve already done. At the same time, in the other branch, you work on the alternative version of the story. Both you and your reviewers can work at your own pace because you both have a separate copy of the files. Each copy has its own history and log.
If you don’t like where you end up heading, you can abandon the “experimental” branch you’ve created and resume work on the original branch, once the reviewers have finished with it. If you prefer the alternative ending, you can merge the changes from the “testing” branch into what you’re currently working on.
Creating branches is easy. Subversion makes uses of “directory branches,” which means that a branch shows up in the working tree as a different directory. But though they look like folders, there’s one important difference: a branch is a “cheap copy.” Instead of making a complete copy of every file in the repository, an internal link is created without duplicating data. This means that it’s quick to create branches and they take up almost no extra space in the repository.
Note: Throughout the remainder of this tutorial, I will be using TortoiseSVN to show how to create and merge different branches. The process is very similar for other Subversion clients, KDE-SVN on Linux. It’s also possible to create and merge branches using the command line.
To create a new branch, you select the folder in your working copy which you want to copy. Then, you right click and select “TortoiseSVN > Branch/Tag…” from the context menu.
TortoiseSVN will load the Branch/Tag window and prompt you to add some additional information. First, it will want to know where you would like to store the branched copy. The default location will be the URL which the working copy is based off of. You should edit that URL to something else.
A good practice is to have a folder in the repository where you store all of your branches. Depending on how you use them, you may even want to have multiple folders. Below, you can see the directory structure for a repository for a pair of books I’m working on.
The working text can be found in the “Open Source Writing” and “Open Source Design” folders. Example files, used in both books, are found in the “Examples” folder. Extensions and plugins for the programs covered (some of which I’ve written) are kept in the “Programs and Plugins” folder. I keep branches in one of several top-level folders. If I want to send a review copy, I’ll create the branch in the “Review” folder and then send that to those I’m working with. If I’m soliciting revisions form a collaborator, I may create a branch in a “Collaborators” folder. This keeps them separate from the rest of the project and provides a simple URL that I can give to others.
For this reason, I need to update the destination URL that appears in the “To path:” field of the “Copy (Branch/Tag)” dialog. If I were creating a review copy, I might change it to “draft-20120123”. I would also add a message to the log stating that I had created a review branch. Because I’ll be sending the URL for people to download over an HTTP connection, it’s generally a good idea if the paths to your branches don’t include spaces.
After you specify where the branch should be saved, you then need to decide if you want to create a copy from the current “HEAD”, “a specific numbered revision”, or the local “working copy”:
- If you create the copy from the HEAD, it will save a snapshot of the repository as it exists now. You won’t need to transfer any information from your working copy. As a result, the branch will be created very quickly.
- If you create a branch from a specific revision, it will use an older revision than HEAD. This is useful if you want to get comments on something that may have already changed. If you can’t remember the revision number, you can click on the “Show Log” button help find it. Again, no data is transferred and the branch will be created very quickly.
- If you choose the “working copy” option, the new branch will be made from your local copy. If you have updated some files to an older revision or made other changes, these will be sent to the new branch.
Working With Branches
Once you’ve created the branch, you work with it in the exact same way that you would work with the main text. You can create a local copy of the files by checking it out from the repository,2 providing the path to the branch.
Once the files have finished checking out, you can edit the draft and have all of your changes tracked. When ready to submit the revisions, you commit them back to the branch history. To download additions that others have made to the branch, you update from the repository. Everything works exactly the same as when working with the main body of your text, which is really nothing more than another branch.
At some point, the branch you’ve created will have served its purpose. You will have gotten the feedback you were looking for, your co-authors will have finished with their sections, or you will have completed your alternative ending. At that point, you will be faced with an important decision: what do you want to do with it?
If you created the branch because you wanted to solicit feedback, then it’s likely that you will want to merge the changes back into the main text. If you created the branch to the experiment with the text, then you may not. Or, you might only want to merge a subset of the changes.
Once you’ve begun using branches to solicit review or to create different iterations of your work, it is possible to merge the changes of one branch into another. Subversion provides you with three different options: you can merge a range of revisions from one branch to another, reintegrate all of the changes of one branch into the main working text, or you might want to integrate changes from two different branches into the version you’re currently working on.
Subversion provides you with tools to do all three. Once a branch has been created, you can allow for it to grow as long as you would like. If there’s no good reason to merge two branches, you don’t have to. When it comes time to merge the branches, though, you can merge the entire history of one – back from the time it was split off – into any other, or, you can choose to merge a range of specific revisions.
To begin a merge, you should navigate to the working copy that you would like to hold all of your changes. (Merging always happens in a working copy, which means that if you want to merge changes into a branch you need to have a working copy for that branch checked out.) Then, right click and select “Merge” from the TortoiseSVN context menu. (It’s generally a good idea to merge changes into an unmodified working copy, this will greatly decrease the chance of errors.3) This will launch the Merge Wizard. On the first step of the Wizard, you will be accessed whether you want to merge a range of revisions, reintegrate a branch, or merge two different trees. In most cases, you will want to merge a range of revisions.
From there, you specify which branch you would like to merge the changes from. This goes in the “URL to merge from” field. Then, in the “Revision range to merge” field, you specify which revisions you would like to include. If you want to merge the entire history of the branch into your working copy, just leave the box empty.
If you’re unsure which changes you would like to include, the easiest way to select the range of revisions is to click on the “Show Log” button. This will list recent changes with the log comments.4 If you want to merge changes from several revisions, select the range while holding down the “Shift” key. When you click “Ok”, the list of revision numbers to merge will be filled in for you.
When you have specified which changes you would like to include, click “Next.” The last step is to specify any special options and, optionally, test the merge to see if there any problems. Usually, I just make use of the default merge options.
If will be merging in a large number of changes/edits, it’s generally a good idea to test a merge to see if there will be any conflicts. Knowing which files have conflicts can help you plan how to resolve them. Typically, dealing with “conflicts” in a writing project means that you compare the two files and generate a third which contains all of the changes in both. It is relatively easy to do, but requires that you know which files have to be looked at.
The last step in merging changes is to specify any special options and to test the merge. This will help you locate any conflicts and generate a strategy to deal with them.
If there are no conflicts, you can start the process by clicking on the “Merge” button.
Though the idea of “branching” may take a while to warm up to, it is tremendously powerful. It gives you a way to create a snapshot of your work that can you send to others for review.
For a solitary writer, this is important because it requires you to package the draft for consumption and pushes you toward completion. You branch when ready for specific feedback which gets provided on a copy meant for consumption. The result of which is a better critique, more thoughtful advice, and better writing.
- For TortoiseSVN users, you can open the repository browser by right clicking on the folder you have under version control and selecting “Repo-Browser” from the TortoiseSVN context menu. If opened from your local working copy, it will automatically connect to the repository from which you checked out the files. If you open up the repository browser from a folder not under version control, though, you will need to enter the path to where it can be found.
For Mac OS X Versions users, you can access the repository by clicking on the repository bookmark in the navigation pane. The repository bookmark will usually be above the link to the working copy and uses a small globe icon.
- For instructions on how to checkout files from a remote repository, Getting Started with Subversion, Part: Basics.
- When you use Subversion for writing, handling errors and complex merges is a bit of an art form and requires a bit more discussion. For that reason, we’ll look at it in the next article in this series.
- This is a good example of why you should submit comments in the log which explain what changes were made. Using the log to browse for specific changes is much faster than looking at specific change sets to find the version of the file that you are interested in.