2009-03-25 08:20:14
Introduction to Mercurial
Mercurial is a popular open source, distributed revision-control system written in Python with a little C. Mercurial is fast, robust, friendly and easy to use. Many extensions add functionality. Mercurial itself is a command-line utility but add-ons supply GUIs and integration with other packages.
Binary packages are available for many operating systems.
On Windows, the TortoiseHg installer includes many useful GUI utilities and integrates with Windows Explorer.
I recommend disabling the TortoiseHg shell extensions (they seem a bit flaky) and installing hg view according to the instructions here.
In your home directory, create a file called Mercurial.ini. (Note: the docs refer to both Mercurial.ini and .hgrc. You can use either name.) Add your username to it with two lines similar to these:
[ui]
username = Kent Johnson <kjohnson@mydomain.com>
The default visual diff program is kdiff3. If you would rather use a different program, add two lines to your Mercurial.ini such as these (configuring Beyond Compare):
[extdiff]
cmd.vdiff = C:\Program Files\Beyond Compare 2\BC2.exe
Now the command hg vdiff will launch Beyond Compare.
The default visual merge program is kdiff3. If you would rather use gpyfm (trust me, you would), add these three lines to your Mercurial.ini (assuming the TortoiseHg install):
[merge-tools]
gpyfm.checkconflicts = True
gpyfm.checkchanged = True
Now merging will launch gpyfm.
Mercurial is extensively documented. Many useful resources are linked from the Mercurial home page. Some starting points:
Distributed revision control with Mercurial is a comprehensive on-line book.
You can also type hg help, hg help <command> or hg help <extension> to get help from the command line.
If you have used a centralized version control system such as CVS, SVN or a commercial VCS, using a distributed VCS takes a bit of an adjustment in your thinking. The most important thing to understand is that you will always be working with a local repository. When you check in or check out a file, revert, diff, view history, etc., it all happens against the local repository.
For private projects, the local repository may be the only one for the project; with Mercurial, it is very easy to put a local directory under version control.
If you are also working with a central repository, your local repository is a full peer of the central repository. In Mercurial, a "master" repository is just a working designation, not a technical one. When working with an upstream repository, you will generally be working with three copies of the source code - the upstream repository, your local repository, and your working copy. To get a change from your working copy to the upstream repository requires two steps. First, check in to the local repository; second, push the local repository to the upstream repository.
You can create a local repository from scratch, or as a clone of an existing repository.
To clone an existing repository, use
hg clone <repository_url>``
This creates a subdirectory of the current directory containing both a clone of the upstream repository and a working copy. For example, I created a repository at bitbucket.org containing sample programs I have written for python-tutor. To clone this repository, use the command
hg clone https://kent37@bitbucket.org/kent37/python-tutor-samples/
This creates a directory named python-tutor-samples containing a Mercurial repository (in the .hg directory) and a working copy of the files from the repository. It also configures the default repository for hg pull and hg push commands (see below).
You can clone a local repository, making a new local copy. This is a common way to branch a repository. Files in the clone working copy symlink to the upstream repository so the clone is fast and cheap.
hg init
creates a new, empty repository in the current directory. No files have been committed yet.
hg status
shows the files in the working copy, with a ? indicating that they are not in the repository.
You probably have files in the working copy that you don't want to include the repository. Typically these are build products such as object files and executables. Create a file named .hgignore at the top level of the working copy (not in the .hg directory) and edit it to exclude these files. Lines in .hgignore are either glob patterns or regular expression patterns matching files to exclude. For example:
syntax: glob
*.orig
*.rej
*~
*.o
tests/*.err
syntax: regexp
.*\#.*\#$
When hg status shows just the files that you want in the repository, type
hg add
to add them to the repository and
hg commit -m "Commit message"
to actually commit the files.
The commands you will use the most are
- hg status - show the status of the working copy (hg st)
- hg add - add new files to the local repository
- hg commit - commit changes to the local repository (hg ci)
If you have configured vdiff, qct and hgk, these commands open useful GUI views:
- hg vdiff - visual diff of uncommitted changes
- hg qct - opens the qct commit tool
- hg view - opens the hgk repository viewer
Commands can be abbreviated to the shortest unique name, such as hg st. Many commands have aliases, such as hg ci. hg help <command> lists the aliases for a command.
Often you will be working with an upstream repository, either to collaborate with others or to publish your repository.
These examples assume you have a default path set for the upstream repository (default parameter in the [paths] section of Mercurial.ini). If you created your local repository by cloning the upstream repository, the default path is set automatically. Otherwise, supply the repository url with each command.
hg incoming shows changesets in the upstream repository that are not in your local repository.
hg pull -u pulls changes from the upstream repository to your local repository and updates your working copy. You probably want your changes to be checked in locally before you do this.
hg outgoing shows changesets in your local repository that are not in the upstream repository. Note this shows committed changesets, not working copy changes.
hg push updates the upstream repository with local changesets. Your local repository must be up-to-date with the remote for this to work.
If you make changes in a local repository, and other changes are pushed to an upstream repository, when you pull from the upstream your local repository will branch. Resolving the branch requires two steps. First, hg merge to merge the two heads in your working copy. Verify that the merge is correct, then check in the merge changeset. See this explanation complete with pictures.
Mercurial may be customized with settings in Mercurial.ini or .hgrc. Settings may apply to a single repository, a single user or all users on a system, depending on where the settings file is located. For complete details see the .hgrc docs.
You can define default arguments for any Mercurial command by adding a [defaults] section to Mercurial.ini. For example, to make the hg log command default to showing only five entries, add this section:
[defaults]
log -l 5
You can create aliases for paths to other repositories. In particular you can define a default repository for pull and push. Note that if you created a repository by cloning another, the defaults are already set up for you. The default configuration looks like this:
[paths]
default = <repository url>
As initially installed, Mercurial exposes a no-frills set of basic commands. Many included extensions are disabled by default, and many add-on extensions are available. When you feel comfortable with basic Mercurial operations, or miss some feature, it is worth taking some time to explore the available extensions.
Extensions are enabled by adding an entry to the [extensions] section of Mercurial.ini. Many extensions also have configuration sections of their own.
You can create aliases for Mercurial commands that you use frequently. First, enable aliases by adding the line
hgext.alias =
in the [extensions] section of your Mercurial.ini. Then define your aliases in an [alias] section. For example, to make hg qon be an alias for hg qapplied, add these lines to Mercurial.ini:
[alias]
qon = qapplied
The record extension provides the hg record command. This command lets you choose which parts of the changes in a working directory you'd like to commit, at the granularity of patch hunks. It also adds a hg qrecord command if you are using Mercurial queues.
The Mercurial queues extension gives you more control over your local changesets by allowing you to push and pop changesets in your local repository. Mq adds complexity and power to your repository. For example, you can avoid merge changesets before a push by keeping all your changes in a queue. Before a pull, hg qpop all your changesets. This restores your local repository to the state at the last pull. Now hg pull -u to sync with the upstream repository, then hg qpush to restore your changes. You have applied the upstream revisions ''before'' your changes, so no merge is needed before a push. (Of course if there are conflicts you still have to merge the individual files.)
For more information see the Mq tutorial and documentation.
I find the below sequence of commands gives a useful summary of the current state of a repository. It shows incoming and outgoing changesets, the state of the patch queue, and local uncommitted changes. Put it in a batch file; I call it fullstat:
echo off
echo Incoming:
hg in
echo
echo Outgoing:
hg out
echo
echo Queue on:
hg qapplied
echo
echo Queue off:
hg qunapplied
echo
echo Status:
hg status
Another useful command converts all qpushed patches into permanent changesets. The command is
hg qdelete -r qbase:qtip
I create a Mercurial alias hg qdall for this command by adding these lines to Mercurial.ini:
[extensions]
alias =
[alias]
qdall = qdelete -r qbase:qtip
(Mercurial 1.1 includes a qfinish command which is similar.)
|
|
© Kent S Johnson
|
Comments about life, the universe and Python, from the imagination of Kent S Johnson.
kentsjohnson.com
Weblog home
All By Date
All By Category
Essays
BlogRoll
|