Subversion

Subversion
Subversion is a version control system designed to replace to CVS.

Admin commands

 * svnadmin create [--fstype fsfs|bdb] 

While BDB (Berkeley DB) has been the default for a long time, releases 1.4 and later default to FSFS. It's able to handle large repositories just as well, and it doesn't have as many issues with log files growing, doesn't have to be cleaned after a crash, and needs less special attention during backups.

Easy Setup For SVN+SSH
Note: Usually renaming the svnserve executable is a terrible solution, although it's unfortunately recommended by many very intelligent people. It makes it difficult to run more than one repository on the same server since they all use the same svnserve program whether it's customized or not. Plus it's an annoyance when you upgrade Subversion because most packaging systems will clobber your wrapper and it'll be difficult to remember to reinstall it. Unfortunately, the Subversion client doesn't seem to have any configuration knob for the command to execute on the server; it's hard-coded to "svnserve -t". (If this is wrong, please update this and describe how to do it.) There's a simple but unfortunate kludge to get around this, described below.

Add a user and group named svn. All read-write access will use the svn user ID. Add users who need read-write access to the svn group. sudo will allow these users to switch to the svn user ID.

Add the following to /usr/local/etc/sudoers. %svn ALL = (svn) NOPASSWD: /usr/local/bin/svnserve-wrapper

Create /usr/local/bin/svnserve-wrapper as follows. This places the configuration of the repository's root in one easy place to update on the server, plus it prevents abuse of the svn account. umask 022 /usr/local/bin/svnserve --root=/project/svn --tunnel --tunnel-user=`logname`
 * 1) !/bin/sh

Execute: $ chown -R svn:svn /project/svn $ chmod +x /usr/local/bin/svnserve-wrapper

Unfortunately, each client needs a tweak. Add the following to the client's ~/.subversion/config. [tunnels] wrapper = svn+wrapper

Create svn+wrapper in the path of the client and set it +x: ssh $1 'sudo -u svn svnserve-wrapper'
 * 1) !/bin/sh

Check out the repository: $ svn checkout svn+wrapper://svn.example.com/project-name

Note: Remember to execute all svnadmin commands as the svn user. If you forget, chown the repository again. For example: sudo -u svn svnadmin

Easy Setup For Public Access To Your Repository
Add to /etc/inetd.conf: svn stream tcp nowait nobody /usr/local/bin/svnserve svnserve --root=/project/svn --inetd

Check out the repository: $ svn checkout svn://svn.example.com/project-name

Client commands
In general, the client commands take the format of "command URI [flags] [ revision number or range ]" All of these commands have more flags than are mentioned here, use svn help co to see more information on the checkout command, for example.


 * Getting a local copy of the repository in the first place
 * svn co URI - This particular URI may be more complicated than any of the others you use.
 * svn co file:///home/svn/repository/glibc/trunk/glibc would checkout the trunk of the glibc project in a repository stored on a local machine into your current directory.
 * svn co file:///home/svn/repository/glibc/branches/franks_build/glibc would checkout the branch being worked on by your good friend frank. (see Svn for more information on branches and merges between branches)
 * svn co svn+ssh://username@myserver/home/svn/repository/glibc/trunk/glibc would download from a remote repository on server 'myserver' via an ssh tunnel. Everytime you connect to that server, you will authenticate using ssh (ie, ssh keys are really convenient here).
 * Hint: you can use svn ls with the same URI you use for a checkout to browse through a repository before downloading or copying the whole thing
 * svn cat URI - If you don't want to bother downloading the actual archive, with all the svn information, this command can be useful to grab a single file.
 * svn cat file:///home/svn/repository/glibc/trunk/ChangeLog -r543 > old_changelog might be useful to grab an older/newer version of a changelog, for example.
 * Syncing your local copy with your repository
 * svn up - This will update your local copy with any changes that have been made by other people in the repository. svn up -r38 will update or backdate your local copy to revision 38. If there is a conflict during an update between your local files and files that other people have edited, svn will attempt to merge them nicely. If it cannot, it will generate several files:
 * conflictedfile.c.r### - two of these will be created, one for the original revision you checked out, one for the revision that conflicts with your changes
 * conflictedfile.c.mine - this is a copy of your local version
 * conflictedfile.c - This is a slightly mangled copy, that includes both versions inline with >>>>>, <<<<< and ===== markers (you can search for them to find conflict easily).
 * When you have decided how you will resolve this conflict, make the conflictedfile.c be the version you want to keep, and use the svn resolved command.
 * svn resolved  - This marks a given files conflicts between the repository and local copy as resolved, removes the extra files generated by svn up, and clears away the flags that would prevent you from checking in your changes.
 * svn ci or svn ci somefile.c - This will upload your changes (in the current directory or to a particular file) to the server. When you use this command, svn will open an svn-commit.txt message in your $EDITOR, to allow you to enter your log message. Below the line, it lists the files that you will be changing in this commit. You cannot check in changes if you have a conflict (see svn up) without resolving the conflict first.
 * svn revert  - If you decide that your local changes were, perhaps, a bit unwise... you can undo any damage you've done by reverting those changes back to the version that matches your last svn update. The -R flag allows this command to extend recursively through a directory tree.
 * Getting information - Most commands can omit the file/directory argument and will print information about the current directory.
 * svn status or svn st  - This will list all files in the specified (or current) directory that have changed in some ways since the last "svn up". Each symbol on the side identifies a different type of change. This can be a quick way to check what you have changed so far, and is wise to check before doing a commit. One note of importance: Anything marked with a "?" is a file that is not under version control, these files will NOT be committed to the repository when you do a svn ci.
 * svn di or svn di URI [ URI ] - This generates a unified diff between two versions of a file/directory tree/repository. The default version simply shows you a diff between the original checked out version and the current working copy. Most of the time, the output of this command will be a legal -p0 patchfile.
 * svn info or svn info  - This command will return information on the current revision, last revision changed, and time and date information about the repository or file. Checking the svn info at a particular revision is allowed.
 * svn log or svn log URI - This will print out the revision logs either from the first revision up to the current one, or just in the specified revision number or range.
 * svn ls URI - This command lists the files in the directory or URI specified. It is most useful when working on a remote URI (prior to checkout, for example), and/or when listing files present in the repository at a particular revision.
 * svn blame  - This will cat a version of the specified file that includes on each line a revision number (the revision that it was added/changed) and a name (the name of the committer who added/changed it).
 * Adding and removing things - If the URI is remote, some of these commands can work on the repository itself
 * svn add  - This is used to add a new source file to a repository that includes your current directory.
 * svn mkdir  - This will add a new directory to the repository. You can also use "mkdir dir_name && svn add dir_name", but this is a bit easier.
 * svn cp URI URI - You can copy from a particular revision of the source URI by using a revision specifier
 * svn rm  - This will immediately remove the file in your local copy, and it will be removed from the repository the next time you commit.
 * svn mv URI URI - You can move from a particular revision of the source URI by using a revision specifier

Access Methods
The uri can be:


 * A file in your working copy: mycodefile.c
 * A file in a repository on the local filesystem: file:///home/frank/franks_svn/myproject/trunk/projectdir/mycodefile.c
 * A file in a remote repository, using one of the following protocols:
 * SSH: svn+ssh://username@server/home/frank/franks_svn/myproject/trunk/projectdir/mycodefile.c
 * svnserve (which is analogous to CVS's pserver) (read-only access does not require authentication): svn://username@server/home/frank/franks_svn/myproject/trunk/projectdir/mycodefile.c
 * HTTP: http://username@server/home/frank/franks_svn/myproject/trunk/projectdir/mycodefile.c

Revision Specifiers
The basic form of the revision specifier is -r #, where # is the revision you want to view, copy, update to, or otherwise use. Instead of the revision number, you can use a date, enclosed with { and }. There are also a number of aliases provided:
 * HEAD: latest version checked into the repository
 * BASE: latest version "svn up"d from the repository to the local copy
 * COMMITTED: latest version checked in from this local copy (at or before BASE)
 * PREV: revision just before COMMITTED

You can specify a range over which certain actions are to be made (such as diff and log), by using a colon between two ranges. For example svn log -r 15:HEAD will give you the log messages from 15 to HEAD (including 15). Note that if you want to use a range that includes the current checked out version, you usually don't use a range, and it will default to comparing the specified revision and the working directory.

Migrating from CVS
To take a CVS repository and make a Subversion repository from it, there is a program from  called cvs2svn that does the trick. $ cvs2svn -s NEW_SVNREPOS CVSREPOS

If you have a need to regularly sync to a cvs repository... take a look at Tracking_cvs_trunk_with_svn.

Including external subversion repositories
Often times projects will depend on other projects. subversion has a property called svn:externals. It enables automatic updates of external svn repositories whenever the main one is updated

Setup
Checkout the external repository into the directory of you chosing. Then edit a temporary file and add the external repository information like below:  protocol://hostname/path/to/repository

Once the repository is setup run the following command: svn propset svn:externals -F  