Following up from the previous article about Subversion basics, let's look at some more complicated things you might want to do with your repository and your files: reverting to an earlier revision, splitting a repository and branching a repository.
Using a Previous Version of a File
Say you've made some changes to a file, but have decided they're no good after all and want to go back to an earlier version. In the easy case, when you've scheduled a change but not yet committed it, svn revert filename will restore the version from the most recent commit.
If you want to reverse already committed changes, you can go back further in the history, to an earlier previous version of a particular file. To find the version you want, you'll need to look at the repository history. The command svn log will show you the basic log entries for the directory you're in, or use svn log filename to see the history for just a particular file. To include a list of files changed in each revision in the output, use the -v (verbose) switch.
To get information about the contents of a file, use svn cat or svn diff. svn diff file.txt will show you the differences between your working copy and the most recent copy in the repository. Other alternatives are:
|svn diff -r 123 file.txt||Compare your working copy with revision 123|
|svn diff -r 120:123 file.txt||Compare revision 120 with revision 123|
|svn diff -c 123 file.txt||Compare revision 123 with the previous revision (in this case 122)|
Use svn cat -r 123 file.txt to show the full contents of revision 123 of file.txt.
Once you've found the revision you want, run
svn update --revision 123 filename
BE WARNED: doing this loses any changes you've made to your working version. If there may be changes you need, copy the file elsewhere first.
If you now re-edit filename and try to commit it, you'll get an "Out of date" error message, and when you run svn --update to resolve this, the file will be marked C. This indicates a conflict. Before you commit, you'll need to edit the file in question to resolve the conflict (or to ensure that it's clean), then run
svn resolved filename
There may come a time when you decide your single repository would be better off as two repositories. Maybe you want to divide out the config files from the code or your text notes from your code. Before you start, make sure all working changes are committed (or you'll lose them when tidying up afterwards).
To get a list of the directories in the repository and decide what to move, type:
svn list file:///path/to/repository
svnadmin dump /path/to/repos > repos.dump
svnadmin create /path/to/newrepos
The tool svndumpfilter allows you to choose a particular directory or directories. The command you want is:
cat repos.dump | svndumpfilter include testdir | svnadmin load newrepos
|Some of the output from the import|
All that's left to do after this is to tidy up: delete the dumpfile, delete the migrated directory from the old repository with svn delete .; svn commit (from that directory), and check a working copy back out from the new repository. And you're done!
Note: unfortunately there's no way in Subversion of removing a directory from the database altogether; if you want to do that you'll have to use svndumpfilter exclude to create a new repository without the unwanted directory.
The canonical situation where you'd want to branch is when you want to create a dev branch of a project, so that the main fork can be the stable code. (Or vice versa.) To create a new branch, you must make a copy of the main project:
svn copy /path/to/repos/proj/trunk /path/to/repos/proj/branch
In due course, you'll probably want to merge the changes back into the main tree (e.g. to create your next stable release). This is going to be a little more complicated because chances are, you've made a few changes to the stable branch as well, and it may not be possible to automatically merge them all.
To merge changes from the trunk back to your branch, use
svn merge /path/to/repos/proj/trunk
To merge your branch back into the trunk, first check out a clean copy of the trunk. Then run:
svn merge --reintegrate /path/to/repos/proj/branch
There are of course many more things you can do with your repository – for example, merging two repositories. Subversion is intended to be easy to use, so most things you might want to do are possible.