Mercurial (hg) and SVN reference

hg and svn are the two revision control systems I use. Here is a summary of their use and differences.

Creating repository

hg:

Doesn't have a global repository. Every copy is its own local repository. If desired, one copy can be designated as a global repository. Each project is its own repository.

svn:
svnadmin create [--fs-type fsfs|bdb] url://to/repo

In svn, a repository is usually on a server somewhere, and contains multiple projects.

Creating a new project

hg:
hg init proj

This creates proj directory if it doesn't exist, and makes it into a local repository. No files are added. hg does not impose any directory structure.

svn:

Create new directory (e.g., in your home directory) to hold files, then import it. svn suggests (but doesn't require) the following directory structure for projects:

mkdir proj
mkdir proj/trunk/
mkdir proj/branches/
mkdir proj/tags/

svn import /path/to/proj url://to/repo/proj

This imports proj to repository and adds any existing files in proj.

Checking out a project

hg:
hg clone url://to/repo

hg clones an existing project repository. This can be any copy of the repository, as no global repository is imposed. Clone automatically sets the default push/pull path to the original repository, which is useful if the original repository is designated the “global repository”.

To set the default push/pull path, edit the file .hg/hrc and set the path as:

    [paths]
    default = url://to/repo

URLs can be local files:

    hg clone relative/path/to/project

or ssh:

    hg clone ssh://hostname/relative/path/to/project

(also presumably http, but I've never used that.)

svn:
svn co url://to/repo/proj/trunk

You can checkout any directory, but typically people checkout the trunk or some branch (see below). (I guess.)

URLs can be https:

    svn co https://hostname/path/to/project

local files:

    svn co file:///absolute/path/to/project

or ssh:

    svn+ssh://hostname/absolute/path/to/project

File management

Add files
hg add files
svn add [--parents] files.

Use --parents to automatically add parent directories.

Add all new files in directory, recursively
hg add [dir]
svn add --force dir
Add directory
hg does not put directories under revision control; add a file in that directory to add the directory.
svn mkdir dir
Delete files
hg rm files
svn rm files
Copy files
hg cp file1 file2
svn cp file1 file2
Move files
hg mv file1 file2
svn mv file1 file2
Revert file to previous version
hg revert {files|--all}
svn revert files
Show status, compared to last update (i.e., local only)
hg st [--all] [files]
svn st [-v] [files]
Show status, compared to remote repository
n/a
svn st -u [files]
Show diff, by default compared to last update
hg diff [-r rev] [files]
svn diff [-r rev] [files]
Show diff, compared to another repository
hg {incoming | outgoing} [-p] url://to/repo
n/a
Update to changes from repository
hg pull [url://to/repo] && hg up, or
hg pull -u [url://to/repo]
svn up
Resolve conflict after an update
n/a
svn resolve --accept {mine-full | theirs-full | working} files
Commit changes to repository
hg commit -m 'message' && hg push [url://to/repo]
svn commit -m 'message'

Ignoring files

hg:

Store glob or regexp patterns, one per line, in file proj/.hgignore for the whole project.

Global ignore patterns can be put in ~/.hgignore-global

svn:

Store glob patterns, one per line, in property lists for each directory.

svn propset  svn:ignore "file1dir
svn propedit svn:ignore dir

Global ignore patterns can be set with the global-ignores option in ~/.subversion/config.

Branching and Merging

hg:

Clone the project and merge changes as usual. I.e., there is nothing special about branching. In effect, every local repository is a branch.

svn:

Make a light-weight copy on the server, check it out. Changes from the trunk can be merged into the branch. At the end, the branch can be reintegrated with the trunk.

svn copy url://to/repo/proj/trunk url://to/repo/proj/branches/my-branch

svn co url://to/repo/proj/branches/my-branch

# in copy of branch
# merge changes from trunk into branch (can do many times)
svn merge ^/proj/trunk

# in copy of trunk
# reintegrate branch into trunk (can do only once)
svn merge --reintegrate ^/proj/branches/my-branch

# test and verify, then commit
svn commit -m msg
See note on relative URLs.

Properties

hg:

Doesn't have the concept of properties (that I know of).

svn:

Uses properties as metadata associated with files or directories.

	svn propset  <propname> 'text' files
	svn propset  <propname> --file file files
	svn proplist files
	svn propget  files
	svn propedit <propname>  # starts $EDITOR
	svn propdel  <propname>

propnames starting with svn: are reserved.

Text substitution

hg

Doesn't generally support keywords. Their website explains why not and possible alternatives.

svn:

Set svn:keywords property to which keywords to substitute, e.g., "Date Author".

svn propset svn:keywords "Date Author" files

svn supports these keywords in text:

$Date$
$Revision$
$Author$
$HeadURL$
$Id$      # combination of above, condensed
$Header$  # combination of above, with full url