8/25/2010

My subversion svn notes

Non-comment lines of $HOME/.subversion/config (%APPDATA%\Subversion\config on Windows):

global-ignores = *.ipr *.iml *.iws .project .classpath .settings .*.swp out.txt todo.txt *.save *.my *.class *.org #*# .*.rej *.rej .*~ *~ .#* .DS_Store
enable-auto-props = yes
*.java = svn:eol-style=native;svn:keywords=Date Author Id Revision HeadURL
To view the usage of a subcommand, for example, propedit:
svn help propedit
To view the details of a commit with rev number, including changed files and log messages (Without -v option, changed files are omitted in the output):
svn log -v -c 1234 Foo.java

Date and time in log are in local timezone of the current client. For example,
r526 | user1 | 2012-02-25 09:32:00 -0500 (Sat, 25 Feb 2012) | 3 lines

-0500 indicates the timezone EST (US/Eastern Standard Time), 5 hours behind UTC

r536 | user2 | 2012-04-26 13:44:59 -0400 (Thu, 26 Apr 2012) | 2 lines
-0400 indicates the timezone EDT (US/Eastern Daylight Time), 4 hours behind UTC

In contrast, git log displays the date in the committer's timezone with offset to UTC.  git log --date=local displays it in the git client local time without showing any timezone value.

To get the date and time in UTC (the ending Z is for UTC):
svn propget --revprop -r 537 svn:date
2012-05-01T02:08:21.396811Z


# shows all changes made by rev 1234 compared to previous rev
svn diff -c 1234 Foo.java To get, or set end-of-line property (One of 'native', 'LF', 'CR', 'CRLF'):
svn pg      svn:eol-style Utils.java
svn pget    svn:eol-style Utils.java
svn propget svn:eol-style Utils.java

svn propset svn:eol-style LF Utils.java
svn pset    svn:eol-style LF Utils.java
svn ps      svn:eol-style LF Utils.java
To view the svn:externals or svn:ignore for the current directory:
svn propget svn:externals .
svn pg svn:externals .
svn pg svn:ignore .
To delete the svn:ignore for the current directory:
svn pd svn:ignore .
To edit the externals for the current directory:
svn --editor-cmd vim propedit svn:externals .
svn --editor-cmd vim pe svn:externals .
If any one of these environment variables SVN_EDITOR, VISUAL or EDITOR is set, you can omit the "--editor-cmd vim" part:
setenv EDITOR vim (in csh/tcsh)
export EDITOR=vim (in bash)
svn pe svn:externals .
To compare two different versions of a file:
svn diff -r r99:r100 build.xml
svn diff -r 99:100 build.xml
svn diff -c 100
It's easier to copy r99 r100 from svn log output, so I prefer the first form. The option "-c 100" is the same as "-r 99:100", and shows all changes made by rev 100.

To skip any differences in deleted files:
svn diff --no-diff-deleted
svn diff will not included newly added files, or files that are moved to target directory. To view colored diff with vim:
svn diff | view -
I also have a shell script wrapper (diffv) for the above:
#! /bin/sh
svn diff -x -wub $@ | view -
# use -x -wub to ignore whitespace changes
To get detailed info like URL, repository URL, revision, last changed date, etc:
svn info .
To relocate a loca workspace after the server repository has moved:
cd root-of-current-workspace
svn switch --relocate http://old http://new .
To revert all modified files under current directory:
svn revert *
svn revert util/*
Note that "svn revert ." does not revert changes in sub-directories. For recursive revert,
svn revert --depth infinity util
svn revert -R util
svn revert --recursive util
When newly-added files (with svn add or svn move) are reverted, they will stay in the file system, even though removed from version control. This can also happen when you apply someone else's patch to your local workspace and then revert them. As a consequence, when building the workspace these left-over files are still included in project artifacts, causing mysterious errors.

To downgrade svn client version:
cd {to the directory with local changes};
python $HOME/bin/change-svn-wc-format.py . 1.5
The above command will downgrade the working copy format to svn 1.5. This is to fix the annoying svn version error:
svn: This client is too old to work with working copy '...'.  You need
to get a newer Subversion client, or to downgrade this working copy.
See http://subversion.tigris.org/faq.html#working-copy-format-change
for details.
To apply a patch (.diff file), ignoring all parent directories in diff index:
cd {working directory containing the target file}
patch -i $HOME/Desktop/a.diff
svn patch $HOME/Desktop/a.diff .  # for subversion client 1.7 or later

To apply a patch (.diff file), preserving all parent directories in diff index:
cd {parent directory of the whole directory structure in diff index}
patch -p0 -i /tmp/a.diff
This is useful when target files do not fall under the same directory. -p means how many levels of directories to prune. patch is a Unix (not svn) command, usually resolves to /usr/bin/patch.

If you've copied the diff (e.g., from email received from coworker), you can let patch command take input from console:
patch
patch -p0
After pasting diff content, Ctrl-D to end.

If a patch contains moved files between different directories, /usr/bin/patch or svn patch doesn't know how to create the destination files. You will need to 'svn copy' these files to their destinations before running patch.


To make directories and parent directories together (the equivalent of OS command mkdir -p),
svn mkdir --parents com/a/b/c
To move a single file to another directory (--parents option will make any intermediate directories if not already exist):
svn mv --parents Utils.java ../common/a/b/c/Utils.java
# note that both SRC and DST must be file.  If DST is a ../common/a/b/c,
# c will actually be treated as a file to hold the content of Utils.java

To move MULTIPLE files to another directory (--parents option will make any intermediate directories if not already exist):
cd <source directory>
svn mv --parents *.java ../common/a/b/c

To move the whole directory to another location:
svn mv impl ../common
After this command, if you do a "svn st", you will see all the deleted directories and files are listed, but under the DST directory, only the top-level directory (../common/impl) is listed as Added. Even in the comment editor window of "svn ci", still only the top-level directory listed as Added. How about files under the top-level directory, have they been copied over? But have no fear, everything from the SRC along with revision history were indeed moved to the destination. "svn ci" will commit these changes to the repository.

With TortoiseSVN (Windows only), all these move operations can be done in Windows Explorer: right-click the SRC, hold and drag it to the DST, and confirm your operation in the pop-up menu.

To remove a directory (there is no svn rmdir command),
svn rm a/
To merge some changes from trunk to branch, branch to trunk, or branch 1 to branch 2:
cd <source directory of changes>
svn log . | head -25
copy and paste the start rev and end rev, e.g., r123:r129
svn info; and copy the source URL, e.g., http://host:port/my-project-svn/a/b
cd <dest directory>
svn merge --dry-run -r r123:r129 http://host:port/my-project-svn/a/b
To make real changes, omit --dry-run option.

To merge ALL changes in Foo.java from trunk to branch:
cd <source directory of changes>
svn info Foo.java; and copy the complete source URL, e.g., http://host:port/.../Foo.java
cd <dest directory>
svn merge http://host:port/.../Foo.java ./Foo.java

To merge rev 567 in Foo.java from trunk to branch:
cd <source directory of changes>
svn info Foo.java; and copy the complete source URL, e.g., http://host:port/.../Foo.java
cd <dest directory>
svn merge -c 567 http://host:port/.../Foo.java ./Foo.java

To quickly undo or revert a bad commit (rev 99) with a reverse merge (notice the negative rev number is used. It must be a number; args like -c -r99 is rejected.):
svn merge -c -99 .
svn ci -m 'revert my changes in rev 99.'

To create a changelist with a list of files:

svn cl user.changelist src/main/java/com/xxx/User.java src/main/java/com/xxx/Person.java


To create a changelist from a file created by svn st command, need to first cut off the leading characters like "M", "A", deleting all lines starting with "?", and then use --targets option (in plural):

svn cl user.changelist --targets /tmp/d


To diff only those files associated with user.changelist:

svn diff --cl user.changelist


To remove a changelist, you don't remove the changelist itself, instead remove the association of all files. You can either list the files in command line, or include these lines in a file. After that, the changelist will simply disappear:

svn cl --remove src/main/java/com/xxx/User.java src/main/java/com/xxx/Person.java
svn cl --remove --targets /tmp/d


To revert changes in a changelist, you need to specify both the changelist and path:

svn revert --cl user.changelist -R user/src/main

Changelist is helpful when working on multiple tasks in the same workspace. You cannot check in changes for task1 due to some other dependency, but would like to start working on task2. But be very careful when juggling with multiple tasks in the same workspace, as some java files will stay in the file systems even after they are reverted and be built into the artifacts.

If you have locally modified a file, and an incoming update will delete or move the same file, its status after the update will be Tree Conflict (delete upon update). What I will do is to first back it up, revert local changes, and then resolve this conflict

cp Method.java $tmp/Method.java
svn revert Method.java
svn resolved Method.java

If the file (Method.java) is moved to some other directory, apply your local changes to Method.java in its new directory. If you run "svn resolved" with local modifications, this file will show up as newly added file that contains your local changes, which is probably not what you want.

To view svn status, excluding untracked local-only files (filtering out lines like "?    config/server.xml.bak"):
svn st | grep -v "^?"
To view locally modified files only:
svn st | grep "^M"