paulgorman.org

Mercurial code management notes

hg is the chemical symbol of the element mercury.

Basic workflow

Starting a new repository:

cd myproj hg init hg add hg status hg commit -m 'Initial import.'

Reviewing changes after editing some files:

hg status hg diff hg commit -m 'Refactored widgets.' hg tip -vp

Clone to a remote repository (note that Mercurial assumes path relative to home directory, so ~ in unnecessary; use // if you need an absolute path):

hg clone ./ ssh://example.com/projects/myproj

Update local repository from remote repository (and update working copy):

hg pull ssh://example.com/projects/myproj/ hg update

Push local changes to a remote repository:

hg status hg commit -m 'Code cleanup.' hg push ssh://example.com/projects/myproj/

See a history of changes with hg log -r : or hg log -v. Examine history of a particular changeset with hg log -v -r 3 (where "3" is the start of a changeset id like "3:0272e0d5a517").

Change the working copy to a different revision like hg update 3, and change back to the latest revision with hg update tip.

To stop tracking a file under version control: hg remove myfile.

Also: hg copy file1 file2 and hg rename old new.

See finding and fixing mistakes for how to rollback the last commit (hg rollback), revert pre-commit changes (hg revert file), and more.

Ignoring certain files

If it doesn't already exist, create an .hgignore file in the root of the repository. if you run hg status and see:

M myrepo/foo/doc.tex
? myrepo/foo/doc.aux
? myrepo/foo/doc.log

Add the line myrepo/foo/doc.log to .hgignore, and Mercurial will ignore that file. It should no longer show when you run hg status. You can also add patterns to the ignore file, such as .*.swp to ignore vim's swap files.

Initial setup

After installing Mercurial, create an ~/.hgrc:

[ui] username = John Smith <jsmith@example.com> editor = gvim merge = meld [merge-tools] meld.args = $local $other $base meld.priority = 1 [extensions] hgext.extdiff = hgext.hgk = [extdiff] cmd.meld = cmd.vimdiff = gvim

Stick this in myproject/.hg/hgrc:

[paths] default = ssh://example.com/repo/myproject

Concepts and terminology

Unlike SVN or CVS, Mercurial is a distributed system. Instead of having one central repository from which developers checkout individuals files, in a distributed system each developer clones the entire repository. This is practical because distributed systems are better at merging than SVN or CVS, and faster generally.

A Mercurial repository has a store (stored in the .hg directory) and a working copy. It is possible (and often useful) to checkout older version from the repository into the working copy.

Each commit generates a changeset, which records the state of the working directory. Each changeset has its own changeset ID.

A head is a changeset with not child changesets. A tip is the most recently changed head in a repository.

A branch is a repository, a repository is a branch. Each time you clone a repository, you create a new branch. (Technically, a branch is the set of all changesets with the same branch name. The default branch name is 'default', so a repository will be all once branch unless you create a named branch.)

A tag is a symbolic identifier for a changeset. A local tag (hg tag -l my_tag) is a convenience identifier that is not revision controlled, and doesn't propagate with other changes. A tag with no special specifier (hg tag my_tag) is revision controlled, and does propagate with other changes.