SVN: Subversion's Very Neat

Quick Start guide to SVN



  $Rev: 3515 $:  Revision of last commit
  $Date: 2017-06-30 15:50:44 +0200 (ven, 30 giu 2017) $:  Date of last commit

Giorgio F. Signorini, <giorgio.signorini@unifi.it>

Getting more help

The official SVN (1.8) guide is at http://svnbook.red-bean.com/en/1.8/

Definitions

"URL"
repository copy

"PATH"
working copy

How to access a repository

Repository URLs:
  $url=file:///u/pc01/svn/REPO/SVN-guide   # no need for a SVN server
  $url=svn://pc01/SVN-guide       # SVN server with non-encrypted passwords
  $url=svn+ssh://pc01/home/svn/REPO/SVN-guide

Note the special URL (>=1.6):
  $url=^/
which is the root dir of repository of the current working copy (very useful)
Listing the repo tree:
  svn list [-R] $path
  svn list [-R] $url
  svnlook tree $path-of-repos [$dir-in_repos]  # only on the server

Getting info about the repository a working copy comes from:
  svn info $path

Basic Work Cycle

Checking files out:
  svn checkout $dir_url [$dir_path]
  svn checkout --depth=files  $dir_url $dir_path   # don't checkout subdirectories

You can only checkout a DIRECTORY, not a single file
Seeing What You Have Changed:
  svn status [$path]    
will give an output like:

    ?       scratch.c           # file is not under version control
    A       stuff/loot/bloo.h   # file is scheduled for addition
    C       stuff/loot/lump.c   # file has textual conflicts from an update
    D       stuff/fish.c        # file is scheduled for deletion
    M       bar.c               # the content in bar.c has local modifications

  svn status -v [$path]    #  include unchanged files, print vers nos, etc.
  svn diff [$path]

Seeing What's Changed in the Repository:
  svn status -u [-v] [$path]      # out-of-date files are marked with a *
  svn diff -r HEAD [$path]
  svn log -r HEAD [-v] [$path]          # see comments about changes in $path
  svn log -r HEAD [-v] $url	  # see comments about changes in tree starting at $url

Note that svn log, like svn diff, by default shows changes with respect to BASE (the version your working copy is based upon), as opposed to HEAD (the most recent version in the repo).

Refreshing Local Copies:
  svn update [$path]
U working file unchanged but outdated, now Updated
G working file changed and outdated, changes merGed (was M in CVS)
C (with --non-interactive in SVN>=1.5) like G, but a Conflict was found (see concurrent editing below)
Committing Changes
  svn commit [$path]

Concurrent editing

If someone commits a new version while you are editing, your working file will be based on an outdated version.

If you try to commit your changes to the now out-of-date version, you won't be allowed to:

  $ svn commit -m "Add another rule"
  Sending        rules.txt
  svn: Commit failed (details follow):
  svn: File '/sandwich.txt' is out of date
  ...

First, you must update. Changes in the repository copy since you checked out will be merged into your working copy. If there is a conflict, you are given a choice (in subversion >= 1.5):

  Conflict discovered in 'Makefile'.
  Select: (p) postpone, (df) diff-full, (e) edit,
          (mc) mine-conflict, (tc) theirs-conflict,
          (s) show all options: 

Most probably, you will edit, resolve the conflict, and finally save; then the next choice includes (r):

  Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
          (mc) mine-conflict, (tc) theirs-conflict,
          (s) show all options: r
  G    Makefile
  Updated to revision 40.

In the example above, you tell SVN that the conflict is resolved. Now you have a merGed working copy that is up-to-date with the latest revision. When you are ready, you can commit.

If you postpone, SVN will leave the working copy as it is (possibily adding a tentative merged copy), and put on the same directory a copy of its base revision and of the latest revision on the repository. You cannot commit until you resolve. Decide which one to keep, then resolve with

  svn resolve --accept=<option>

Common tasks

Reverting to the copy in the repo, discarding local changes:
  svn revert $file_path

Retrieving a different revision:
  svn update -r $rev $file_path
  svn update -r PREV $file_path    # not useful! use merge instead

N.B. If you retrieve an old version, and edit it, you won't be able to commit changes; you must update it first -that is, go up to the latest revision again! Use svn merge to retrieve an old version and work on.

Backing out a bad commit:
  svn merge -r HEAD:PREV $path     # retrieve next-to-last version
  svn merge -c -N        $path     # undo changes N-1:N (it's not necessary that N=HEAD)
You can work on, then commit
Synopsis of svn merge

  svn merge -- Apply the differences between two sources to a working copy path.
  
  svn merge sourceURL1[@N] sourceURL2[@M] [WCPATH]
  svn merge sourceWCPATH1@N sourceWCPATH2@M [WCPATH]
  svn merge [[-c M]... | [-r N:M]...] [SOURCE[@REV] [WCPATH]]

-c M = -r (M-1):M

-c -M = -r M:(M-1)

default revisions: -r 1:HEAD

The main use of svn merge is with branches (see below)
If you edited a file outside SVN:

Suppose you took $file_path home, edited it on your PC, then you go back to office to discover that people have committed many revisions since you checked out your home copy. You must make SVN apply, to the file edited at home, the changes going from the BASE (of the file you took home) up to HEAD

  cp -p $file-edited-at-home $file_path     # now working copy is at BASE+your home changes
  svn update $file_path                     # merge changes from BASE to HEAD into working copy
  svn commit                                # 

Adding files or directories to the repo:
  svn add $path
  svn commit

Deleting a file or directory (working copy or repository copy):
  svn delete $url     # delete repository copy
  svn delete $path    # del working copy, schedule for deletion of repo copy ...
  svn commit $path    # ... now del repo copy too

Moving files or directory(es) == add and delete:

  svn mv SRC ... TGT       # if multiple SRC, TGT must be a directory
SRC ... TGT may be either both $urls or both $paths, but not mixed.
Moving a directory to a different point of the repository:

  cd did
  svn update
  svn mv svn+ssh://pc01/home/svn/REPO/did svn+ssh://pc01/home/svn/REPO/myuser/ -m "moved did to myuser/did"

Note the now the repository (meta)data in the working directory did aren't correct anymore (they still contain old file paths, etc.). Remove or rename the directory, and check it out again:

  mv did did.old
  svn co svn+ssh://pc01/home/svn/REPO/myuser/did
Seeing what files have changed since a certain revision:

  svn update -r $old-rev   # go back to revision $old-rev
  svn update               # will show all items committed since $old-rev, and update them

Tags and Branching

Creating a branch/tag:
  [svn status -u]
  [svn update]
  [svn commit]
  svn copy $trunk_url $branch_url

Getting a working copy of the branch
  svn checkout $branch_url

Syncing the branch to the trunk:
  cd $branch_path          
  svn merge $trunk_url     # merges changes of the trunk (since last merge), into the branch
  # [... possibly resolve conflicts]
  # now your working copies are changed  
  # ... test 
  # ... commit

Comparing a branch or a tag to the trunk status:
  svn diff svn+ssh://pc01/home/svn/REPO/PROJ/tags/rel_5.1.r85 svn+ssh://pc01/home/svn/REPO/PROJ/trunk
  svn diff --summarize svn+ssh://pc01/home/svn/REPO/PROJ/trunk svn+ssh://pc01/home/svn/REPO/PROJ/branches/rel_5.1 

(syntax is diff OLD NEW)
Merging branch back to the trunk:
  # first, sync the branch to the trunk (see above)
  #   if branch is too far from trunk, SVN won't let you reintegrate it into trunk:
  #   "Reintegrate can only be used if revisions ... through ... were previously merged from [trunk] ..."
  # and AFTER that do:
  cd $trunk_path
  svn update
  svn merge --reintegrate $branch_url
  # ... resolve conflicts, diff, test
  svn commit -m "Finally merged branch back into trunk"

Merge a bugfix from the trunk onto the release branch:
  cd $working_dir
  svn checkout $release_url
  # bug has been fixed in trunk from r2191 to r2192
  svn merge -c 2192 ^/PROJ/trunk/src/sge.f90 .
  svn commit -m "Bug fix ... merged from trunk"

Deleting the branch:
  svn delete $branch_url   # branch history is not destroyed

Showing a log of the branch, starting at the branching point:
  svn log $branch_path --stop-on-copy

Repository Administration

Initializing a repository:
   mkdir svn-repos
   svnadmin create /u/pc01/svn/REPO/

Importing a project:
   cd source-dir
   svn import -m "initial import of SVN quick guide" . file:///home/svn/REPO/SVN-guide/trunk 
Initializing the SVN server:
  1. create a group for SVN users:

      [root]# groupadd subversion
      [root]# usermod -G subversion myuser
      [root]# chgrp -R subversion /u/pc01/svn/REPO
      [root]# chmod -R 770 /u/pc01/svn/REPO
    

  2. then edit svnserve.conf in the conf subdirectory of the repository, uncommenting the following lines:

      anon-access = read
      auth-access = write
    
Starting the SVN server:
copying repository data:
  svnadmin dump svn-repos/ > tmp/svndump
  svnadmin load misc/pc01/SVN-repos/ < tmp/svndump

Emacs interface