Using Mercurial

  • Revision slug: Mercurial_FAQ
  • Revision title: Using Mercurial
  • Revision id: 11183
  • Created:
  • Creator: DBaron
  • Is current revision? No
  • Comment /* How do I check stuff in? */

Revision Content

How is Mercurial different from CVS?

  • "Very". You should read and understand Mercurial basics before undertaking work with Mercurial that you care about.
  • Mercurial checkins are atomic.
  • In Mercurial, tagging is fast and O(1).
  • Mercurial makes it easy for anyone to fork the central repository. (The command is hg clone.)
  • With Mercurial, a complete, fully armed and operational clone of the entire Mozilla repository is on your local hard drive. You can do work locally and check it in without affecting anybody else. To push changes upstream, use hg push.
  • Mercurial queues can help you juggle patches. It's like Quilt. The idea behind Quilt is this:

    The scripts allow to manage a series of patches by keeping track of the changes each patch makes. Patches can be applied, un-applied, refreshed, etc.

    The key philosophical concept is that your primary output is patches. Not ".c" files, not ".h" files. But patches. So patches are the first-class object here.

  • When CVS finds merge conflicts, it puts conflict markers in your file. When Mercurial finds merge conflicts, it launches a merge program. This is a pain in the neck.
  • In a lot of places where CVS is per-file or per-directory, Mercurial is per-repository. For example, a single Mercurial changeset may contain changes to many files throughout the tree.
  • We hope Mercurial will allow us to rethink the way we work. Teams and individuals should be able to branch and merge much more easily—without opening IT tickets. People outside the community who are powerhouse developers should be able to do surprising stuff with this. Companies maintaining forks of Mozilla should have an easier time too. It all sort of remains to be seen, though.

How do I install Mercurial?

If you use apt-get, emerge, port, or yum to install software, just do the usual. If not, the Mercurial binary packages are for you. Or see {{mediawiki.interwiki('wikimo', 'Mercurial_on_Windows', 'wikimo:Mercurial on Windows')}}.

After installing, choose a merge program. Seriously. Do it now. If you don't, Mercurial will choose one for you and spring it on you when you least expect it.

How does Mercurial handle line endings?

The Windows version of Mercurial does not automatically convert line endings between Windows and Unix styles. All our repositories use Unix line endings. We need a story for Windows, but right now I have no ideas.

(How about a pre-commit hook that rejects pushes containing CR with a suitably informative error message? We possibly want to make exceptions for certain types of files (at least binary files of course), but we can tweak the hook as necessary as these crop up. Mercurial 1.0 adds a standard hook for this in the win32text extension that we could use/adapt. --jwatt)

How can I...

How can I check out Mozilla?

The Mozilla 2 trunk is located at http://hg.mozilla.org/mozilla-central/ .

You need Python 2.4 or later just to check everything out. This is because we're using Python to do some checkout-related stuff that client.mk used to do—blame bsmedberg ;)

hg clone http://hg.mozilla.org/mozilla-central/ mozilla
cd mozilla
python client.py checkout    # <--- *** don't forget this ***

After that you can just get yourself a .mozconfig file and build as you normally would.

You will need to have autoconf-2.13 installed. If you don't already, please go here to find out how to get it for your platform.

If you get the error message "No module named subprocess", that's because you didn't install Python 2.4 or later. Go back two paragraphs.

{{template.Warning("If you don\'t run client.py, it won\'t build.")}}

client.py does three things:

  • Pulls the correct version (by tag) of NSS and NSPR and places them in right locations in your source tree. This is required to build.
  • Pulls Tamarin code. This is not required (and it's only a pull, so it's harmless). Pass --no-tamarin to client.py to skip this.
  • Runs a 'hg pull' to pull changes. This is also not required (in fact, you may prefer to pull manually). Pass --hg=echo to client.py to skip this.

For an up-to-date copy of CVS trunk via hg (rather than the Mozilla 2 trunk), see http://hg.mozilla.org/cvs-trunk-mirror/. In order to build, you'll need to run the same client.py script, which is not provided in cvs-trunk-mirror. You need to get that from mozilla-central, then copy it into the source directory and run.

How can I edit and update files?

You can randomly edit files, just like CVS.

To update a tree, run

python client.py checkout

(just as you did as the last step of pulling it originally). If you just use hg pull -u, you risk not getting updates to NSPR, NSS, or tamarin-central that are required to build.

It is not possible to update only one directory; you have to update the entire tree.

How can I diff and patch files?

  • hg diff diffs the entire tree by default. Use hg diff . (note the dot) to diff only the current directory.
  • When applying a patch generated by Mercurial, use patch -p1, not patch -p0. (This is due to a quirk of Mercurial diff output—it refers to fictional "a" and "b" directories. Don't ask.)

hg (before 1.0) had no exact equivalent of cvs diff -u8p. The simplest thing is hg diff, which provides 3 lines of context. To get 8 lines of context, enable the hg extdiff command (by editing your ~/.hgrc file). In 1.0, a -U parameter was added to hg's diff command (but it didn't work correctly in qdiff; that'll be fixed in the next version). There, you can use -U8 to get 8 lines of context. You can add this to a hgrc's {{mediawiki.external('default')}} section to make it the default.

How do I check stuff in?

To commit your changes to your local repository:

hg commit

To commit just some files, as opposed to every changed file as reported by hg status (see hg help commit for more details):

hg commit dir/file1 dir/file2 file3

To push those changes upstream to the central repository:

hg push

For that to work, you have to have committer access, and you must edit the file (your-local-hg-root)/.hg/hgrc (note, this is NOT your ~/.hgrc) to add this line:

[paths]
default = http://hg.mozilla.org/mozilla-central/
default-push = ssh://hg.mozilla.org/mozilla-central/

You also have to tell ssh what username to use when connecting to hg.mozilla.org. This should be the username associated with your Mozilla LDAP account. You can do this either by making the default-push path above more complicated (user@host.name@hg.mozilla.org) or by adding lines to your ~/.ssh/config :

 Host hg.mozilla.org
 User user@host.domain

You'll get a bogus error message each time you push:

remote: Could not chdir to home directory : No such file or directory

Just ignore it.

How do I deal with "abort: push creates new remote heads!"?

Whatever you do, don't do 'push -f' like the message suggests. (It'll probably fail anyway, but don't try it.)

Someone pushed new commits upstream since your last pull. You then committed your patch locally and are trying to push that commit upstream; that upstream has a different commit that you started from.

There are two things you can do. The simplest is to merge your commits: run hg pull, then hg merge. Fix up any conflicts, and then commit the merge: hg commit -m "Merge commit for bug 123456". Then hg push as normal. This has the unfortunate side effect of leaving an ugly minor merge commit in the revision history, and, worse, making your patch more difficult to back out if you had conflicts to fix up.

However, it is the simplest thing to do, and is very safe. There is another approach, but it's considerably more arcane -- a fix/replacement is in the works.

{{template.Warning("This next approach mostly works fine, but there have been reports of patches being eaten at various times. Take steps to back up your patch (perhaps by obtaining a diff: hg log -p -r 12345 to show the patch for rev 12345) until you\'re sure things work like you expect.")}}

The more advanced thing you can do is to import the commit into mq, pop it off the queue, update, and then commit it again before pushing:

% hg log -l 5
415[tip]   d1accb6ee840   2008-04-30 09:57 -0700   vladimir
  b=430873; fast path drawImage with a canvas as source
414   3a3ecbb4873e   2008-04-30 09:55 -0700   vladimir
  cvs sync
% hg qimport -r 415
% hg qtop
415.diff
% hg qpop
Patch queue now empty
% hg pull -u
... various pull/update messages ...
% hg qpush
applying 415.diff
Now at: 415.diff
Fix up conficts as necessary; if you fixed up any, run hg qrefresh first
% hg qrm -r 415.diff
qrm -r means "remove this patch from my queue, but keep the revision"
% hg log -l 5
verify that the log looks good, with your commit on top
% hg push

If you already use mq to manage your patches, then just make sure you pull/update right before committing and pushing your patch. If you have problems with the above, it's ok to just do a simple merge as described previously.

How do I see what these commands will do before I do them?

If you want to see what hg commit will commit, run hg diff first.

If you want to see what hg push will push, run hg outgoing first.

If you want to see what hg pull will pull, run hg incoming first.

These pairs of commands all take similar arguments, for good reason. These are a good idea to use all the time when you're learning mercurial. And even once you're an expert, always doing outgoing before push is a good idea.

Help

Help, I can't push!

If you're trying to push, and you can't, first try this:

 $ ssh hg.mozilla.org

If you see output like:

 Permission denied (publickey,gssapi-with-mic).

then you need to configure your username correctly or you don't have an hg.mozilla.org account.

If you see output like:

 You are not allowed to use this system, go away!

then you need to file a bug in mozilla.org:Server Operations.

However, the output:

 Could not chdir to home directory : No such file or directory

is harmless (although some people see it and some people don't).

Things that have changed

bonsai blame == hg annotate
bonsai log == hg revisions
also you can browse the repository using the "manifest" link.

  • There's no Bugzilla integration for Mercurial.

Revision Source

<h3 name="How_is_Mercurial_different_from_CVS.3F"> How is Mercurial different from CVS? </h3>
<ul><li> "Very".  You should read and understand <a href="en/Mercurial_basics">Mercurial basics</a> before undertaking work with Mercurial that you care about.
</li></ul>
<ul><li> Mercurial checkins are atomic.
</li></ul>
<ul><li> In Mercurial, tagging is fast and O(1).
</li></ul>
<ul><li> Mercurial makes it easy for anyone to fork the central repository.  (The command is <code>hg clone</code>.)
</li></ul>
<ul><li> Mercurial makes branching quick and easy and keeps merging pretty much sane.  (See <a href="en/Publishing_Mercurial_Clones">Publishing Mercurial Clones</a>.)
</li></ul>
<ul><li> With Mercurial, a complete, fully armed and operational <i>clone</i> of the entire Mozilla repository is on your local hard drive.  You can do work locally and check it in without affecting anybody else.  To push changes upstream, use <code>hg push</code>.
</li></ul>
<ul><li> <a class="external" href="http://hgbook.red-bean.com/hgbookch12.html#x16-26700012">Mercurial queues</a> can help you juggle patches.  It's like <a class="external" href="http://savannah.nongnu.org/projects/quilt">Quilt</a>.  The idea behind Quilt is this:  <blockquote><p>The scripts allow to manage a series of patches by keeping track of the changes each patch makes. Patches can be applied, un-applied, refreshed, etc.</p> <p>The key philosophical concept is that your primary output is patches. Not ".c" files, not ".h" files. But patches. So patches are the first-class object here.</p> </blockquote>
</li></ul>
<ul><li> When CVS finds merge conflicts, it puts conflict markers in your file.  When Mercurial finds merge conflicts, it launches a <a class="external" href="http://www.selenic.com/mercurial/wiki/index.cgi/MergeProgram">merge program</a>.  This is a pain in the neck.
</li></ul>
<ul><li> In a lot of places where CVS is per-file or per-directory, Mercurial is per-repository.  For example, a single Mercurial changeset may contain changes to many files throughout the tree.
</li></ul>
<ul><li> <b>We hope Mercurial will allow us to rethink the way we work.</b>  Teams and individuals should be able to branch and merge much more easily—without opening IT tickets.  People outside the community who are powerhouse developers should be able to do surprising stuff with this.  Companies maintaining forks of Mozilla should have an easier time too.  It all sort of remains to be seen, though.
</li></ul>
<h3 name="How_do_I_install_Mercurial.3F"> How do I install Mercurial? </h3>
<p>If you use <code>apt-get</code>, <code>emerge</code>, <code>port</code>, or <code>yum</code> to install software, just do the usual.  If not, the <a class="external" href="http://www.selenic.com/mercurial/wiki/index.cgi/BinaryPackages">Mercurial binary packages</a> are for you.  Or see {{mediawiki.interwiki('wikimo', 'Mercurial_on_Windows', 'wikimo:Mercurial on Windows')}}.
</p><p>After installing, <b>choose a <a class="external" href="http://www.selenic.com/mercurial/wiki/index.cgi/MergeProgram">merge program</a></b>.  Seriously.  Do it now.  If you don't, Mercurial will choose one for you and spring it on you when you least expect it.
</p>
<h3 name="How_does_Mercurial_handle_line_endings.3F"> How does Mercurial handle line endings? </h3>
<p>The Windows version of Mercurial does not automatically convert line endings between Windows and Unix styles.  All our repositories use Unix line endings.  We need a story for Windows, but right now I have no ideas.
</p><p>(How about a pre-commit hook that rejects pushes containing CR with a suitably informative error message? We possibly want to make exceptions for certain types of files (at least binary files of course), but we can tweak the hook as necessary as these crop up. Mercurial 1.0 adds a standard hook for this in the win32text extension that we could use/adapt. --jwatt)
</p>
<h2 name="How_can_I..."> How can I...</h2>
<h3 name="How_can_I_check_out_Mozilla.3F"> How can I check out Mozilla? </h3>
<p>The Mozilla 2 trunk is located at http://hg.mozilla.org/mozilla-central/ .
</p><p>You need <a class="external" href="http://www.python.org/download/">Python 2.4 or later</a> just to check everything out.  This is because we're using Python to do some checkout-related stuff that <code>client.mk</code> used to do—blame bsmedberg ;)
</p>
<pre class="eval">hg clone <span class="plain">http://hg.mozilla.org/mozilla-central/</span> mozilla
cd mozilla
python client.py checkout    # &lt;--- *** don't forget this ***
</pre>
<p>After that you can just get yourself a .mozconfig file and build as you normally would.
</p><p>You will need to have autoconf-2.13 installed. If you don't already, <a href="en/Build_Documentation#Build_prerequisites">please go here</a> to find out how to get it for your platform.
</p><p>If you get the error message "No module named subprocess", that's because you didn't install Python 2.4 or later.  Go back two paragraphs.
</p><p>{{template.Warning("If you don\'t run client.py, it won\'t build.")}}
</p><p>client.py does three things:
</p>
<ul><li> Pulls the correct version (by tag) of NSS and NSPR and places them in right locations in your source tree.  This is required to build.
</li><li> Pulls Tamarin code.  This is not required (and it's only a pull, so it's harmless).  Pass --no-tamarin to client.py to skip this.
</li><li> Runs a 'hg pull' to pull changes.  This is also not required (in fact, you may prefer to pull manually).  Pass --hg=echo to client.py to skip this.
</li></ul>
<p>For an up-to-date copy of CVS trunk via hg (rather than the Mozilla 2 trunk), see http://hg.mozilla.org/cvs-trunk-mirror/. In order to build, you'll need to run the same client.py script, which is not provided in cvs-trunk-mirror. You need to <a class="external" href="http://hg.mozilla.org/mozilla-central/?file/tip/client.py">get that from mozilla-central</a>, then copy it into the source directory and run.
</p>
<h3 name="How_can_I_edit_and_update_files.3F"> How can I edit and update files? </h3>
<p>You can randomly edit files, just like CVS.
</p><p>To update a tree, run
</p>
<pre class="eval">python client.py checkout
</pre>
<p>(just as you did as the last step of pulling it originally).  If you just use <code>hg pull -u</code>, you risk not getting updates to NSPR, NSS, or tamarin-central that are required to build.
</p><p>It is not possible to update only one directory; you have to update the entire tree.
</p>
<h3 name="How_can_I_diff_and_patch_files.3F"> How can I diff and patch files? </h3>
<ul><li> <code>hg diff</code> diffs the entire tree by default.  Use <code>hg diff .</code> (note the dot) to diff only the current directory.
</li></ul>
<ul><li> When applying a patch generated by Mercurial, use <code>patch -p1</code>, not <code>patch -p0</code>.  (This is due to a quirk of Mercurial diff output—it refers to fictional "a" and "b" directories.  Don't ask.)
</li></ul>
<p><code>hg</code> (before 1.0) had no exact equivalent of <code>cvs diff -u8p</code>. The simplest thing is <code>hg diff</code>, which provides 3 lines of context. To get 8 lines of context, enable the <code>hg extdiff</code> command (by editing your <code>~/.hgrc</code> file). In 1.0, a -U parameter was added to hg's diff command (but it didn't work correctly in qdiff; that'll be fixed in the next version). There, you can use -U8 to get 8 lines of context. You can add this to a hgrc's {{mediawiki.external('default')}} section to make it the default.
</p>
<h3 name="How_do_I_check_stuff_in.3F"> How do I check stuff in? </h3>
<p>To commit your changes <i>to your local repository</i>:
</p>
<pre class="eval">hg commit
</pre>
<p>To commit just some files, as opposed to every changed file as reported by <code>hg status</code> (see <code>hg help commit</code> for more details):
</p>
<pre class="eval">hg commit dir/file1 dir/file2 file3
</pre>
<p>To push those changes upstream to the central repository:
</p>
<pre class="eval">hg push
</pre>
<p>For that to work, you have to have committer access, and you must edit the file <code><i>(your-local-hg-root)</i>/.hg/hgrc</code> (note, this is <strong>NOT</strong> your <code>~/.hgrc</code>) to add this line:
</p>
<pre class="eval"><span class="plain">[paths]
default = http://hg.mozilla.org/mozilla-central/</span>
<b>default-push = <span class="plain">ssh://hg.mozilla.org/mozilla-central/</span></b>
</pre>
<p>You also have to tell ssh what username to use when connecting to hg.mozilla.org.  This should be the username associated with your Mozilla LDAP account.  You can do this either by making the default-push path above more complicated (user@host.name@hg.mozilla.org) or by adding lines to your ~/.ssh/config :
</p>
<pre class="eval"> Host hg.mozilla.org
 User user@host.domain
</pre>
<p>You'll get a bogus error message each time you push:
</p>
<pre class="eval">remote: Could not chdir to home directory : No such file or directory
</pre>
<p>Just ignore it.
</p>
<h3 name="How_do_I_deal_with_.22abort:_push_creates_new_remote_heads.21.22.3F"> How do I deal with "abort: push creates new remote heads!"? </h3>
<p>Whatever you do, don't do 'push -f' like the message suggests.  (It'll probably fail anyway, but don't try it.)
</p><p>Someone pushed new commits upstream since your last pull.  You then committed your patch locally and are trying to push that commit upstream; that upstream has a different commit that you started from.
</p><p>There are two things you can do.  The simplest is to merge your commits: run hg pull, then hg merge.  Fix up any conflicts, and then commit the merge: hg commit -m "Merge commit for bug 123456".  Then hg push as normal.  This has the unfortunate side effect of leaving an ugly minor merge commit in the revision history, and, worse, making your patch more difficult to back out if you had conflicts to fix up.
</p><p>However, it is the simplest thing to do, and is very safe.  There is another approach, but it's considerably more arcane -- a fix/replacement is in the works.
</p><p>{{template.Warning("This next approach mostly works fine, but there have been reports of patches being eaten at various times.  Take steps to back up your patch (perhaps by obtaining a diff: hg log -p -r 12345 to show the patch for rev 12345) until you\'re sure things work like you expect.")}}
</p><p>The more advanced thing you can do is to import the commit into mq, pop it off the queue, update, and then commit it again before pushing:
</p>
<pre class="eval">% <b>hg log -l 5</b>
415[tip]   d1accb6ee840   2008-04-30 09:57 -0700   vladimir
  b=430873; fast path drawImage with a canvas as source
414   3a3ecbb4873e   2008-04-30 09:55 -0700   vladimir
  cvs sync
% <b>hg qimport -r 415</b>
% <b>hg qtop</b>
415.diff
% <b>hg qpop</b>
Patch queue now empty
% <b>hg pull -u</b>
<i>... various pull/update messages ...</i>
% <b>hg qpush</b>
applying 415.diff
Now at: 415.diff
<i>Fix up conficts as necessary; if you fixed up any, run hg qrefresh first</i>
% <b>hg qrm -r 415.diff</b>
<i>qrm -r means "remove this patch from my queue, but keep the revision"</i>
% <b>hg log -l 5</b>
<i>verify that the log looks good, with your commit on top</i>
% <b>hg push</b>
</pre>
<p>If you already use mq to manage your patches, then just make sure you pull/update right before committing and pushing your patch.  If you have problems with the above, it's ok to just do a simple merge as described previously.
</p>
<h3 name="How_do_I_see_what_these_commands_will_do_before_I_do_them.3F"> How do I see what these commands will do before I do them? </h3>
<p>If you want to see what <code>hg commit</code> will commit, run <code>hg diff</code> first.
</p><p>If you want to see what <code>hg push</code> will push, run <code>hg outgoing</code> first.
</p><p>If you want to see what <code>hg pull</code> will pull, run <code>hg incoming</code> first.
</p><p>These pairs of commands all take similar arguments, for good reason.  These are a good idea to use all the time when you're learning mercurial.  And even once you're an expert, always doing outgoing before push is a good idea.
</p>
<h2 name="Help"> Help </h2>
<h3 name="Help.2C_I_can.27t_push.21"> Help, I can't push! </h3>
<p>If you're trying to push, and you can't, first try this:
</p>
<pre class="eval"> $ ssh hg.mozilla.org
</pre>
<p>If you see output like:
</p>
<pre class="eval"> Permission denied (publickey,gssapi-with-mic).
</pre>
<p>then you need to <a href="#How_do_I_check_stuff_in.3F">configure your username correctly</a> or you don't have an hg.mozilla.org account.
</p><p>If you see output like:
</p>
<pre class="eval"> You are not allowed to use this system, go away!
</pre>
<p>then you need to file a bug in mozilla.org:Server Operations.
</p><p>However, the output:
</p>
<pre class="eval"> Could not chdir to home directory : No such file or directory
</pre>
<p>is harmless (although some people see it and some people don't).
</p>
<h2 name="Things_that_have_changed"> Things that have changed </h2>
<ul><li> Bonsai is replaced by the Hg web viewer, see <a class="external" href="http://hg.mozilla.org/mozilla-central/">. This lacks some bonsai features that would be nice, including mark, line-number anchors, and graphs. There are some terminology differences:
</a></li></ul><a class="external" href="http://hg.mozilla.org/mozilla-central/">
<p>bonsai blame == hg annotate<br>
bonsai log == hg revisions<br>
also you can browse the repository using the "manifest" link.
</p>
</a><ul><a class="external" href="http://hg.mozilla.org/mozilla-central/"></a><li><a class="external" href="http://hg.mozilla.org/mozilla-central/"> MXR for mozilla-central is </a><a class="external" href="http://mxr.mozilla.org/mozilla-central/">now available</a>.
</li></ul>
<ul><li> There's no Bugzilla integration for Mercurial.
</li></ul>
<ul><li> <a href="en/Mercurial%2f%2fDesired_Features">Mercurial/Desired Features</a>
</li></ul>
Revert to this revision