All notes



NOTE: you must keep the cases consistent, for "Trunk" is not same as "trunk". See FAQ.

Get your work copy from repo

svn ls $svnRoot
svn co $svnRoot/Trunk/proj

Work routine

# 1. First update.
svn update/up

# 2. Make changes.
svn add files/dirs
svn delete files/dirs
svn copy
svn mv SRC DEST
svn mkdir newDir

# 3. Examine your change.

# IMPORTANT: Always do this before trying to commit changes.
# --show-updates (-u)
svn status -u

svn diff > FILE.patch
svn diff -r revision1:revision2 FILENAME

# Cancel modifications.
svn revert files

# Cat the file on repo.
svn cat FILENAME

# 4. Merge changes.

svn merge %SVNROOT%/Trunk/proj
svn resolved PATH

# 5. Commit.
svn commit/ci -m "msg."

# blame (praise, annotate, ann): Show when each line of a file was last (or next) changed.
svn blame FILENAME

svn log
svn info

# Searches your working copy and runs any leftover logs, removing locks in the process.
svn cleanup

# Export a copy, e.g. for distribution.
svn export [-r REV] [PATH]
# Import into repo.
svn import

svn switch URL [PATH]


svn auth dir is under ~/.subversion/.

SVN administration

# --daemon, -d
# --root, -r
# Default port 3690
svnserve --daemon --listen-port=3091 --root=/usr/local/svn_rooty
svn checkout svn://



Run "svn up --help", you can get the status code:

A  Added
D  Deleted
U  Updated
C  Conflict
G  Merged
E  Existed
R  Replaced


"svn st --help":

First column: Says if item was added, deleted, or otherwise changed
  ' ' no modifications
  'A' Added
  'C' Conflicted
  'D' Deleted
  'I' Ignored
  'M' Modified
  'R' Replaced
  'X' an unversioned directory created by an externals definition
  '?' item is not under version control
  '!' item is missing (removed by non-svn command) or incomplete
  '~' versioned item obstructed by some item of a different kind
Second column: Modifications of a file's or directory's properties
  ' ' no modifications
  'C' Conflicted
  'M' Modified
Third column: Whether the working copy is locked for writing by
        another Subversion client modifying the working copy
  ' ' not locked for writing
  'L' locked for writing


-l [--limit] ARG  : maximum number of log entries   
-v [--verbose]  : also print all affected paths

# Show recent 5 logs, and also the changed paths:
svn log -l 5 -v


svn info

# Return only the URL for the repository:
svn info | grep 'Repository Root' | awk '{print $NF}'



# List
svn proplist

svn propset svn:mime-type image/jpeg foo.jpg
# On a Unix system, if you want a file to have the executable permission set:
svn propset svn:executable ON somescript
svn propset owner sally foo.c

# Get prop in current dir:
svn propget svn:ignore .
# Set prop in current dir:
svn propset svn:ignore -F ignoreFile .

# Edit prop in current dir, in a new text editor:
svn propedit svn:ignore .

# 如果你在特定修订版本的日志信息里有一些错误,并且希望修改,可以使用--revprop设置svn:log为新的日志信息:
svn propset --revprop -r 25 svn:log "Journaled about trip to New York."
# Or, if you don't have a working copy, you can provide a URL:
svn propset --revprop -r 26 svn:log "Document nap."

# 从一个文件得到输入,你甚至可以使用这个方式来设置一个属性为二进制内容:
svn propset owner-pic -F sally.jpg moo.c


SO: how do I ignore a directory with svn.

Ignore list for c#:

*.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store thumbs.db Thumbs.db *.bak *.class *.exe *.dll *.mine *.obj *.ncb *.lib *.log *.idb *.pdb *.ilk *.msi* .res *.pch *.suo *.exp *.*~ *.~* ~*.* cvs CVS .CVS .cvs release Release debug Debug ignore Ignore bin Bin obj Obj *.csproj.user *.user *.generated.cs

This won't work if the directory is already "in" svn.

svn rm --keep-local dirname

wcfNote: I found that the ignore-prop set in command-line is not respected by tortoiseSVN. I have to use tortoiseSVN GUI to edit the properties. There are "svn:global-ignores" and "svn:ignore". I modified the former one, and applied recursively. Also note that when you add new directories, you have to propagate the ignore list again.


The reason why a user can checkout but not commit

The case: user1 could update/ci, user2 could update but not ci, and they have similar LDAP settings. I found that there two repos: myrepo and myRepo, and yes they differ only in char-cases. Simply renaming myrepo to myrepo.old solving this problem. Here comes the reference and quotes:

I do not know if this answer helps you, but in my case it had something to do with server domain names and case sensitivity.
The URL we used for this working copy was
instead of the correct URL

Misteriously the wrong URL worked for "check out" and "update" and browsing the respository but not for "copy" or "commit".

Checking out a new working copy using the exact URL made the problems disappear.

(Using subversion 1.6.12 with Visual SVN Server installed on a Microsoft Windows Server)
Reference (See the mostly-upvoted one, not the chosen one).

# Make dir for svn using username and password.
svn mkdir -m "init." --username myname https://server/pathToRepo/proj
# Another better way, so you could put the long URL into bash alias.
svn mkdir -m "init." https://username:password@server/pathToRepo/proj
# The best way to add your repo under SVN control is: 1. mkdir on remote repo. 2. co the repo to local. 3. copy the files under the local repo.
# Import. The $svnRoot/proj1 will be created automatically. In svn help import it says "If PATH is a directory, the contents of the directory are added directly under URL."
# proj1/* will be added to $svnRoot/, which is not what we intend to get.
svn import -m "Import." proj1 $svnRoot/
# proj1/* will be added to $svnRoot/proj1/.
svn import -m "Import." proj1 $svnRoot/proj1
# Ignore all jpeg files.
svn propset svn:ignore "*.jpg" .
# Edit in an editor to ignore multiple files or folders.
svn propedit svn:ignore .
# Find files not under version control.
svn status | awk '/^?/{print $2}'

# Find the default ignore list.
cat ~/.subversion/config
# The default is
# "global-ignores = *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo"
# If you don't have your global ignores set,
# it will default to *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo *.rej *~ #*# .#* .*.swp .DS_Store.
# If you want to override this default, you will need to set global-ignore yourself.
# So svn ignores .a files.
# The command below will print all ignored files with 'I' flag.
svn status --no-ignore
# To add the files bypassing ignore tag:
svn add *.a --no-ignore


Reverts any local changes to a file or directory and resolves any conflicted states. svn revert will not only revert the contents of an item in your working copy, but also any property changes. Finally, you can use it to undo any scheduling operations that you may have done (e.g., files scheduled for addition or deletion can be "unscheduled").

svn revert foo.c
# Reverted foo.c

# If you want to revert a whole directory of files
svn revert --depth=infinity .
# Reverted newdir/afile
# Reverted foo.c
# Reverted bar.txt

svn add mistake.txt whoops
# A         mistake.txt
# A         whoops
# A         whoops/oopsie.c
svn revert mistake.txt whoops
# Reverted mistake.txt
# Reverted whoops

svn revert
# Nothing happens.
# 如果你没有给svn revert提供了目标,它不会做任何事情——为了保护你不小心失去对工作拷贝的修改,svn revert需要你提供至少一个目标。

Comparison to svn update


Branching and Merging

red-bean: svn branch and merge.

The directory structure is recommended to be:


Subversion has no internal concept of a branch - it knows only how to make copies.

Make branch

Always do a remote copy. While it's also possible to create a branch by using svn copy to duplicate a directory within the working copy, this technique isn't recommended. It can be quite slow, in fact! Copying a directory on the client side is a linear-time operation, in that it actually has to duplicate every file and subdirectory within that working copy directory on the local disk. Copying a directory on the server, however, is a constant-time operation, and it's the way most people create branches.

SVN employs the hard link concept to make the "cheap copy" happen on repo.

# Do a remote copy
svn copy \ \
         -m "Creating a private branch of /calc/trunk."

Delete/Resurrect branch

After merging back into Trunk, there's no need for your private branch directory to stick around anymore:

svn delete \
           -m "Removing obsolete branch of calc project."

It's not really gone: the directory is simply missing from the HEAD revision, no longer distracting anyone. If you use svn checkout, svn switch, or svn list to examine an earlier revision, you can still see your old branch.

Resurrecting data is very easy in Subversion. If there's a deleted directory (or file) that you'd like to bring back into HEAD, simply use svn copy to copy it from the old revision:

svn copy \
           -m "Restore my-calc-branch."


In Subversion 1.6, a new caret (^) notation was introduced as a shorthand for “the URL of the repository's root directory”.

svn merge "^/calc/trunk"

SVN branching strategy

Different with "Branches" and "Tags", "Trunk" is usually in singular format.

Release branches

red-bean: branch merge.

Most software has a typical life cycle: code, test, release, repeat. There are two problems with this process:

Here's where version control can help. The typical procedure looks like this:

  1. Developers commit all new work to the trunk. Day-to-day changes are committed to /trunk: new features, bug fixes, and so on.
  2. The trunk is copied to a “release” branch. When the team thinks the software is ready for release (say, a 1.0 release), /trunk might be copied to /branches/1.0.
  3. Teams continue to work in parallel. One team begins rigorous testing of the release branch, while another team continues new work (say, for version 2.0) on /trunk. If bugs are discovered in either location, fixes are ported back and forth as necessary. At some point, however, even that process stops. The branch is “frozen” for final testing right before a release.
  4. The branch is tagged and released. When testing is complete, /branches/1.0 is copied to /tags/1.0.0 as a reference snapshot. The tag is packaged and released to customers.
  5. The branch is maintained over time. While work continues on /trunk for version 2.0, bug fixes continue to be ported from /trunk to /branches/1.0. When enough bug fixes have accumulated, management may decide to do a 1.0.1 release: /branches/1.0 is copied to /tags/1.0.1, and the tag is packaged and released.

This entire process repeats as the software matures: when the 2.0 work is complete, a new 2.0 release branch is created, tested, tagged, and eventually released. After some years, the repository ends up with a number of release branches in “maintenance” mode, and a number of tags representing final shipped versions.

Feature Branches

A feature branch is the sort of branch that's been the dominant example in this chapter (the one you've been working on while Sally continues to work on /trunk). It's a temporary branch created to work on a complex change without interfering with the stability of /trunk. Unlike release branches (which may need to be supported forever), feature branches are born, used for a while, merged back to the trunk, and then ultimately deleted. They have a finite span of usefulness. Again, project policies vary widely concerning exactly when it's appropriate to create a feature branch. Some projects never use feature branches at all: commits to /trunk are a free-for-all. The advantage to this system is that it's simple—nobody needs to learn about branching or merging. The disadvantage is that the trunk code is often unstable or unusable. Other projects use branches to an extreme: no change is ever committed to the trunk directly. Even the most trivial changes are created on a short-lived branch, carefully reviewed, and merged to the trunk. Then the branch is deleted. This system guarantees an exceptionally stable and usable trunk at all times, but at the cost of tremendous process overhead. Most projects take a middle-of-the-road approach. They commonly insist that /trunk compile and pass regression tests at all times. A feature branch is required only when a change requires a large number of destabilizing commits. A good rule of thumb is to ask this question: if the developer worked for days in isolation and then committed the large change all at once (so that /trunk were never destabilized), would it be too large a change to review? If the answer to that question is “yes,” the change should be developed on a feature branch. As the developer commits incremental changes to the branch, they can be easily reviewed by peers. Finally, there's the issue of how to best keep a feature branch in “sync” with the trunk as work progresses. As we mentioned earlier, there's a great risk to working on a branch for weeks or months; trunk changes may continue to pour in, to the point where the two lines of development differ so greatly that it may become a nightmare trying to merge the branch back to the trunk. This situation is best avoided by regularly merging trunk changes to the branch. Make up a policy: once a week, merge the last week's worth of trunk changes to the branch. When you are eventually ready to merge the “synchronized” feature branch back to the trunk, begin by doing a final merge of the latest trunk changes to the branch. When that's done, the latest versions of branch and trunk are absolutely identical except for your branch changes. You then merge back with the --reintegrate option: $ cd trunk-working-copy $ svn update Updating '.': At revision 1910. $ svn merge --reintegrate ^/calc/branches/mybranch --- Merging differences between repository URLs into '.': U real.c U integer.c A newdirectory A newdirectory/newfile U .


The code in trunk is always maintained as close to release state as possible. Changes made to the trunk must be coded, tested and are ready to deploy within 2 days.

If it takes more than 2 days, they are not allowed to directly change the code in the trunk. They have to create a branch.

If you don't want people to add new features to the project, but you don't want to tell all developers to stop programming either. So instead, you create a “stable” branch of the software that won't change much:

$ svn copy \
           -m "Creating stable branch of calc project."

Now developers are free to continue adding cutting-edge (or experimental) features to /calc/trunk, and you can declare a project policy that only bug fixes are to be committed to /calc/branches/stable-1.0.


Developer Branch:

Each developer must create his or her own branch if their code will take more time to program than your normal deployment cycle. It is the responsibility of the developer to regularly (timeframe depends on your development environment) merge changes from trunk to his branch.

Feature branch:

Create a feature branch if 2 or more developers are going to work on a new feature that will take considerable time to complete. It is the responsibility of the team lead to merge changes from trunk to this feature branch on a regular basis.


Tag is similar to branch.

Simply rename the folder from branch/branches to tag.

Always use Tags to tag a release whenever a new release version is deployed. This will come in handy if a very minor patch has to be made on the release version when your trunk is temporarily dirty.

Ideally, you do not merge from trunk to the tag.


Access forbidden

SVN error "access to '/svn/myservice/!svn/act/d99e498e-9a8d-374c-a3e4-fde21198bfa2' forbidden".


This happens when you check out a repository and the casing in the repository path that you typed does not match the actual repository path. When the casing does not match you're able to check out the repo but you get that error when you commit.

However, it can also occur when the name of your SVN account is entered with the wrong capitalization when making the commit (e.g., "Username: Joe" instead of "Username: joe").

Change repo URL


To relocate:

svn relocate http://IP/pathURL

Download GCC with svn


# You could first see what tags are available:
svn ls svn://
# Then download your version
svn co svn://

Where does TortoiseSVN store Auth



%AppData%/Subversion (XP and before)
%AppData%/Roaming/Subversion (Vista)