SVN Apache Subversion

Apache Subversion is a software versioning and revision control system distributed as open source under the Apache License. Software developers use Subversion to maintain current and historical versions of files such as source code, web pages, and documentation.

Common Commands

Checkout a remote repo

Checkout the my_repo SVN repo starting from its html directory, from the remote server at https://my.svn.server into the webroot directory on a local machine.

sudo svn co https://my.svn.server/my_repo/html/ /path/to/webroot

Info about the local repo

# All iformation
svn info

# URL info
svn info | grep URL

Status of the local repo

svn st
svn stat
svn st -q  # View locally modified items (does not list un-added items). 
svn st -v  # View full revision information on every item in the repo.

The first column from the output indicates that an item was added, deleted, or otherwise changed with the following codes:

Code Description
No modifications.
A Item is scheduled for addition.
D Item is scheduled for deletion.
M Item has been modified.
R Item has been replaced in your working copy. This means the file was scheduled for deletion, and then a new file with the same name was scheduled for addition in its place.
C The contents (as opposed to the properties) of the item conflict with updates received from the repository.
X Item is present because of an externals definition.
I Item is being ignored (e.g., with the svn:ignore property).
? Item is not under version control.
! Item is missing (e.g., you moved or deleted it without using svn). This also indicates that a directory is incomplete (a checkout or update was interrupted).
~ Item is versioned as one kind of object (file, directory, link), but has been replaced by a different kind of object.

Update a local repo

This will update the local repo with any new information from the remote repo.

svn up
svn update

Add local files and directories

Files and directories with the status of ? (not under version control) must be added to the repo before they are tracked.

Add a new file:

svn add file_name

Add all un-versioned files (except ignored) from a specified directory:

svn add --force path/to/dir

Delete local files and directories

NOTE: Do not remove files and directories unless you use the svn delete command.

svn delete file_name

Rename local files and directories

NOTE: Do not rename or move files or directories unless you use the svn mv command.

Commit local changes to the remote repo

Commit ALL changes to the repo:

svn commit -m "A descriptive message about what was accomplished."

Commit one or more specific files to the repo:

svn commit -m "A descriptive message about what was accomplished." my/first/file my/second/file

Ignore files and directories

  • Ignored directories and files are defined in the svn:ignore property for a directory.
  • This property gets committed to the repo.
  • The svn:ignore property is only defined on directories.
  • The definitions in the svn:ignore property only affect files and directories within it’s directory. SVN does not ignore recursively (although there are methods to write the svn:ignore property recursively to a directory structure).

Example

This example shows how to ignore all .json files in the root directory of a repo.

  • Navigate to the root directory of the repo.
  • Edit the svn:ignore property for the current directory by using the propedit command. The svn:ignore property will open in your defined text editor:
svn propedit svn:ignore .

NOTE: Always use propedit to edit properties in SVN. Never use propset (example: svn propset svn:ignore 'my_file.txt' .) because each use completely replaces the property definitions.

  • Each svn:ignore property definition is on it’s own line.
  • Each definition line is a “file pattern” or simply a file or directory name.
  • Any number of definitions can appear in the property.
  • The current ignore already contains:
*.DS_Store  
*.project  
*.sublime-project  
*.sublime-workspace 
  • This is the complete list after adding the new file pattern line to ignore .json files:
*.DS_Store  
*.project  
*.sublime-project  
*.sublime-workspace 
*.json
  • Save the svn:ignore property file after edits are complete to make the changes take affect.
  • Commit the ignored changes:
svn commit -m "Adding ignored files and directories to the app root."
  • To see all properties set for the current directory and everything under it, run:
svn proplist -v -R
  • Use SVN ‘status’ to see ignored items too:
# All files.
svn st --no-ignore

# Just ignored files.
svn status --no-ignore | grep "^I"

Repo History

Diff files

To see all changes currently not checked-in:

svn diff

To see all changes currently not checked-in to a specific file:

svn diff file_name

Compare two specific revisions:

svn diff -r 8979:11390

Compare the last committed state against the currently saved working files with convenience keywords:

svn diff -r PREV:HEAD

Using svn diff without a specified file path will show all files with changes in the revision. Limit a diff to compare a specific file by adding the file path to the end of the command:

svn diff -r 8979:HEAD /path/to/my/file.php

View the last commit number

svn info --show-item last-changed-revision

View all the commits to a repo

svn log

View the complete history of a repo

svn log -v

Repo Structure

The most common SVN repository structure is to have a trunk, branches and tags directory for each project:

/project/trunk/...
/project/branches/...
/project/tags/...

Every time a new branch or tag is created, a directory named after the commit, containing the changes, is added to the repo:

/project/trunk/...

/project/branches/b1
/project/branches/b2
/project/branches/...

/project/tags/t1
/project/tags/t2
/project/tags/...

The underlying implementation as tags, branches, and trunk directories is only conventional and not in any way enforced by the tools. However, violating these conventions leads to confusion as this breaks habits and expectations of others accessing the repository. Special care must be taken to avoid committing new changes into tags, which should be frozen.

Trunk

The trunk is the main-line of development in a SVN repository. It represents the current production code base which gets deployed to the production environment.

  • There is only one trunk and it must always be kept bug-free and deployable.

Branch

A branch is a copy of the trunk, or another branch which can be worked-on and then merged back to the trunk when it’s ready (after review and testing).

Tag

A tag is simply a snapshot (a copy) of the trunk, or a branch. It marks, or highlights notable revisions in the history of the repository, usually things like “this was released as 1.0”.

  • NEVER commit new changes into a tag.

NOTE: There is confusion with tags and branches because in SVN there really is no distinction between them, besides the name of the directory. In svn you are able to commit changes to a tag, and in fact it is difficult to prevent this. Using an SVN hook script, one can make SVN treat any path containing “/tag/” to be write-protected after creation; the net result is that tags, once created, are immutable (at least to “ordinary” users). As long as nobody ever commits to a directory, it remains a tag. If people start committing to it, it becomes a branch.

Fork

In open source projects, major branches that are not accepted into the trunk by the project stakeholders can become the bases for a fork, a totally separate project that share a common origin with other source code.

Add a Trunk to an Existing Repo

Make the trunk dir in the root of your SVN repo:

svn mkdir https://mydomain.com/svn/my_repo/trunk -m "making trunk dir"

Move everything from the repos root dir to the new trunk. You will need to move each root-level file and directory manually:

svn move https://mydomain.com/svn/my_repo/A_FOLDER https://mydomain.com/svn/my_repo/trunk/A_FOLDER -m "Moving the folder to the trunk."
svn move https://mydomain.com/svn/my_repo/A_FILE.TXT https://mydomain.com/svn/my_repo/trunk/A_FILE.TXT -m "Moving the file to the trunk."

After everything from the repo root has been moved, use svn switch top point the local repo at the trunk.
Go into the root folder of your local repo and run:

svn switch https://mydomain.com/svn/my_repo/trunk --ignore-ancestry

NOTE: Beginning with Subversion 1.7, the svn switch command will demand by default that the URL to which you are switching your working copy shares a common ancestry with the item that the local copy currently reflects. Override this behavior by specifying the --ignore-ancestry option.