vankuik.nl RecentChanges 2010-03-11 XML TXT

SVN

I've written about the differences between SVN and CVS and the usage of the plugins in Eclipse, see also 2006-02-01.

Importing your project

I found the svn import syntax a bit funny, but that might just be me. If you're importing from the commandline, do it like this:

  $ cd myproject
  $ svn import http://machinename/subversion/myproject

I'm assuming here that you use the http protocol to access the subversion protocol; most do it that way. However it's also possible to create a file-based repository. If the admin likes that better, then import as follows. (I'm assuming here the admin has given you the path /var/www/svn/repos but that might be different!)

  $ cd myproject
  $ svn import file:///var/www/svn/repos/myproject

Your source is NOT versioned yet. So, continue with something like:

  $ cd ..
  $ mv myproject myproject.backup
  $ svn checkout http://machinename/subversion/myproject
  or
  $ svn checkout file:///var/www/svn/repos/myproject

Check the result:

  $ cd myproject
  $ svnversion .

SVN should answer "I'm sorry Dave, I'm afraid I can't do that", or if it's in a better mood, "Revision 1".

Moving a directory from one repository to another

Private projects can grow bigger than expected. Such a project may be sitting in a private repository and to keep access rights simple, it's useful to move a growing project to its own repository. I assume a new repository has been created.

First export the directory from the old repository:

  $ svn export http://localhost/svn/my_private_repository/libs/lib_tool

What results is a directory called 'lib_tool', stripped of all evidence that it once resided in SVN.

Now import that same directory into the new repository called 'lib_tool'.

  $ cd lib_tool
  $ svn import http://localhost/svn/lib_tool

If the import was successful, delete the directory you just imported, and check out the fresh first version:

  $ cd ..
  $ rm -rf lib_tool
  $ svn checkout http://localhost/svn/lib_tool
  Checked out revision 1.

It's probably best to do an 'svn delete' in the old repository:

  $ svn delete -m "Moved to its own repository" \
       http://localhost/svn/my_private_repository/libs/lib_tool

Ignore files

SVN does ignore files its own way, through a property. To ignore certain files, do:

  $ svn propedit svn:ignore .
  (An editor pops up, type in the filenames you want to have ignored, separated by enter)
  $ svn commit -m "Added Eclipse project files to ignorelist" .

Put the revision/author/et cetera in a file

SVN also uses properties for keyword substitution. Enter any of $Date$, $Revision$, $Author$, $HeadURL$ or $Id$ in your file and then do:

  $ svn propset svn:keywords "Revision" filename
  $ svn commit -m "Added property for keywords" filename

To remove:

  $ svn propdel svn:keywords filename
  property 'svn:keywords' deleted from 'filename'.

From CVS to SVN

If you want to move from CVS to SVN, there are all sorts of fancy tools. What I did for small projects was the following:

  $ for i in `find . -type d -name CVS`; do svn delete $i; done
  $ svn commit -m "Deleted superfluous CVS directories"

Rolling back changes

Suppose you inadvertently made changes in some files some time back. You can examine revisions of files with

 $ svn log ccsds.h

You see that the previous revision was 205. So you diff it:

 $ svn diff -r 205 ccsds.h

You then decide that yes, you want to roll back the file to that revision to the current revision 270 and then commit it. You can specify the current revision as a number (270 in my case), or just type HEAD (yes, all capitals), which SVN will understand:

 $ svn merge -r HEAD:205 ccsds.h
 U  ccsds.h
 $ svn commit -m "Rolled back inadvertent changes"
 Transmitting file data ....
 Sending       ccsds.h
 Committed revision 271.

Done!

Current revision

If you are in a source tree and you want to know what revision is there, just type:

 $ svnversion .

To incorporate this into your source files, check out this FAQ.

Creating a tag

Sometimes, you do a release of a particular directory in your repository, and you want to re-create that release later. For instance, you have the repository my_department, in which you have the subdirectory trunk/embedded_software/superwidget.

You don't want to branch the whole trunk but rather, you want to mark that subdirectory so you can always refer to it later. This is called tagging. Technically, it's the same as branching in SVN, but we use it somewhat differently.

Move into your repository directory. A possible layout could be:

 $ cd my_department
 $ ls
 trunk/
 branch-version-1.0
 branch-version-1.1

Then create a tags subdirectory:

 $ mkdir tags

Then tag a subdirectory deep in your trunk:

 $ svn copy trunk/embedded_software/superwidget \ 
            tags/superwidget-release-client-CompanyInc
 A   tags/superwidget-release-client-CompanyInc
 $ svn ci -m "Added tag for specific release for client Company Inc."
 Adding tags/superwidget-release-client-CompanyInc
 Committed version 12355.
 $

You don't actually need to be in the repository directory for the copy action; it can work with URLs as well. For more info, check the SVN manual on svn copy.

Creating a new branch afterwards

Sometimes, you start working on a revision to find out later that your work is huge and others have been committing all the time. In hindsight, creating a new branch would've been a good idea. To correct this, first you'll want to create a patch of all your changes:

  $ cd your/current/project/directory
  $ svn diff > ~/hackwork.patch

Then find out what revision you are hacking:

  $ svnversion .
  590M

Now create a separate branch of the original version:

  $ svn copy http://subversion.company.com/svn/telis/tuce \
    http://subversion.company.com/svn/telis/tuce-branch-gron \
    -m "Creating separate branch for work outside integration efforts"
  Committed revision 606.

Go to another directory, in my case ~/workspace

  $ cd ~/workspace
  $ svn co http://subversion/svn/telis/tuce-branch-gron
  $ cd tuce-branch-gron

And now integrate your changes again, and commit them in the branch:

  $ patch -p 0 < ~/gron.patch
  patching file tdb/mysql-telis.sql
  patching file client/python/plotffo.py
  ... lines removed ...
  $ svn commit -m "Fixes made on colors in FFO plot, conversion housekeeping \
  macro different, conversion FFO plot corrected"

Merging a branch back into the trunk

Go to your branch directory and find out the last revision:

  $ svn log --verbose --stop-on-copy | tail -20
  ...
  ...
  r608 | bartvk | 2007-02-02 12:20:55 -0100 (Fri, 02 Feb 2007) | 1 line
  ..
  ..

It should also show the comment that you entered when you created a branch then committed.

Go to the trunk directory and make sure everything's committed. Then find out the current revision with

  $ svnversion .
  668

Then see what would happen with a dry-run merge:

  $ svn merge --dry-run -r 608:668 http://subversion/svn/mybranch/

You'll see a whole list of modifications, additions, deletions and probably lots of conflicts (beginning the line with a capital C).

Now merge the whole branch into the trunk:

  $ svn merge -r 608:668 http://subversion/svn/mybranch/

Check what files are conflicted:

  $ svn status | grep "^C"

For each file:

When all conflicts have been merged, you can compile and test your code. If everything's well, you can do a commit, remove the old branch and commit again:

  $ svn commit -m "Merged branch xxx into trunk with changes x, y and z"
  $ svn delete mybranch
  $ svn commit -m "Removed branch xxx"

Seeing which files changed between revisions

Sometimes you need to revisit a particular change. So you type 'svn log' to see which revision you made the change. You spot that you made the change in revision 45. To see what files changed from revision 44 to 45, do:

  $ svn diff -r44:45 --summarize
  M      themes/Outlet/style/style.css
  M      includes/meta.php
  M      modules/Outlet/language/lang-dutch.php
  M      modules/Outlet/index.php
  M      modules/Outlet/functions.php
  A      issues/keywords_issue.sql

Creating a new project

I'm assuming your SVN directory is /var/www/svn. This directory should have owner apache, group dev (or some other common development group), and rights set to rwxrwsr-x (octal 4775).

Anyone in the development group can then create a project with:

 $ svnadmin create /var/www/svn/newprojectname

Depending on the umask of the creating user, the directory will probably have to be made writeable for the group:

 $ chmod g+w /var/www/svn/newprojectname

After this, other developers can check out and update the new project:

 $ svn co file:///var/www/svn/newprojectname
 Checked out revision 0.