Bismillahirrahmannirahhim~

This commit is contained in:
Jacque Fresco 2022-12-09 13:33:42 +09:00 committed by tfelypoc
commit dda7b72891
22 changed files with 9894 additions and 0 deletions

119
_Al_Fatiha.html Normal file
View File

@ -0,0 +1,119 @@
<!-- -*- html -*- -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Mercurial: The Definitive Guide</title>
<link rel="stylesheet" href="/support/styles.css" type="text/css"/>
<link rel="alternate" type="application/atom+xml" title="Comments"
href="/feeds/comments/"/>
<link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"/>
<script type="text/javascript" src="/support/jquery.js"></script>
<script type="text/javascript" src="/support/form.js"></script>
<script type="text/javascript" src="/support/hsbook.js"></script>
</head>
<body>
<div class="navheader"><h1 class="booktitle">Mercurial: The Definitive Guide<div class="authors">by Bryan O'Sullivan</div></h1></div>
<div class="book">
<h2>Welcome to Mercurial: The Definitive Guide</h2>
<p>This is the online home of the book &#8220;Mercurial: The
Definitive Guide&#8221;.
It was published in 2009 by O'Reilly Media.</p>
<p><a href="http://www.selenic.com/mercurial">Mercurial</a> is a
fast, lightweight source control management system
designed for easy and efficient handling of very large distributed
projects. My book tells you what it is, why you should care, and
how you can use it effectively.</p>
<h2>Read it online</h2>
<p>I make the content freely available online: you
can <a href="/read/"><i>read it here</i></a>. If you like it,
please <a href="#buy">buy a copy</a>!</p>
<p>For news updates, please
visit <a href="http://www.serpentine.com/blog/">my blog</a>. You
should follow me on
Twitter <a href="http://twitter.com/bos31337">here</a>.</p>
<h2><a name="#buy">How</a> to buy</h2>
<p>If you like the book, please support the work of the Software
Freedom Conservancy (<a href="#sfc">see below</a>) by buying a
copy.</p>
<ul>
<li><a href="http://www.amazon.com/gp/product/0596800673?ie=UTF8&tag=reaworhas-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596800673">Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=reaworhas-20&l=as2&o=1&a=0596800673" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></li>
<li><a href="http://oreilly.com/catalog/9780596800673/">O'Reilly Media</a></li>
</ul>
<h2>You should contribute!</h2>
<p>I publish the source code for this book
as <a href="http://bitbucket.org/bos/hgbook">a
Mercurial repository</a>. Please feel
welcome to clone it, make modifications to your copy, and send me
changes. Getting a copy of the source takes just a few seconds if
you have Mercurial installed:</p>
<pre class="screen">hg clone http://bitbucket.org/bos/hgbook</pre>
<p>The online version of the book includes a comment system
that you can use to send feedback involving errors, omissions, and
suggestions.</p>
<p>(If you would like to adapt the comment system for a
publishing project of your own, the source for the web application
is included with the book source at the link above.)</p>
<h2><a name="sfc">How</a> I help Mercurial and free software, and
you can too</h2>
<p>Mercurial is a member of the <a href="http://conservancy.softwarefreedom.org/">Software Freedom Conservancy</a>, a
wonderful non-profit organisation that offers its member projects
legal and administrative advice.</p>
<p>I donate my royalties from the sales of this book to the
Software Freedom Conservancy, and I encourage you to support their
work, too.</p>
<p>The SFC can
accept <a href="http://conservancy.softwarefreedom.org/?donate">accept
donations</a> (tax-free under IRS 501(c)(3), within the United
States) on behalf of its member projects. If you would like to
support Mercurial directly, please consider making a donation to
the SFC on its behalf.</p>
<p>If you would like to help free software developers to provide
their important public services without being impeded by legal
issues, please consider donating to the SFC's sister organisation,
the <a href="http://www.softwarefreedom.org/">Software Freedom Law
Center</a>.</p>
</div>
<div class="hgbookfooter"> <p><img src="/support/figs/rss.png"> Want to stay
up to date? Subscribe to comment feeds for any chapter, or
the <a class="feed"
href="/feeds/comments/">entire book</a>.</p> <p>Copyright
2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by
<a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a
href="http://mattahan.deviantart.com/">Mattahan</a>.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

61
read/_Al_Fatiha.html Normal file
View File

@ -0,0 +1,61 @@
<!-- -*- html -*- -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Mercurial: The Definitive Guide</title>
<link rel="stylesheet" href="/support/styles.css" type="text/css"/>
<link rel="alternate" type="application/atom+xml" title="Comments"
href="/feeds/comments/"/>
<link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"/>
<script type="text/javascript" src="/support/jquery.js"></script>
<script type="text/javascript" src="/support/form.js"></script>
<script type="text/javascript" src="/support/hsbook.js"></script>
</head>
<body>
<div class="navheader"><h1 class="booktitle">Mercurial: The Definitive Guide<div class="authors">by Bryan O'Sullivan</div></h1></div>
<div class="book"><ul class="booktoc">
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:preface/"><img src="/support/figs/rss.png"/></a></span>0. <a href="preface.html">Preface</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:intro/"><img src="/support/figs/rss.png"/></a></span>1. <a href="how-did-we-get-here.html">How did we get here?</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:tour-basic/"><img src="/support/figs/rss.png"/></a></span>2. <a href="a-tour-of-mercurial-the-basics.html">A tour of Mercurial: the basics</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:tour-merge/"><img src="/support/figs/rss.png"/></a></span>3. <a href="a-tour-of-mercurial-merging-work.html">A tour of Mercurial: merging work</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:concepts/"><img src="/support/figs/rss.png"/></a></span>4. <a href="behind-the-scenes.html">Behind the scenes</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:daily/"><img src="/support/figs/rss.png"/></a></span>5. <a href="mercurial-in-daily-use.html">Mercurial in daily use</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/cha:collab/"><img src="/support/figs/rss.png"/></a></span>6. <a href="collaborating-with-other-people.html">Collaborating with other people</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:names/"><img src="/support/figs/rss.png"/></a></span>7. <a href="file-names-and-pattern-matching.html">File names and pattern matching</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:branch/"><img src="/support/figs/rss.png"/></a></span>8. <a href="managing-releases-and-branchy-development.html">Managing releases and branchy development</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:undo/"><img src="/support/figs/rss.png"/></a></span>9. <a href="finding-and-fixing-mistakes.html">Finding and fixing mistakes</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:hook/"><img src="/support/figs/rss.png"/></a></span>10. <a href="handling-repository-events-with-hooks.html">Handling repository events with hooks</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:template/"><img src="/support/figs/rss.png"/></a></span>11. <a href="customizing-the-output-of-mercurial.html">Customizing the output of Mercurial</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:mq/"><img src="/support/figs/rss.png"/></a></span>12. <a href="managing-change-with-mercurial-queues.html">Managing change with Mercurial Queues</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:mq-collab/"><img src="/support/figs/rss.png"/></a></span>13. <a href="advanced-uses-of-mercurial-queues.html">Advanced uses of Mercurial Queues</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:hgext/"><img src="/support/figs/rss.png"/></a></span>14. <a href="adding-functionality-with-extensions.html">Adding functionality with extensions</a></li>
<li class="zebra_a"><span class="chapinfo">2009-04-28<a href="/feeds/comments/svn/"><img src="/support/figs/rss.png"/></a></span>A. <a href="migrating-to-mercurial.html">Migrating to Mercurial</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-04<a href="/feeds/comments/chap:mqref/"><img src="/support/figs/rss.png"/></a></span>B. <a href="mercurial-queues-reference.html">Mercurial Queues reference</a></li>
<li class="zebra_a"><span class="chapinfo">2009-03-30<a href="/feeds/comments/chap:srcinstall/"><img src="/support/figs/rss.png"/></a></span>C. <a href="installing-mercurial-from-source.html">Installing Mercurial from source</a></li>
<li class="zebra_b"><span class="chapinfo">2009-03-30<a href="/feeds/comments/cha:opl/"><img src="/support/figs/rss.png"/></a></span>D. <a href="open-publication-license.html">Open Publication License</a></li>
</ul></div>
<div class="hgbookfooter"> <p><img src="/support/figs/rss.png"> Want to stay
up to date? Subscribe to comment feeds for any chapter, or
the <a class="feed"
href="/feeds/comments/">entire book</a>.</p> <p>Copyright
2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by
<a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a
href="http://mattahan.deviantart.com/">Mattahan</a>.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -0,0 +1,384 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 3. A tour of Mercurial: merging work</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="a-tour-of-mercurial-the-basics.html" title="Chapter 2. A tour of Mercurial: the basics"><link rel="next" href="behind-the-scenes.html" title="Chapter 4. Behind the scenes"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 3. A tour of Mercurial: merging work</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="a-tour-of-mercurial-the-basics.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="behind-the-scenes.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:tour-merge"><div class="titlepage"><div><div><h2 class="title">Chapter 3. A tour of Mercurial: merging work</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="a-tour-of-mercurial-merging-work.html#id352947">Merging streams of work</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-merging-work.html#id353683">Head changesets</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-merging-work.html#id353830">Performing the merge</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-merging-work.html#id353997">Committing the results of the merge</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-merging-work.html#id354262">Merging conflicting changes</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-merging-work.html#id354379">Using a graphical merge tool</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-merging-work.html#id354524">A worked example</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-merging-work.html#sec:tour-merge:fetch">Simplifying the pull-merge-commit sequence</a></span></dt><dt><span class="sect1"><a href="a-tour-of-mercurial-merging-work.html#id355904">Renaming, copying, and merging</a></span></dt></dl></div><p id="x_338"><a name="x_338"></a>We've now covered cloning a repository, making changes in a
repository, and pulling or pushing changes from one repository
into another. Our next step is <span class="emphasis"><em>merging</em></span>
changes from separate repositories.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id352947">Merging streams of work</h2></div></div></div><p id="x_339"><a name="x_339"></a>Merging is a fundamental part of working with a distributed
revision control tool. Here are a few cases in which the need
to merge work arises.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_33a"><a name="x_33a"></a>Alice and Bob each have a personal copy of a
repository for a project they're collaborating on. Alice
fixes a bug in her repository; Bob adds a new feature in
his. They want the shared repository to contain both the
bug fix and the new feature.</p></li><li><p id="x_33b"><a name="x_33b"></a>Cynthia frequently works on several different
tasks for a single project at once, each safely isolated in
its own repository. Working this way means that she often
needs to merge one piece of her own work with
another.</p></li></ul></div><p id="x_33c"><a name="x_33c"></a>Because we need to merge often, Mercurial makes
the process easy. Let's walk through a merge. We'll begin by
cloning yet another repository (see how often they spring up?)
and making a change in it.</p><pre id="id353643" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone hello my-new-hello</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd my-new-hello</code></strong>
# Make some simple edits to hello.c.
<code class="prompt">$</code> <strong class="userinput"><code>my-text-editor hello.c</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'A new hello for a new day.'</code></strong>
</pre><p id="x_33d"><a name="x_33d"></a>We should now have two copies of
<code class="filename">hello.c</code> with different contents. The
histories of the two repositories have also diverged, as
illustrated in <a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:sep-repos" title="Figure 3.1. Divergent recent histories of the my-hello and my-new-hello repositories">Figure 3.1, “Divergent recent histories of the my-hello and my-new-hello
repositories”</a>. Here is a copy of our
file from one repository.</p><pre id="id353616" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat hello.c</code></strong>
/*
* Placed in the public domain by Bryan O'Sullivan. This program is
* not covered by patents in the United States or other countries.
*/
#include &lt;stdio.h&gt;
int main(int argc, char **argv)
{
printf("once more, hello.\n");
printf("hello, world!\");
printf("hello again!\n");
return 0;
}
</pre><p id="x_722"><a name="x_722"></a>And here is our slightly different version from the other
repository.</p><pre id="id353585" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat ../my-hello/hello.c</code></strong>
/*
* Placed in the public domain by Bryan O'Sullivan. This program is
* not covered by patents in the United States or other countries.
*/
#include &lt;stdio.h&gt;
int main(int argc, char **argv)
{
printf("hello, world!\");
printf("hello again!\n");
return 0;
}
</pre><div class="figure"><a name="fig:tour-merge:sep-repos"></a><p class="title"><b>Figure 3.1. Divergent recent histories of the <code class="filename">my-hello</code> and <code class="filename">my-new-hello</code>
repositories</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/tour-merge-sep-repos.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_33f"><a name="x_33f"></a>We already know that pulling changes from our <code class="filename">my-hello</code> repository will have no
effect on the working directory.</p><pre id="id353533" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg pull ../my-hello</code></strong>
pulling from ../my-hello
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
</pre><p id="x_340"><a name="x_340"></a>However, the <span class="command"><strong>hg pull</strong></span>
command says something about “<span class="quote">heads</span>”.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id353683">Head changesets</h3></div></div></div><p id="x_341"><a name="x_341"></a>Remember that Mercurial records what the parent
of each change is. If a change has a parent, we call it a
child or descendant of the parent. A head is a change that
has no children. The tip revision is thus a head, because the
newest revision in a repository doesn't have any children.
There are times when a repository can contain more than one
head.</p><div class="figure"><a name="fig:tour-merge:pull"></a><p class="title"><b>Figure 3.2. Repository contents after pulling from <code class="filename">my-hello</code> into <code class="filename">my-new-hello</code></b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/tour-merge-pull.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_343"><a name="x_343"></a>In <a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:pull" title="Figure 3.2. Repository contents after pulling from my-hello into my-new-hello">Figure 3.2, “Repository contents after pulling from my-hello into my-new-hello”</a>, you can
see the effect of the pull from <code class="filename">my-hello</code> into <code class="filename">my-new-hello</code>. The history that
was already present in <code class="filename">my-new-hello</code> is untouched, but
a new revision has been added. By referring to <a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:sep-repos" title="Figure 3.1. Divergent recent histories of the my-hello and my-new-hello repositories">Figure 3.1, “Divergent recent histories of the my-hello and my-new-hello
repositories”</a>, we can see that the
<span class="emphasis"><em>changeset ID</em></span> remains the same in the new
repository, but the <span class="emphasis"><em>revision number</em></span> has
changed. (This, incidentally, is a fine example of why it's
not safe to use revision numbers when discussing changesets.)
We can view the heads in a repository using the <span class="command"><strong>hg heads</strong></span> command.</p><pre id="id354126" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg heads</code></strong>
changeset: 6:b6fed4f21233
tag: tip
parent: 4:2278160e78d4
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
changeset: 5:5218ee8aecf3
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:55 2009 +0000
summary: A new hello for a new day.
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id353830">Performing the merge</h3></div></div></div><p id="x_344"><a name="x_344"></a>What happens if we try to use the normal <span class="command"><strong>hg update</strong></span> command to update to the
new tip?</p><pre id="id354203" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg update</code></strong>
abort: crosses branches (use 'hg merge' or 'hg update -C')
</pre><p id="x_345"><a name="x_345"></a>Mercurial is telling us that the <span class="command"><strong>hg update</strong></span> command won't do a merge;
it won't update the working directory when it thinks we might
want to do a merge, unless we force it to do so.
(Incidentally, forcing the update with <span class="command"><strong>hg update
-C</strong></span> would revert any uncommitted changes in the
working directory.)</p><p id="x_723"><a name="x_723"></a>To start a merge between the two heads, we use the
<span class="command"><strong>hg merge</strong></span> command.</p><pre id="id354163" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
merging hello.c
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
</pre><p id="x_347"><a name="x_347"></a>We resolve the contents of <code class="filename">hello.c</code>
This updates the working directory so that it
contains changes from <span class="emphasis"><em>both</em></span> heads, which
is reflected in both the output of <span class="command"><strong>hg
parents</strong></span> and the contents of
<code class="filename">hello.c</code>.</p><pre id="id354360" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 5:5218ee8aecf3
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:55 2009 +0000
summary: A new hello for a new day.
changeset: 6:b6fed4f21233
tag: tip
parent: 4:2278160e78d4
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
<code class="prompt">$</code> <strong class="userinput"><code>cat hello.c</code></strong>
/*
* Placed in the public domain by Bryan O'Sullivan. This program is
* not covered by patents in the United States or other countries.
*/
#include &lt;stdio.h&gt;
int main(int argc, char **argv)
{
printf("once more, hello.\n");
printf("hello, world!\");
printf("hello again!\n");
return 0;
}
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id353997">Committing the results of the merge</h3></div></div></div><p id="x_348"><a name="x_348"></a>Whenever we've done a merge, <span class="command"><strong>hg
parents</strong></span> will display two parents until we <span class="command"><strong>hg commit</strong></span> the results of the
merge.</p><pre id="id354037" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Merged changes'</code></strong>
</pre><p id="x_349"><a name="x_349"></a>We now have a new tip revision; notice that it has
<span class="emphasis"><em>both</em></span> of our former heads as its parents.
These are the same revisions that were previously displayed by
<span class="command"><strong>hg parents</strong></span>.</p><pre id="id354110" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 7:ecb0e17b2a4e
tag: tip
parent: 5:5218ee8aecf3
parent: 6:b6fed4f21233
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:56 2009 +0000
summary: Merged changes
</pre><p id="x_34a"><a name="x_34a"></a>In <a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:merge" title="Figure 3.3. Working directory and repository during merge, and following commit">Figure 3.3, “Working directory and repository during merge, and
following commit”</a>, you can see a
representation of what happens to the working directory during
the merge, and how this affects the repository when the commit
happens. During the merge, the working directory has two
parent changesets, and these become the parents of the new
changeset.</p><div class="figure"><a name="fig:tour-merge:merge"></a><p class="title"><b>Figure 3.3. Working directory and repository during merge, and
following commit</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/tour-merge-merge.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_69c"><a name="x_69c"></a>We sometimes talk about a merge having
<span class="emphasis"><em>sides</em></span>: the left side is the first parent
in the output of <span class="command"><strong>hg parents</strong></span>,
and the right side is the second. If the working directory
was at e.g. revision 5 before we began a merge, that revision
will become the left side of the merge.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id354262">Merging conflicting changes</h2></div></div></div><p id="x_34b"><a name="x_34b"></a>Most merges are simple affairs, but sometimes you'll find
yourself merging changes where each side modifies the same portions
of the same files. Unless both modifications are identical,
this results in a <span class="emphasis"><em>conflict</em></span>, where you have
to decide how to reconcile the different changes into something
coherent.</p><div class="figure"><a name="fig:tour-merge:conflict"></a><p class="title"><b>Figure 3.4. Conflicting changes to a document</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/tour-merge-conflict.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_34d"><a name="x_34d"></a><a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:conflict" title="Figure 3.4. Conflicting changes to a document">Figure 3.4, “Conflicting changes to a document”</a> illustrates
an instance of two conflicting changes to a document. We
started with a single version of the file; then we made some
changes; while someone else made different changes to the same
text. Our task in resolving the conflicting changes is to
decide what the file should look like.</p><p id="x_34e"><a name="x_34e"></a>Mercurial doesn't have a built-in facility for handling
conflicts. Instead, it runs an external program, usually one
that displays some kind of graphical conflict resolution
interface. By default, Mercurial tries to find one of several
different merging tools that are likely to be installed on your
system. It first tries a few fully automatic merging tools; if
these don't succeed (because the resolution process requires
human guidance) or aren't present, it tries a few
different graphical merging tools.</p><p id="x_34f"><a name="x_34f"></a>It's also possible to get Mercurial to run a
specific program or script, by setting the
<code class="envar">HGMERGE</code> environment variable to the name of your
preferred program.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id354379">Using a graphical merge tool</h3></div></div></div><p id="x_350"><a name="x_350"></a>My preferred graphical merge tool is
<span class="command"><strong>kdiff3</strong></span>, which I'll use to describe the
features that are common to graphical file merging tools. You
can see a screenshot of <span class="command"><strong>kdiff3</strong></span> in action in
<a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:kdiff3" title="Figure 3.5. Using kdiff3 to merge versions of a file">Figure 3.5, “Using kdiff3 to merge versions of a
file”</a>. The kind of
merge it is performing is called a <span class="emphasis"><em>three-way
merge</em></span>, because there are three different versions
of the file of interest to us. The tool thus splits the upper
portion of the window into three panes:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_351"><a name="x_351"></a>At the left is the <span class="emphasis"><em>base</em></span>
version of the file, i.e. the most recent version from
which the two versions we're trying to merge are
descended.</p></li><li><p id="x_352"><a name="x_352"></a>In the middle is “<span class="quote">our</span>” version of
the file, with the contents that we modified.</p></li><li><p id="x_353"><a name="x_353"></a>On the right is “<span class="quote">their</span>” version
of the file, the one that from the changeset that we're
trying to merge with.</p></li></ul></div><p id="x_354"><a name="x_354"></a>In the pane below these is the current
<span class="emphasis"><em>result</em></span> of the merge. Our task is to
replace all of the red text, which indicates unresolved
conflicts, with some sensible merger of the
<span class="quote">ours</span>” and “<span class="quote">theirs</span>” versions of the
file.</p><p id="x_355"><a name="x_355"></a>All four of these panes are <span class="emphasis"><em>locked
together</em></span>; if we scroll vertically or horizontally
in any of them, the others are updated to display the
corresponding sections of their respective files.</p><div class="figure"><a name="fig:tour-merge:kdiff3"></a><p class="title"><b>Figure 3.5. Using <span class="command">kdiff3</span> to merge versions of a
file</b></p><div class="figure-contents"><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="100%"><tr><td><img src="figs/kdiff3.png" width="100%" alt="XXX add text"></td></tr></table></div></div></div><br class="figure-break"><p id="x_357"><a name="x_357"></a>For each conflicting portion of the file, we can choose to
resolve the conflict using some combination of text from the
base version, ours, or theirs. We can also manually edit the
merged file at any time, in case we need to make further
modifications.</p><p id="x_358"><a name="x_358"></a>There are <span class="emphasis"><em>many</em></span> file merging tools
available, too many to cover here. They vary in which
platforms they are available for, and in their particular
strengths and weaknesses. Most are tuned for merging files
containing plain text, while a few are aimed at specialised
file formats (generally XML).</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id354524">A worked example</h3></div></div></div><p id="x_359"><a name="x_359"></a>In this example, we will reproduce the file modification
history of <a class="xref" href="a-tour-of-mercurial-merging-work.html#fig:tour-merge:conflict" title="Figure 3.4. Conflicting changes to a document">Figure 3.4, “Conflicting changes to a document”</a>
above. Let's begin by creating a repository with a base
version of our document.</p><pre id="id354880" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat &gt; letter.txt &lt;&lt;EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Greetings!</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>I am Mariam Abacha, the wife of former</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Nigerian dictator Sani Abacha.</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add letter.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m '419 scam, first draft'</code></strong>
</pre><p id="x_35a"><a name="x_35a"></a>We'll clone the repository and make a change to the
file.</p><pre id="id354860" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone scam scam-cousin</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd scam-cousin</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat &gt; letter.txt &lt;&lt;EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Greetings!</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>I am Shehu Musa Abacha, cousin to the former</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Nigerian dictator Sani Abacha.</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m '419 scam, with cousin'</code></strong>
</pre><p id="x_35b"><a name="x_35b"></a>And another clone, to simulate someone else making a
change to the file. (This hints at the idea that it's not all
that unusual to merge with yourself when you isolate tasks in
separate repositories, and indeed to find and resolve
conflicts while doing so.)</p><pre id="id354843" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone scam scam-son</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd scam-son</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat &gt; letter.txt &lt;&lt;EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Greetings!</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>I am Alhaji Abba Abacha, son of the former</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Nigerian dictator Sani Abacha.</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m '419 scam, with son'</code></strong>
</pre><p id="x_35c"><a name="x_35c"></a>Having created two
different versions of the file, we'll set up an environment
suitable for running our merge.</p><pre id="id355540" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone scam-cousin scam-merge</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd scam-merge</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg pull -u ../scam-son</code></strong>
pulling from ../scam-son
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
not updating, since new heads added
(run 'hg heads' to see heads, 'hg merge' to merge)
</pre><p id="x_35d"><a name="x_35d"></a>In this example, I'll set
<code class="envar">HGMERGE</code> to tell Mercurial to use the
non-interactive <span class="command"><strong>merge</strong></span> command. This is
bundled with many Unix-like systems. (If you're following this
example on your computer, don't bother setting
<code class="envar">HGMERGE</code>. You'll get dropped into a GUI file
merge tool instead, which is much preferable.)</p><pre id="id355530" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>export HGMERGE=merge</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
merging letter.txt
merge: warning: conflicts during merge
merging letter.txt failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
<code class="prompt">$</code> <strong class="userinput"><code>cat letter.txt</code></strong>
Greetings!
&lt;&lt;&lt;&lt;&lt;&lt;&lt; /tmp/tour-merge-conflictgW7-1Z/scam-merge/letter.txt
I am Shehu Musa Abacha, cousin to the former
=======
I am Alhaji Abba Abacha, son of the former
&gt;&gt;&gt;&gt;&gt;&gt;&gt; /tmp/letter.txt~other.c6Rq0s
Nigerian dictator Sani Abacha.
</pre><p id="x_35f"><a name="x_35f"></a>Because <span class="command"><strong>merge</strong></span> can't resolve the
conflicting changes, it leaves <span class="emphasis"><em>merge
markers</em></span> inside the file that has conflicts,
indicating which lines have conflicts, and whether they came
from our version of the file or theirs.</p><p id="x_360"><a name="x_360"></a>Mercurial can tell from the way <span class="command"><strong>merge</strong></span>
exits that it wasn't able to merge successfully, so it tells
us what commands we'll need to run if we want to redo the
merging operation. This could be useful if, for example, we
were running a graphical merge tool and quit because we were
confused or realised we had made a mistake.</p><p id="x_361"><a name="x_361"></a>If automatic or manual merges fail, there's nothing to
prevent us from “<span class="quote">fixing up</span>” the affected files
ourselves, and committing the results of our merge:</p><pre id="id355496" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat &gt; letter.txt &lt;&lt;EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Greetings!</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>I am Bryan O'Sullivan, no relation of the former</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>Nigerian dictator Sani Abacha.</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg resolve -m letter.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Send me your money'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 3:6f17ad930bf5
tag: tip
parent: 1:cef8fbca9a6f
parent: 2:dc8f64391590
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:57 2009 +0000
summary: Send me your money
</pre><div class="note"><table border="0" summary="Note: Where is the hg resolve command?"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Where is the hg resolve command?</th></tr><tr><td align="left" valign="top"><p id="x_724"><a name="x_724"></a>The <span class="command"><strong>hg resolve</strong></span> command was introduced
in Mercurial 1.1, which was released in December 2008. If
you are using an older version of Mercurial (run <span class="command"><strong>hg
version</strong></span> to see), this command will not be
present. If your version of Mercurial is older than 1.1,
you should strongly consider upgrading to a newer version
before trying to tackle complicated merges.</p></td></tr></table></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:tour-merge:fetch">Simplifying the pull-merge-commit sequence</h2></div></div></div><p id="x_362"><a name="x_362"></a>The process of merging changes as outlined above is
straightforward, but requires running three commands in
sequence.</p><pre id="id355698" class="programlisting">hg pull -u
hg merge
hg commit -m 'Merged remote changes'</pre><p id="x_363"><a name="x_363"></a>In the case of the final commit, you also need to enter a
commit message, which is almost always going to be a piece of
uninteresting “<span class="quote">boilerplate</span>” text.</p><p id="x_364"><a name="x_364"></a>It would be nice to reduce the number of steps needed, if
this were possible. Indeed, Mercurial is distributed with an
extension called <code class="literal">fetch</code> that
does just this.</p><p id="x_365"><a name="x_365"></a>Mercurial provides a flexible extension mechanism that lets
people extend its functionality, while keeping the core of
Mercurial small and easy to deal with. Some extensions add new
commands that you can use from the command line, while others
work “<span class="quote">behind the scenes,</span>” for example adding
capabilities to Mercurial's built-in server mode.</p><p id="x_366"><a name="x_366"></a>The <code class="literal">fetch</code>
extension adds a new command called, not surprisingly, <span class="command"><strong>hg fetch</strong></span>. This extension acts as a
combination of <span class="command"><strong>hg pull -u</strong></span>,
<span class="command"><strong>hg merge</strong></span> and <span class="command"><strong>hg commit</strong></span>. It begins by pulling
changes from another repository into the current repository. If
it finds that the changes added a new head to the repository, it
updates to the new head, begins a merge, then (if the merge
succeeded) commits the result of the merge with an
automatically-generated commit message. If no new heads were
added, it updates the working directory to the new tip
changeset.</p><p id="x_367"><a name="x_367"></a>Enabling the <code class="literal">fetch</code> extension is easy. Edit the
<code class="filename">.hgrc</code> file in your home
directory, and either go to the <code class="literal">extensions</code> section or create an
<code class="literal">extensions</code> section. Then
add a line that simply reads
<span class="quote"><code class="literal">fetch=</code></span>”.</p><pre id="id355838" class="programlisting">[extensions]
fetch =</pre><p id="x_368"><a name="x_368"></a>(Normally, the right-hand side of the
<span class="quote"><code class="literal">=</code></span>” would indicate where to find
the extension, but since the <code class="literal">fetch</code> extension is in the standard
distribution, Mercurial knows where to search for it.)</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id355904">Renaming, copying, and merging</h2></div></div></div><p id="x_729"><a name="x_729"></a>During the life of a project, we will often want to change
the layout of its files and directories. This can be as simple
as renaming a single file, or as complex as restructuring the
entire hierarchy of files within the project.</p><p id="x_72a"><a name="x_72a"></a>Mercurial supports these kinds of complex changes fluently,
provided we tell it what we're doing. If we want to rename a
file, we should use the <span class="command"><strong>hg rename</strong></span><sup>[<a name="id355926" href="#ftn.id355926" class="footnote">2</a>]</sup> command to rename it, so that Mercurial can do the
right thing later when we merge.</p><p id="x_72c"><a name="x_72c"></a>We will cover the use of these commands in more detail in
<a class="xref" href="mercurial-in-daily-use.html#chap:daily.copy" title="Copying files">the section called “Copying files”</a>.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id355926" href="#id355926" class="para">2</a>] </sup>If you're a Unix user, you'll be glad to know that the
<span class="command"><strong>hg rename</strong></span> command can be abbreviated as
<span class="command"><strong>hg mv</strong></span>.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="a-tour-of-mercurial-the-basics.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="behind-the-scenes.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 2. A tour of Mercurial: the basics </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 4. Behind the scenes</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,826 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 2. A tour of Mercurial: the basics</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="how-did-we-get-here.html" title="Chapter 1. How did we get here?"><link rel="next" href="a-tour-of-mercurial-merging-work.html" title="Chapter 3. A tour of Mercurial: merging work"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 2. A tour of Mercurial: the basics</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="how-did-we-get-here.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="a-tour-of-mercurial-merging-work.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:tour-basic"><div class="titlepage"><div><div><h2 class="title">Chapter 2. A tour of Mercurial: the basics</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#sec:tour:install">Installing Mercurial on your system</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id344575">Windows</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id344904">Mac OS X</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id344922">Linux</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id344998">Solaris</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id345016">Getting started</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id345318">Built-in help</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id345120">Working with a repository</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id345147">Making a local copy of a repository</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id345415">What's in a repository?</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id345536">A tour through history</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id345833">Changesets, revisions, and talking to other
people</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id345980">Viewing specific revisions</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id346082">More detailed information</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id346408">All about command options</a></span></dt><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id346595">Making and reviewing changes</a></span></dt><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id347157">Recording changes in a new changeset</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id347208">Setting up a username</a></span></dt><dd><dl><dt><span class="sect3"><a href="a-tour-of-mercurial-the-basics.html#sec:tour-basic:username">Creating a Mercurial configuration file</a></span></dt><dt><span class="sect3"><a href="a-tour-of-mercurial-the-basics.html#id347496">Choosing a user name</a></span></dt></dl></dd><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id347526">Writing a commit message</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id347874">Writing a good commit message</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id347674">Aborting a commit</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id347689">Admiring our new handiwork</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id347917">Sharing changes</a></span></dt><dd><dl><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#sec:tour:pull">Pulling changes from another repository</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id348343">Updating the working directory</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id348825">Pushing changes to another repository</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id349161">Default locations</a></span></dt><dt><span class="sect2"><a href="a-tour-of-mercurial-the-basics.html#id349277">Sharing changes over a network</a></span></dt></dl></dd><dt><span class="sect1"><a href="a-tour-of-mercurial-the-basics.html#id349357">Starting a new project</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:tour:install">Installing Mercurial on your system</h2></div></div></div><p id="x_1"><a name="x_1"></a>Prebuilt binary packages of Mercurial are available for
every popular operating system. These make it easy to start
using Mercurial on your computer immediately.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id344575">Windows</h3></div></div></div><p id="x_c"><a name="x_c"></a>The best version of Mercurial for Windows is
TortoiseHg, which can be found at <a class="ulink" href="http://bitbucket.org/tortoisehg/stable/wiki/Home" target="_top">http://bitbucket.org/tortoisehg/stable/wiki/Home</a>.
This package has no external dependencies; it “<span class="quote">just
works</span>”. It provides both command line and graphical
user interfaces.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id344904">Mac OS X</h3></div></div></div><p id="x_a"><a name="x_a"></a>Lee Cantey publishes an installer of Mercurial
for Mac OS X at <a class="ulink" href="http://mercurial.berkwood.com" target="_top">http://mercurial.berkwood.com</a>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id344922">Linux</h3></div></div></div><p id="x_2"><a name="x_2"></a>Because each Linux distribution has its own packaging
tools, policies, and rate of development, it's difficult to
give a comprehensive set of instructions on how to install
Mercurial binaries. The version of Mercurial that you will
end up with can vary depending on how active the person is who
maintains the package for your distribution.</p><p id="x_3"><a name="x_3"></a>To keep things simple, I will focus on installing
Mercurial from the command line under the most popular Linux
distributions. Most of these distributions provide graphical
package managers that will let you install Mercurial with a
single click; the package name to look for is
<code class="literal">mercurial</code>.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4"><a name="x_4"></a>Ubuntu and Debian:</p><pre id="id344957" class="programlisting">apt-get install mercurial</pre></li><li><p id="x_5"><a name="x_5"></a>Fedora:</p><pre id="id344968" class="programlisting">yum install mercurial</pre></li><li><p id="x_715"><a name="x_715"></a>OpenSUSE:</p><pre id="id344980" class="programlisting">zypper install mercurial</pre></li><li><p id="x_6"><a name="x_6"></a>Gentoo:</p><pre id="id344991" class="programlisting">emerge mercurial</pre></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id344998">Solaris</h3></div></div></div><p id="x_9"><a name="x_9"></a>SunFreeWare, at <a class="ulink" href="http://www.sunfreeware.com" target="_top">http://www.sunfreeware.com</a>,
provides prebuilt packages of Mercurial.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id345016">Getting started</h2></div></div></div><p id="x_e"><a name="x_e"></a>To begin, we'll use the <span class="command"><strong>hg
version</strong></span> command to find out whether Mercurial is
installed properly. The actual version information that it
prints isn't so important; we simply care whether the command
runs and prints anything at all.</p><pre id="id345379" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg version</code></strong>
Mercurial Distributed SCM (version 1.2)
Copyright (C) 2005-2008 Matt Mackall &lt;mpm@selenic.com&gt; and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</pre><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id345318">Built-in help</h3></div></div></div><p id="x_f"><a name="x_f"></a>Mercurial provides a built-in help system. This is
invaluable for those times when you find yourself stuck
trying to remember how to run a command. If you are
completely stuck, simply run <span class="command"><strong>hg
help</strong></span>; it will print a brief list of commands,
along with a description of what each does. If you ask for
help on a specific command (as below), it prints more
detailed information.</p><pre id="id345368" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg help init</code></strong>
hg init [-e CMD] [--remotecmd CMD] [DEST]
create a new repository in the given directory
Initialize a new repository in the given directory. If the given
directory does not exist, it is created.
If no directory is given, the current directory is used.
It is possible to specify an ssh:// URL as the destination.
See 'hg help urls' for more information.
options:
-e --ssh specify ssh command to use
--remotecmd specify hg command to run on the remote side
use "hg -v help init" to show global options
</pre><p id="x_10"><a name="x_10"></a>For a more impressive level of detail (which you won't
usually need) run <span class="command"><strong>hg help <code class="option">-v</code></strong></span>. The <code class="option">-v</code> option is short for
<code class="option">--verbose</code>, and tells
Mercurial to print more information than it usually
would.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id345120">Working with a repository</h2></div></div></div><p id="x_11"><a name="x_11"></a>In Mercurial, everything happens inside a
<span class="emphasis"><em>repository</em></span>. The repository for a project
contains all of the files that “<span class="quote">belong to</span>” that
project, along with a historical record of the project's
files.</p><p id="x_12"><a name="x_12"></a>There's nothing particularly magical about a repository; it
is simply a directory tree in your filesystem that Mercurial
treats as special. You can rename or delete a repository any
time you like, using either the command line or your file
browser.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id345147">Making a local copy of a repository</h3></div></div></div><p id="x_13"><a name="x_13"></a><span class="emphasis"><em>Copying</em></span> a repository is just a little
bit special. While you could use a normal file copying
command to make a copy of a repository, it's best to use a
built-in command that Mercurial provides. This command is
called <span class="command"><strong>hg clone</strong></span>, because it
makes an identical copy of an existing repository.</p><pre id="id345593" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg clone https://bitbucket.org/bos/hg-tutorial-hello</code></strong>
destination directory: hello
requesting all changes
adding changesets
adding manifests
adding file changes
added 5 changesets with 5 changes to 2 files
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_67c"><a name="x_67c"></a>One advantage of using <span class="command"><strong>hg
clone</strong></span> is that, as we can see above, it lets us clone
repositories over the network. Another is that it remembers
where we cloned from, which we'll find useful soon when we
want to fetch new changes from another repository.</p><p id="x_14"><a name="x_14"></a>If our clone succeeded, we should now have a local
directory called <code class="filename">hello</code>.
This directory will contain some files.</p><pre id="id345299" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>ls -l</code></strong>
total 4
drwxrwxr-x 3 bos bos 4096 May 5 06:55 hello
<code class="prompt">$</code> <strong class="userinput"><code>ls hello</code></strong>
Makefile hello.c
</pre><p id="x_15"><a name="x_15"></a>These files have the same contents and history in our
repository as they do in the repository we cloned.</p><p id="x_16"><a name="x_16"></a>Every Mercurial repository is complete,
self-contained, and independent. It contains its own private
copy of a project's files and history. As we just mentioned,
a cloned repository remembers the location of the repository
it was cloned from, but Mercurial will not communicate with
that repository, or any other, unless you tell it to.</p><p id="x_17"><a name="x_17"></a>What this means for now is that we're free to experiment
with our repository, safe in the knowledge that it's a private
<span class="quote">sandbox</span>” that won't affect anyone else.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id345415">What's in a repository?</h3></div></div></div><p id="x_18"><a name="x_18"></a>When we take a more detailed look inside a repository, we
can see that it contains a directory named <code class="filename">.hg</code>. This is where Mercurial
keeps all of its metadata for the repository.</p><pre id="id345568" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd hello</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls -a</code></strong>
. .. .hg Makefile hello.c
</pre><p id="x_19"><a name="x_19"></a>The contents of the <code class="filename">.hg</code> directory and its
subdirectories are private to Mercurial. Every other file and
directory in the repository is yours to do with as you
please.</p><p id="x_1a"><a name="x_1a"></a>To introduce a little terminology, the <code class="filename">.hg</code> directory is the
<span class="quote">real</span>” repository, and all of the files and
directories that coexist with it are said to live in the
<span class="emphasis"><em>working directory</em></span>. An easy way to
remember the distinction is that the
<span class="emphasis"><em>repository</em></span> contains the
<span class="emphasis"><em>history</em></span> of your project, while the
<span class="emphasis"><em>working directory</em></span> contains a
<span class="emphasis"><em>snapshot</em></span> of your project at a particular
point in history.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id345536">A tour through history</h2></div></div></div><p id="x_1b"><a name="x_1b"></a>One of the first things we might want to do with a new,
unfamiliar repository is understand its history. The <span class="command"><strong>hg log</strong></span> command gives us a view of
the history of changes in the repository.</p><pre id="id345930" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log</code></strong>
changeset: 4:2278160e78d4
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:16:53 2008 +0200
summary: Trim comments.
changeset: 3:0272e0d5a517
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:08:02 2008 +0200
summary: Get make to generate the final binary from a .o file.
changeset: 2:fef857204a0c
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:05:04 2008 +0200
summary: Introduce a typo into hello.c.
changeset: 1:82e55d328c8c
user: mpm@selenic.com
date: Fri Aug 26 01:21:28 2005 -0700
summary: Create a makefile
changeset: 0:0a04b987be5a
user: mpm@selenic.com
date: Fri Aug 26 01:20:50 2005 -0700
summary: Create a standard "hello, world" program
</pre><p id="x_1c"><a name="x_1c"></a>By default, this command prints a brief paragraph of output
for each change to the project that was recorded. In Mercurial
terminology, we call each of these recorded events a
<span class="emphasis"><em>changeset</em></span>, because it can contain a record
of changes to several files.</p><p id="x_1d"><a name="x_1d"></a>The fields in a record of output from <span class="command"><strong>hg log</strong></span> are as follows.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_1e"><a name="x_1e"></a><code class="literal">changeset</code>: This
field has the format of a number, followed by a colon,
followed by a hexadecimal (or <span class="emphasis"><em>hex</em></span>)
string. These are <span class="emphasis"><em>identifiers</em></span> for the
changeset. The hex string is a unique identifier: the same
hex string will always refer to the same changeset in every
copy of this repository. The
number is shorter and easier to type than the hex string,
but it isn't unique: the same number in two different clones
of a repository may identify different changesets.</p></li><li><p id="x_1f"><a name="x_1f"></a><code class="literal">user</code>: The identity of the
person who created the changeset. This is a free-form
field, but it most often contains a person's name and email
address.</p></li><li><p id="x_20"><a name="x_20"></a><code class="literal">date</code>: The date and time on
which the changeset was created, and the timezone in which
it was created. (The date and time are local to that
timezone; they display what time and date it was for the
person who created the changeset.)</p></li><li><p id="x_21"><a name="x_21"></a><code class="literal">summary</code>: The first line of
the text message that the creator of the changeset entered
to describe the changeset.</p></li><li><p id="x_67d"><a name="x_67d"></a>Some changesets, such as the first in the list above,
have a <code class="literal">tag</code> field. A tag is another way
to identify a changeset, by giving it an easy-to-remember
name. (The tag named <code class="literal">tip</code> is special: it
always refers to the newest change in a repository.)</p></li></ul></div><p id="x_22"><a name="x_22"></a>The default output printed by <span class="command"><strong>hg log</strong></span> is purely a summary; it is
missing a lot of detail.</p><p id="x_23"><a name="x_23"></a><a class="xref" href="a-tour-of-mercurial-the-basics.html#fig:tour-basic:history" title="Figure 2.1. Graphical history of the hello repository">Figure 2.1, “Graphical history of the hello repository”</a> provides
a graphical representation of the history of the <code class="filename">hello</code> repository, to make it a
little easier to see which direction history is
<span class="quote">flowing</span>” in. We'll be returning to this figure
several times in this chapter and the chapter that
follows.</p><div class="figure"><a name="fig:tour-basic:history"></a><p class="title"><b>Figure 2.1. Graphical history of the <code class="filename">hello</code> repository</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/tour-history.png" alt="XXX add text"></div></div></div><br class="figure-break"><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id345833">Changesets, revisions, and talking to other
people</h3></div></div></div><p id="x_25"><a name="x_25"></a>As English is a notoriously sloppy language, and computer
science has a hallowed history of terminological confusion
(why use one term when four will do?), revision control has a
variety of words and phrases that mean the same thing. If you
are talking about Mercurial history with other people, you
will find that the word “<span class="quote">changeset</span>” is often
compressed to “<span class="quote">change</span>” or (when written)
<span class="quote">cset</span>”, and sometimes a changeset is referred to
as a “<span class="quote">revision</span>” or a “<span class="quote">rev</span>”.</p><p id="x_26"><a name="x_26"></a>While it doesn't matter what <span class="emphasis"><em>word</em></span> you
use to refer to the concept of “<span class="quote">a changeset</span>”, the
<span class="emphasis"><em>identifier</em></span> that you use to refer to
<span class="quote">a <span class="emphasis"><em>specific</em></span> changeset</span>” is of
great importance. Recall that the <code class="literal">changeset</code>
field in the output from <span class="command"><strong>hg
log</strong></span> identifies a changeset using both a number and
a hexadecimal string.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_27"><a name="x_27"></a>The revision number is a handy
notation that is <span class="emphasis"><em>only valid in that
repository</em></span>.</p></li><li><p id="x_28"><a name="x_28"></a>The hexadecimal string is the
<span class="emphasis"><em>permanent, unchanging identifier</em></span> that
will always identify that exact changeset in
<span class="emphasis"><em>every</em></span> copy of the
repository.</p></li></ul></div><p id="x_29"><a name="x_29"></a>This distinction is important. If you send
someone an email talking about “<span class="quote">revision 33</span>”,
there's a high likelihood that their revision 33 will
<span class="emphasis"><em>not be the same</em></span> as yours. The reason for
this is that a revision number depends on the order in which
changes arrived in a repository, and there is no guarantee
that the same changes will happen in the same order in
different repositories. Three changes <code class="literal">a,b,c</code>
can easily appear in one repository as
<code class="literal">0,1,2</code>, while in another as
<code class="literal">0,2,1</code>.</p><p id="x_2a"><a name="x_2a"></a>Mercurial uses revision numbers purely as a convenient
shorthand. If you need to discuss a changeset with someone,
or make a record of a changeset for some other reason (for
example, in a bug report), use the hexadecimal
identifier.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id345980">Viewing specific revisions</h3></div></div></div><p id="x_2b"><a name="x_2b"></a>To narrow the output of <span class="command"><strong>hg
log</strong></span> down to a single revision, use the <code class="option">-r</code> (or <code class="option">--rev</code>) option. You can use
either a revision number or a hexadecimal identifier,
and you can provide as many revisions as you want.</p><pre id="id346352" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r 3</code></strong>
changeset: 3:0272e0d5a517
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:08:02 2008 +0200
summary: Get make to generate the final binary from a .o file.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r 0272e0d5a517</code></strong>
changeset: 3:0272e0d5a517
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:08:02 2008 +0200
summary: Get make to generate the final binary from a .o file.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r 1 -r 4</code></strong>
changeset: 1:82e55d328c8c
user: mpm@selenic.com
date: Fri Aug 26 01:21:28 2005 -0700
summary: Create a makefile
changeset: 4:2278160e78d4
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:16:53 2008 +0200
summary: Trim comments.
</pre><p id="x_2c"><a name="x_2c"></a>If you want to see the history of several revisions
without having to list each one, you can use <span class="emphasis"><em>range
notation</em></span>; this lets you express the idea “<span class="quote">I
want all revisions between <code class="literal">abc</code> and
<code class="literal">def</code>, inclusive</span>”.</p><pre id="id346245" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r 2:4</code></strong>
changeset: 2:fef857204a0c
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:05:04 2008 +0200
summary: Introduce a typo into hello.c.
changeset: 3:0272e0d5a517
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:08:02 2008 +0200
summary: Get make to generate the final binary from a .o file.
changeset: 4:2278160e78d4
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:16:53 2008 +0200
summary: Trim comments.
</pre><p id="x_2d"><a name="x_2d"></a>Mercurial also honours the order in which you specify
revisions, so <span class="command"><strong>hg log -r 2:4</strong></span>
prints 2, 3, and 4. while <span class="command"><strong>hg log -r
4:2</strong></span> prints 4, 3, and 2.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id346082">More detailed information</h3></div></div></div><p id="x_2e"><a name="x_2e"></a>While the summary information printed by <span class="command"><strong>hg log</strong></span> is useful if you already know
what you're looking for, you may need to see a complete
description of the change, or a list of the files changed, if
you're trying to decide whether a changeset is the one you're
looking for. The <span class="command"><strong>hg log</strong></span>
command's <code class="option">-v</code> (or <code class="option">--verbose</code>) option gives you
this extra detail.</p><pre id="id346186" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -v -r 3</code></strong>
changeset: 3:0272e0d5a517
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:08:02 2008 +0200
files: Makefile
description:
Get make to generate the final binary from a .o file.
</pre><p id="x_2f"><a name="x_2f"></a>If you want to see both the description and
content of a change, add the <code class="option">-p</code> (or <code class="option">--patch</code>) option. This displays
the content of a change as a <span class="emphasis"><em>unified diff</em></span>
(if you've never seen a unified diff before, see <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:patch" title="Understanding patches">the section called “Understanding patches”</a> for an overview).</p><pre id="id346230" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -v -p -r 2</code></strong>
changeset: 2:fef857204a0c
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:05:04 2008 +0200
files: hello.c
description:
Introduce a typo into hello.c.
diff -r 82e55d328c8c -r fef857204a0c hello.c
--- a/hello.c Fri Aug 26 01:21:28 2005 -0700
+++ b/hello.c Sat Aug 16 22:05:04 2008 +0200
@@ -11,6 +11,6 @@
int main(int argc, char **argv)
{
- printf("hello, world!\n");
+ printf("hello, world!\");
return 0;
}
</pre><p id="x_67e"><a name="x_67e"></a>The <code class="option">-p</code> option is
tremendously useful, so it's well worth remembering.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id346408">All about command options</h2></div></div></div><p id="x_30"><a name="x_30"></a>Let's take a brief break from exploring Mercurial commands
to discuss a pattern in the way that they work; you may find
this useful to keep in mind as we continue our tour.</p><p id="x_31"><a name="x_31"></a>Mercurial has a consistent and straightforward approach to
dealing with the options that you can pass to commands. It
follows the conventions for options that are common to modern
Linux and Unix systems.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_32"><a name="x_32"></a>Every option has a long name. For example, as
we've already seen, the <span class="command"><strong>hg
log</strong></span> command accepts a <code class="option">--rev</code> option.</p></li><li><p id="x_33"><a name="x_33"></a>Most options have short names, too. Instead
of <code class="option">--rev</code>, we can use
<code class="option">-r</code>. (The reason that
some options don't have short names is that the options in
question are rarely used.)</p></li><li><p id="x_34"><a name="x_34"></a>Long options start with two dashes (e.g.
<code class="option">--rev</code>), while short
options start with one (e.g. <code class="option">-r</code>).</p></li><li><p id="x_35"><a name="x_35"></a>Option naming and usage is consistent across
commands. For example, every command that lets you specify
a changeset ID or revision number accepts both <code class="option">-r</code> and <code class="option">--rev</code> arguments.</p></li><li><p id="x_67f"><a name="x_67f"></a>If you are using short options, you can save typing by
running them together. For example, the command <span class="command"><strong>hg log -v -p -r 2</strong></span> can be written
as <span class="command"><strong>hg log -vpr2</strong></span>.</p></li></ul></div><p id="x_36"><a name="x_36"></a>In the examples throughout this book, I usually
use short options instead of long. This simply reflects my own
preference, so don't read anything significant into it.</p><p id="x_37"><a name="x_37"></a>Most commands that print output of some kind will print more
output when passed a <code class="option">-v</code>
(or <code class="option">--verbose</code>) option, and
less when passed <code class="option">-q</code> (or
<code class="option">--quiet</code>).</p><div class="note"><table border="0" summary="Note: Option naming consistency"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Option naming consistency</th></tr><tr><td align="left" valign="top"><p id="x_680"><a name="x_680"></a>Almost always, Mercurial commands use consistent option
names to refer to the same concepts. For instance, if a
command deals with changesets, you'll always identify them
with <code class="option">--rev</code> or <code class="option">-r</code>. This consistent use of
option names makes it easier to remember what options a
particular command takes.</p></td></tr></table></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id346595">Making and reviewing changes</h2></div></div></div><p id="x_38"><a name="x_38"></a>Now that we have a grasp of viewing history in Mercurial,
let's take a look at making some changes and examining
them.</p><p id="x_39"><a name="x_39"></a>The first thing we'll do is isolate our experiment in a
repository of its own. We use the <span class="command"><strong>hg
clone</strong></span> command, but we don't need to clone a copy of
the remote repository. Since we already have a copy of it
locally, we can just clone that instead. This is much faster
than cloning over the network, and cloning a local repository
uses less disk space in most cases, too<sup>[<a name="id346621" href="#ftn.id346621" class="footnote">1</a>]</sup>.</p><pre id="id344876" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone hello my-hello</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd my-hello</code></strong>
</pre><p id="x_3a"><a name="x_3a"></a>As an aside, it's often good practice to keep a
<span class="quote">pristine</span>” copy of a remote repository around,
which you can then make temporary clones of to create sandboxes
for each task you want to work on. This lets you work on
multiple tasks in parallel, each isolated from the others until
it's complete and you're ready to integrate it back. Because
local clones are so cheap, there's almost no overhead to cloning
and destroying repositories whenever you want.</p><p id="x_3b"><a name="x_3b"></a>In our <code class="filename">my-hello</code>
repository, we have a file <code class="filename">hello.c</code> that
contains the classic “<span class="quote">hello, world</span>” program.</p><pre id="id347024" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat hello.c</code></strong>
/*
* Placed in the public domain by Bryan O'Sullivan. This program is
* not covered by patents in the United States or other countries.
*/
#include &lt;stdio.h&gt;
int main(int argc, char **argv)
{
printf("hello, world!\");
return 0;
}
</pre><p id="x_682"><a name="x_682"></a>Let's edit this file so that it prints a second line of
output.</p><pre id="id346984" class="screen"># ... edit edit edit ...
<code class="prompt">$</code> <strong class="userinput"><code>cat hello.c</code></strong>
/*
* Placed in the public domain by Bryan O'Sullivan. This program is
* not covered by patents in the United States or other countries.
*/
#include &lt;stdio.h&gt;
int main(int argc, char **argv)
{
printf("hello, world!\");
printf("hello again!\n");
return 0;
}
</pre><p id="x_3c"><a name="x_3c"></a>Mercurial's <span class="command"><strong>hg status</strong></span>
command will tell us what Mercurial knows about the files in the
repository.</p><pre id="id346930" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>ls</code></strong>
Makefile hello.c
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
M hello.c
</pre><p id="x_3d"><a name="x_3d"></a>The <span class="command"><strong>hg status</strong></span> command
prints no output for some files, but a line starting with
<span class="quote"><code class="literal">M</code></span>” for
<code class="filename">hello.c</code>. Unless you tell it to, <span class="command"><strong>hg status</strong></span> will not print any output
for files that have not been modified.</p><p id="x_3e"><a name="x_3e"></a>The “<span class="quote"><code class="literal">M</code></span>” indicates that
Mercurial has noticed that we modified
<code class="filename">hello.c</code>. We didn't need to
<span class="emphasis"><em>inform</em></span> Mercurial that we were going to
modify the file before we started, or that we had modified the
file after we were done; it was able to figure this out
itself.</p><p id="x_3f"><a name="x_3f"></a>It's somewhat helpful to know that we've modified
<code class="filename">hello.c</code>, but we might prefer to know
exactly <span class="emphasis"><em>what</em></span> changes we've made to it. To
do this, we use the <span class="command"><strong>hg diff</strong></span>
command.</p><pre id="id347442" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg diff</code></strong>
diff -r 2278160e78d4 hello.c
--- a/hello.c Sat Aug 16 22:16:53 2008 +0200
+++ b/hello.c Tue May 05 06:55:53 2009 +0000
@@ -8,5 +8,6 @@
int main(int argc, char **argv)
{
printf("hello, world!\");
+ printf("hello again!\n");
return 0;
}
</pre><div class="tip"><table border="0" summary="Tip: Understanding patches"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Understanding patches</th></tr><tr><td align="left" valign="top"><p id="x_683"><a name="x_683"></a>Remember to take a look at <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:patch" title="Understanding patches">the section called “Understanding patches”</a> if you don't know how to read
output above.</p></td></tr></table></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id347157">Recording changes in a new changeset</h2></div></div></div><p id="x_40"><a name="x_40"></a>We can modify files, build and test our changes, and use
<span class="command"><strong>hg status</strong></span> and <span class="command"><strong>hg diff</strong></span> to review our changes, until
we're satisfied with what we've done and arrive at a natural
stopping point where we want to record our work in a new
changeset.</p><p id="x_41"><a name="x_41"></a>The <span class="command"><strong>hg commit</strong></span> command lets
us create a new changeset; we'll usually refer to this as
<span class="quote">making a commit</span>” or
<span class="quote">committing</span>”.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id347208">Setting up a username</h3></div></div></div><p id="x_42"><a name="x_42"></a>When you try to run <span class="command"><strong>hg
commit</strong></span> for the first time, it is not guaranteed to
succeed. Mercurial records your name and address with each
change that you commit, so that you and others will later be
able to tell who made each change. Mercurial tries to
automatically figure out a sensible username to commit the
change with. It will attempt each of the following methods,
in order:</p><div class="orderedlist"><ol type="1"><li><p id="x_43"><a name="x_43"></a>If you specify a <code class="option">-u</code> option to the <span class="command"><strong>hg commit</strong></span> command on the command
line, followed by a username, this is always given the
highest precedence.</p></li><li><p id="x_44"><a name="x_44"></a>If you have set the <code class="envar">HGUSER</code>
environment variable, this is checked
next.</p></li><li><p id="x_45"><a name="x_45"></a>If you create a file in your home
directory called <code class="filename">.hgrc</code>, with a <code class="envar">username</code> entry, that will be
used next. To see what the contents of this file should
look like, refer to <a class="xref" href="a-tour-of-mercurial-the-basics.html#sec:tour-basic:username" title="Creating a Mercurial configuration file">the section called “Creating a Mercurial configuration file”</a>
below.</p></li><li><p id="x_46"><a name="x_46"></a>If you have set the <code class="envar">EMAIL</code>
environment variable, this will be used
next.</p></li><li><p id="x_47"><a name="x_47"></a>Mercurial will query your system to find out
your local user name and host name, and construct a
username from these components. Since this often results
in a username that is not very useful, it will print a
warning if it has to do
this.</p></li></ol></div><p id="x_48"><a name="x_48"></a>If all of these mechanisms fail, Mercurial will
fail, printing an error message. In this case, it will not
let you commit until you set up a
username.</p><p id="x_49"><a name="x_49"></a>You should think of the <code class="envar">HGUSER</code> environment
variable and the <code class="option">-u</code>
option to the <span class="command"><strong>hg commit</strong></span>
command as ways to <span class="emphasis"><em>override</em></span> Mercurial's
default selection of username. For normal use, the simplest
and most robust way to set a username for yourself is by
creating a <code class="filename">.hgrc</code> file; see
below for details.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="sec:tour-basic:username">Creating a Mercurial configuration file</h4></div></div></div><p id="x_4a"><a name="x_4a"></a>To set a user name, use your favorite editor
to create a file called <code class="filename">.hgrc</code> in your home directory.
Mercurial will use this file to look up your personalised
configuration settings. The initial contents of your
<code class="filename">.hgrc</code> should look like
this.</p><div class="tip"><table border="0" summary="Tip: Home directory on Windows"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Home directory on Windows</th></tr><tr><td align="left" valign="top"><p id="x_716"><a name="x_716"></a>When we refer to your home directory, on an English
language installation of Windows this will usually be a
folder named after your user name in
<code class="filename">C:\Documents and Settings</code>. You can
find out the exact name of your home directory by opening
a command prompt window and running the following
command.</p><pre id="id347422" class="screen"><code class="prompt">C:\&gt;</code> <strong class="userinput"><code>echo %UserProfile%</code></strong></pre></td></tr></table></div><pre id="id347447" class="programlisting"># This is a Mercurial configuration file.
[ui]
username = Firstname Lastname &lt;email.address@example.net&gt;</pre><p id="x_4b"><a name="x_4b"></a>The “<span class="quote"><code class="literal">[ui]</code></span>” line begins a
<span class="emphasis"><em>section</em></span> of the config file, so you can
read the “<span class="quote"><code class="literal">username = ...</code></span>
line as meaning “<span class="quote">set the value of the
<code class="literal">username</code> item in the
<code class="literal">ui</code> section</span>”. A section continues
until a new section begins, or the end of the file.
Mercurial ignores empty lines and treats any text from
<span class="quote"><code class="literal">#</code></span>” to the end of a line as
a comment.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id347496">Choosing a user name</h4></div></div></div><p id="x_4c"><a name="x_4c"></a>You can use any text you like as the value of
the <code class="literal">username</code> config item, since this
information is for reading by other people, but will not be
interpreted by Mercurial. The convention that most people
follow is to use their name and email address, as in the
example above.</p><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_4d"><a name="x_4d"></a>Mercurial's built-in web server obfuscates
email addresses, to make it more difficult for the email
harvesting tools that spammers use. This reduces the
likelihood that you'll start receiving more junk email if
you publish a Mercurial repository on the
web.</p></td></tr></table></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id347526">Writing a commit message</h3></div></div></div><p id="x_4e"><a name="x_4e"></a>When we commit a change, Mercurial drops us into
a text editor, to enter a message that will describe the
modifications we've made in this changeset. This is called
the <span class="emphasis"><em>commit message</em></span>. It will be a record
for readers of what we did and why, and it will be printed by
<span class="command"><strong>hg log</strong></span> after we've finished
committing.</p><pre id="id347893" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg commit</code></strong>
</pre><p id="x_4f"><a name="x_4f"></a>The editor that the <span class="command"><strong>hg
commit</strong></span> command drops us into will contain an empty
line or two, followed by a number of lines starting with
<span class="quote"><code class="literal">HG:</code></span>”.</p><pre id="id347851" class="programlisting">
This is where I type my commit comment.
HG: Enter commit message. Lines beginning with 'HG:' are removed.
HG: --
HG: user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
HG: branch 'default'
HG: changed hello.c</pre><p id="x_50"><a name="x_50"></a>Mercurial ignores the lines that start with
<span class="quote"><code class="literal">HG:</code></span>”; it uses them only to
tell us which files it's recording changes to. Modifying or
deleting these lines has no effect.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id347874">Writing a good commit message</h3></div></div></div><p id="x_51"><a name="x_51"></a>Since <span class="command"><strong>hg log</strong></span>
only prints the first line of a commit message by default,
it's best to write a commit message whose first line stands
alone. Here's a real example of a commit message that
<span class="emphasis"><em>doesn't</em></span> follow this guideline, and hence
has a summary that is not readable.</p><pre id="id347584" class="programlisting">
changeset: 73:584af0e231be
user: Censored Person &lt;censored.person@example.org&gt;
date: Tue Sep 26 21:37:07 2006 -0700
summary: include buildmeister/commondefs. Add exports.</pre><p id="x_52"><a name="x_52"></a>As far as the remainder of the contents of the
commit message are concerned, there are no hard-and-fast
rules. Mercurial itself doesn't interpret or care about the
contents of the commit message, though your project may have
policies that dictate a certain kind of formatting.</p><p id="x_53"><a name="x_53"></a>My personal preference is for short, but
informative, commit messages that tell me something that I
can't figure out with a quick glance at the output of <span class="command"><strong>hg log --patch</strong></span>.</p><p id="x_55"><a name="x_55"></a>If we run the <span class="command"><strong>hg
commit</strong></span> command without any arguments, it records
all of the changes we've made, as reported by <span class="command"><strong>hg status</strong></span> and <span class="command"><strong>hg diff</strong></span>.</p><div class="note"><table border="0" summary="Note: A surprise for Subversion users"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">A surprise for Subversion users</th></tr><tr><td align="left" valign="top"><p id="x_717"><a name="x_717"></a>Like other Mercurial commands, if we don't supply
explicit names to commit to the <span class="command"><strong>hg
commit</strong></span>, it will operate across a repository's
entire working directory. Be wary of this if you're coming
from the Subversion or CVS world, since you might expect it
to operate only on the current directory that you happen to
be visiting and its subdirectories.</p></td></tr></table></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id347674">Aborting a commit</h3></div></div></div><p id="x_54"><a name="x_54"></a>If you decide that you don't want to commit
while in the middle of editing a commit message, simply exit
from your editor without saving the file that it's editing.
This will cause nothing to happen to either the repository or
the working directory.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id347689">Admiring our new handiwork</h3></div></div></div><p id="x_56"><a name="x_56"></a>Once we've finished the commit, we can use the
<span class="command"><strong>hg tip</strong></span> command to display the
changeset we just created. This command produces output that
is identical to <span class="command"><strong>hg log</strong></span>, but
it only displays the newest revision in the repository.</p><pre id="id347781" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tip -vp</code></strong>
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
files: hello.c
description:
Added an extra line of output
diff -r 2278160e78d4 -r b6fed4f21233 hello.c
--- a/hello.c Sat Aug 16 22:16:53 2008 +0200
+++ b/hello.c Tue May 05 06:55:53 2009 +0000
@@ -8,5 +8,6 @@
int main(int argc, char **argv)
{
printf("hello, world!\");
+ printf("hello again!\n");
return 0;
}
</pre><p id="x_57"><a name="x_57"></a>We refer to the newest revision in the
repository as the <span class="emphasis"><em>tip revision</em></span>, or simply
the <span class="emphasis"><em>tip</em></span>.</p><p id="x_684"><a name="x_684"></a>By the way, the <span class="command"><strong>hg tip</strong></span>
command accepts many of the same options as <span class="command"><strong>hg log</strong></span>, so <code class="option">-v</code> above indicates “<span class="quote">be
verbose</span>”, <code class="option">-p</code>
specifies “<span class="quote">print a patch</span>”. The use of <code class="option">-p</code> to print patches is another
example of the consistent naming we mentioned earlier.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id347917">Sharing changes</h2></div></div></div><p id="x_58"><a name="x_58"></a>We mentioned earlier that repositories in
Mercurial are self-contained. This means that the changeset we
just created exists only in our <code class="filename">my-hello</code> repository. Let's look
at a few ways that we can propagate this change into other
repositories.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:tour:pull">Pulling changes from another repository</h3></div></div></div><p id="x_59"><a name="x_59"></a>To get started, let's clone our original
<code class="filename">hello</code> repository, which
does not contain the change we just committed. We'll call our
temporary repository <code class="filename">hello-pull</code>.</p><pre id="id348308" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone hello hello-pull</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_5a"><a name="x_5a"></a>We'll use the <span class="command"><strong>hg
pull</strong></span> command to bring changes from <code class="filename">my-hello</code> into <code class="filename">hello-pull</code>. However, blindly
pulling unknown changes into a repository is a somewhat scary
prospect. Mercurial provides the <span class="command"><strong>hg
incoming</strong></span> command to tell us what changes the
<span class="command"><strong>hg pull</strong></span> command
<span class="emphasis"><em>would</em></span> pull into the repository, without
actually pulling the changes in.</p><pre id="id348276" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd hello-pull</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg incoming ../my-hello</code></strong>
comparing with ../my-hello
searching for changes
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_5c"><a name="x_5c"></a>Bringing changes into a repository is a simple
matter of running the <span class="command"><strong>hg pull</strong></span>
command, and optionally telling it which repository to pull from.</p><pre id="id348143" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 4:2278160e78d4
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:16:53 2008 +0200
summary: Trim comments.
<code class="prompt">$</code> <strong class="userinput"><code>hg pull ../my-hello</code></strong>
pulling from ../my-hello
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_5d"><a name="x_5d"></a>As you can see from the before-and-after output
of <span class="command"><strong>hg tip</strong></span>, we have
successfully pulled changes into our repository. However,
Mercurial separates pulling changes in from updating the
working directory. There remains one step before we will see
the changes that we just pulled appear in the working
directory.</p><div class="tip"><table border="0" summary="Tip: Pulling specific changes"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Pulling specific changes</th></tr><tr><td align="left" valign="top"><p id="x_5b"><a name="x_5b"></a>It is possible that due to the delay between
running <span class="command"><strong>hg incoming</strong></span> and
<span class="command"><strong>hg pull</strong></span>, you may not see
all changesets that will be brought from the other
repository. Suppose you're pulling changes from a repository
on the network somewhere. While you are looking at the
<span class="command"><strong>hg incoming</strong></span> output, and
before you pull those changes, someone might have committed
something in the remote repository. This means that it's
possible to pull more changes than you saw when using
<span class="command"><strong>hg incoming</strong></span>.</p><p id="x_718"><a name="x_718"></a>If you only want to pull precisely the changes that were
listed by <span class="command"><strong>hg incoming</strong></span>, or
you have some other reason to pull a subset of changes,
simply identify the change that you want to pull by its
changeset ID, e.g. <span class="command"><strong>hg pull
-r7e95bb</strong></span>.</p></td></tr></table></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id348343">Updating the working directory</h3></div></div></div><p id="x_5e"><a name="x_5e"></a>We have so far glossed over the relationship
between a repository and its working directory. The <span class="command"><strong>hg pull</strong></span> command that we ran in
<a class="xref" href="a-tour-of-mercurial-the-basics.html#sec:tour:pull" title="Pulling changes from another repository">the section called “Pulling changes from another repository”</a> brought changes into the
repository, but if we check, there's no sign of those changes
in the working directory. This is because <span class="command"><strong>hg pull</strong></span> does not (by default) touch
the working directory. Instead, we use the <span class="command"><strong>hg update</strong></span> command to do this.</p><pre id="id348753" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>grep printf hello.c</code></strong>
printf("hello, world!\");
<code class="prompt">$</code> <strong class="userinput"><code>hg update tip</code></strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>grep printf hello.c</code></strong>
printf("hello, world!\");
printf("hello again!\n");
</pre><p id="x_5f"><a name="x_5f"></a>It might seem a bit strange that <span class="command"><strong>hg pull</strong></span> doesn't update the working
directory automatically. There's actually a good reason for
this: you can use <span class="command"><strong>hg update</strong></span>
to update the working directory to the state it was in at
<span class="emphasis"><em>any revision</em></span> in the history of the
repository. If you had the working directory updated to an
old revision—to hunt down the origin of a bug,
say—and ran a <span class="command"><strong>hg pull</strong></span>
which automatically updated the working directory to a new
revision, you might not be terribly happy.</p><p id="x_60"><a name="x_60"></a>Since pull-then-update is such a common sequence
of operations, Mercurial lets you combine the two by passing
the <code class="option">-u</code> option to <span class="command"><strong>hg pull</strong></span>.</p><p id="x_61"><a name="x_61"></a>If you look back at the output of <span class="command"><strong>hg pull</strong></span> in <a class="xref" href="a-tour-of-mercurial-the-basics.html#sec:tour:pull" title="Pulling changes from another repository">the section called “Pulling changes from another repository”</a> when we ran it without <code class="option">-u</code>, you can see that it printed
a helpful reminder that we'd have to take an explicit step to
update the working directory.</p><p id="x_62"><a name="x_62"></a>To find out what revision the working directory
is at, use the <span class="command"><strong>hg parents</strong></span>
command.</p><pre id="id348724" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_63"><a name="x_63"></a>If you look back at <a class="xref" href="a-tour-of-mercurial-the-basics.html#fig:tour-basic:history" title="Figure 2.1. Graphical history of the hello repository">Figure 2.1, “Graphical history of the hello repository”</a>, you'll see arrows
connecting each changeset. The node that the arrow leads
<span class="emphasis"><em>from</em></span> in each case is a parent, and the
node that the arrow leads <span class="emphasis"><em>to</em></span> is its
child. The working directory has a parent in just the same
way; this is the changeset that the working directory
currently contains.</p><p id="x_64"><a name="x_64"></a>To update the working directory to a particular
revision, give a revision number or changeset ID to the
<span class="command"><strong>hg update</strong></span> command.</p><pre id="id348699" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg update 2</code></strong>
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 2:fef857204a0c
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Sat Aug 16 22:05:04 2008 +0200
summary: Introduce a typo into hello.c.
<code class="prompt">$</code> <strong class="userinput"><code>hg update</code></strong>
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_65"><a name="x_65"></a>If you omit an explicit revision, <span class="command"><strong>hg update</strong></span> will update to the tip
revision, as shown by the second call to <span class="command"><strong>hg update</strong></span> in the example
above.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id348825">Pushing changes to another repository</h3></div></div></div><p id="x_66"><a name="x_66"></a>Mercurial lets us push changes to another
repository, from the repository we're currently visiting. As
with the example of <span class="command"><strong>hg pull</strong></span>
above, we'll create a temporary repository to push our changes
into.</p><pre id="id349042" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone hello hello-push</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_67"><a name="x_67"></a>The <span class="command"><strong>hg outgoing</strong></span>
command tells us what changes would be pushed into another
repository.</p><pre id="id348976" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd my-hello</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg outgoing ../hello-push</code></strong>
comparing with ../hello-push
searching for changes
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_68"><a name="x_68"></a>And the <span class="command"><strong>hg push</strong></span>
command does the actual push.</p><pre id="id349027" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg push ../hello-push</code></strong>
pushing to ../hello-push
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
</pre><p id="x_69"><a name="x_69"></a>As with <span class="command"><strong>hg
pull</strong></span>, the <span class="command"><strong>hg push</strong></span>
command does not update the working directory in the
repository that it's pushing changes into. Unlike <span class="command"><strong>hg pull</strong></span>, <span class="command"><strong>hg
push</strong></span> does not provide a <code class="literal">-u</code>
option that updates the other repository's working directory.
This asymmetry is deliberate: the repository we're pushing to
might be on a remote server and shared between several people.
If we were to update its working directory while someone was
working in it, their work would be disrupted.</p><p id="x_6a"><a name="x_6a"></a>What happens if we try to pull or push changes
and the receiving repository already has those changes?
Nothing too exciting.</p><pre id="id349466" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg push ../hello-push</code></strong>
pushing to ../hello-push
searching for changes
no changes found
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id349161">Default locations</h3></div></div></div><p id="x_719"><a name="x_719"></a>When we clone a repository, Mercurial records the location
of the repository we cloned in the
<code class="filename">.hg/hgrc</code> file of the new repository. If
we don't supply a location to <span class="command"><strong>hg pull</strong></span> from
or <span class="command"><strong>hg push</strong></span> to, those commands will use this
location as a default. The <span class="command"><strong>hg incoming</strong></span>
and <span class="command"><strong>hg outgoing</strong></span> commands do so too.</p><p id="x_71a"><a name="x_71a"></a>If you open a repository's <code class="filename">.hg/hgrc</code>
file in a text editor, you will see contents like the
following.</p><pre id="id349215" class="programlisting">[paths]
default = http://www.selenic.com/repo/hg</pre><p id="x_71b"><a name="x_71b"></a>It is possible—and often useful—to have the
default location for <span class="command"><strong>hg push</strong></span> and
<span class="command"><strong>hg outgoing</strong></span> be different from those for
<span class="command"><strong>hg pull</strong></span> and <span class="command"><strong>hg incoming</strong></span>.
We can do this by adding a <code class="literal">default-push</code>
entry to the <code class="literal">[paths]</code> section of the
<code class="filename">.hg/hgrc</code> file, as follows.</p><pre id="id349269" class="programlisting">[paths]
default = http://www.selenic.com/repo/hg
default-push = http://hg.example.com/hg</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id349277">Sharing changes over a network</h3></div></div></div><p id="x_6b"><a name="x_6b"></a>The commands we have covered in the previous few
sections are not limited to working with local repositories.
Each works in exactly the same fashion over a network
connection; simply pass in a URL instead of a local
path.</p><pre id="id349432" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg outgoing https://bitbucket.org/bos/hg-tutorial-hello</code></strong>
comparing with https://bitbucket.org/bos/hg-tutorial-hello
searching for changes
changeset: 5:b6fed4f21233
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:53 2009 +0000
summary: Added an extra line of output
</pre><p id="x_6c"><a name="x_6c"></a>In this example, we can see what changes we
could push to the remote repository, but the repository is
understandably not set up to let anonymous users push to
it.</p><pre id="id349340" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg push http://bitbucket.org/bos/hg-tutorial-hello</code></strong>
pushing to http://bitbucket.org/bos/hg-tutorial-hello
searching for changes
ssl required
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id349357">Starting a new project</h2></div></div></div><p id="x_71c"><a name="x_71c"></a>It is just as easy to begin a new project as to work on one
that already exists. The <span class="command"><strong>hg init</strong></span> command
creates a new, empty Mercurial repository.</p><pre id="id349764" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init myproject</code></strong>
</pre><p id="x_71d"><a name="x_71d"></a>This simply creates a repository named
<code class="filename">myproject</code> in the current directory.</p><pre id="id349756" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>ls -l</code></strong>
total 12
-rw-rw-r-- 1 bos bos 47 May 5 06:55 goodbye.c
-rw-rw-r-- 1 bos bos 45 May 5 06:55 hello.c
drwxrwxr-x 3 bos bos 4096 May 5 06:55 myproject
</pre><p id="x_71e"><a name="x_71e"></a>We can tell that <code class="filename">myproject</code> is a
Mercurial repository, because it contains a
<code class="filename">.hg</code> directory.</p><pre id="id349704" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>ls -al myproject</code></strong>
total 12
drwxrwxr-x 3 bos bos 4096 May 5 06:55 .
drwx------ 3 bos bos 4096 May 5 06:55 ..
drwxrwxr-x 3 bos bos 4096 May 5 06:55 .hg
</pre><p id="x_71f"><a name="x_71f"></a>If we want to add some pre-existing files to the repository,
we copy them into place, and tell Mercurial to start tracking
them using the <span class="command"><strong>hg add</strong></span> command.</p><pre id="id349672" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd myproject</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cp ../hello.c .</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cp ../goodbye.c .</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add</code></strong>
adding goodbye.c
adding hello.c
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
A goodbye.c
A hello.c
</pre><p id="x_720"><a name="x_720"></a>Once we are satisfied that our project looks right, we
commit our changes.</p><pre id="id349661" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Initial commit'</code></strong>
</pre><p id="x_721"><a name="x_721"></a>It takes just a few moments to start using Mercurial on a
new project, which is part of its appeal. Revision control is
now so easy to work with, we can use it on the smallest of
projects that we might not have considered with a more
complicated tool.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id346621" href="#id346621" class="para">1</a>] </sup>The saving of space arises when source and destination
repositories are on the same filesystem, in which case
Mercurial will use hardlinks to do copy-on-write sharing of
its internal metadata. If that explanation meant nothing to
you, don't worry: everything happens transparently and
automatically, and you don't need to understand it.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="how-did-we-get-here.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="a-tour-of-mercurial-merging-work.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 1. How did we get here? </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 3. A tour of Mercurial: merging work</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,335 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 14. Adding functionality with extensions</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="advanced-uses-of-mercurial-queues.html" title="Chapter 13. Advanced uses of Mercurial Queues"><link rel="next" href="migrating-to-mercurial.html" title="Appendix A. Migrating to Mercurial"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 14. Adding functionality with extensions</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="advanced-uses-of-mercurial-queues.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="migrating-to-mercurial.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:hgext"><div class="titlepage"><div><div><h2 class="title">Chapter 14. Adding functionality with extensions</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="adding-functionality-with-extensions.html#sec:hgext:inotify">Improve performance with the inotify extension</a></span></dt><dt><span class="sect1"><a href="adding-functionality-with-extensions.html#sec:hgext:extdiff">Flexible diff support with the extdiff extension</a></span></dt><dd><dl><dt><span class="sect2"><a href="adding-functionality-with-extensions.html#id439166">Defining command aliases</a></span></dt></dl></dd><dt><span class="sect1"><a href="adding-functionality-with-extensions.html#sec:hgext:transplant">Cherrypicking changes with the transplant extension</a></span></dt><dt><span class="sect1"><a href="adding-functionality-with-extensions.html#sec:hgext:patchbomb">Send changes via email with the patchbomb extension</a></span></dt><dd><dl><dt><span class="sect2"><a href="adding-functionality-with-extensions.html#id439402">Changing the behavior of patchbombs</a></span></dt></dl></dd></dl></div><p id="x_4fe"><a name="x_4fe"></a>While the core of Mercurial is quite complete from a
functionality standpoint, it's deliberately shorn of fancy
features. This approach of preserving simplicity keeps the
software easy to deal with for both maintainers and users.</p><p id="x_4ff"><a name="x_4ff"></a>However, Mercurial doesn't box you in with an inflexible
command set: you can add features to it as
<span class="emphasis"><em>extensions</em></span> (sometimes known as
<span class="emphasis"><em>plugins</em></span>). We've already discussed a few of
these extensions in earlier chapters.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_500"><a name="x_500"></a><a class="xref" href="a-tour-of-mercurial-merging-work.html#sec:tour-merge:fetch" title="Simplifying the pull-merge-commit sequence">the section called “Simplifying the pull-merge-commit sequence”</a>
covers the <code class="literal">fetch</code> extension;
this combines pulling new changes and merging them with local
changes into a single command, <span class="command"><strong>fetch</strong></span>.</p></li><li><p id="x_501"><a name="x_501"></a>In <a class="xref" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks">Chapter 10, <i>Handling repository events with hooks</i></a>, we covered
several extensions that are useful for hook-related
functionality: <code class="literal">acl</code> adds
access control lists; <code class="literal">bugzilla</code> adds integration with the
Bugzilla bug tracking system; and <code class="literal">notify</code> sends notification emails on
new changes.</p></li><li><p id="x_502"><a name="x_502"></a>The Mercurial Queues patch management extension is
so invaluable that it merits two chapters and an appendix all
to itself. <a class="xref" href="managing-change-with-mercurial-queues.html" title="Chapter 12. Managing change with Mercurial Queues">Chapter 12, <i>Managing change with Mercurial Queues</i></a> covers the
basics; <a class="xref" href="advanced-uses-of-mercurial-queues.html" title="Chapter 13. Advanced uses of Mercurial Queues">Chapter 13, <i>Advanced uses of Mercurial Queues</i></a> discusses advanced topics;
and <a class="xref" href="mercurial-queues-reference.html" title="Appendix B. Mercurial Queues reference">Appendix B, <i>Mercurial Queues reference</i></a> goes into detail on
each
command.</p></li></ul></div><p id="x_503"><a name="x_503"></a>In this chapter, we'll cover some of the other extensions that
are available for Mercurial, and briefly touch on some of the
machinery you'll need to know about if you want to write an
extension of your own.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_504"><a name="x_504"></a>In <a class="xref" href="adding-functionality-with-extensions.html#sec:hgext:inotify" title="Improve performance with the inotify extension">the section called “Improve performance with the inotify extension”</a>,
we'll discuss the possibility of <span class="emphasis"><em>huge</em></span>
performance improvements using the <code class="literal">inotify</code> extension.</p></li></ul></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:hgext:inotify">Improve performance with the <code class="literal">inotify</code> extension</h2></div></div></div><p id="x_505"><a name="x_505"></a>Are you interested in having some of the most common
Mercurial operations run as much as a hundred times faster?
Read on!</p><p id="x_506"><a name="x_506"></a>Mercurial has great performance under normal circumstances.
For example, when you run the <span class="command"><strong>hg
status</strong></span> command, Mercurial has to scan almost every
directory and file in your repository so that it can display
file status. Many other Mercurial commands need to do the same
work behind the scenes; for example, the <span class="command"><strong>hg diff</strong></span> command uses the status
machinery to avoid doing an expensive comparison operation on
files that obviously haven't changed.</p><p id="x_507"><a name="x_507"></a>Because obtaining file status is crucial to good
performance, the authors of Mercurial have optimised this code
to within an inch of its life. However, there's no avoiding the
fact that when you run <span class="command"><strong>hg
status</strong></span>, Mercurial is going to have to perform at
least one expensive system call for each managed file to
determine whether it's changed since the last time Mercurial
checked. For a sufficiently large repository, this can take a
long time.</p><p id="x_508"><a name="x_508"></a>To put a number on the magnitude of this effect, I created a
repository containing 150,000 managed files. I timed <span class="command"><strong>hg status</strong></span> as taking ten seconds to
run, even when <span class="emphasis"><em>none</em></span> of those files had been
modified.</p><p id="x_509"><a name="x_509"></a>Many modern operating systems contain a file notification
facility. If a program signs up to an appropriate service, the
operating system will notify it every time a file of interest is
created, modified, or deleted. On Linux systems, the kernel
component that does this is called
<code class="literal">inotify</code>.</p><p id="x_50a"><a name="x_50a"></a>Mercurial's <code class="literal">inotify</code>
extension talks to the kernel's <code class="literal">inotify</code>
component to optimise <span class="command"><strong>hg status</strong></span>
commands. The extension has two components. A daemon sits in
the background and receives notifications from the
<code class="literal">inotify</code> subsystem. It also listens for
connections from a regular Mercurial command. The extension
modifies Mercurial's behavior so that instead of scanning the
filesystem, it queries the daemon. Since the daemon has perfect
information about the state of the repository, it can respond
with a result instantaneously, avoiding the need to scan every
directory and file in the repository.</p><p id="x_50b"><a name="x_50b"></a>Recall the ten seconds that I measured plain Mercurial as
taking to run <span class="command"><strong>hg status</strong></span> on a
150,000 file repository. With the <code class="literal">inotify</code> extension enabled, the time
dropped to 0.1 seconds, a factor of <span class="emphasis"><em>one
hundred</em></span> faster.</p><p id="x_50c"><a name="x_50c"></a>Before we continue, please pay attention to some
caveats.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_50d"><a name="x_50d"></a>The <code class="literal">inotify</code>
extension is Linux-specific. Because it interfaces directly
to the Linux kernel's <code class="literal">inotify</code> subsystem,
it does not work on other operating systems.</p></li><li><p id="x_50e"><a name="x_50e"></a>It should work on any Linux distribution that
was released after early 2005. Older distributions are
likely to have a kernel that lacks
<code class="literal">inotify</code>, or a version of
<code class="literal">glibc</code> that does not have the necessary
interfacing support.</p></li><li><p id="x_50f"><a name="x_50f"></a>Not all filesystems are suitable for use with
the <code class="literal">inotify</code> extension.
Network filesystems such as NFS are a non-starter, for
example, particularly if you're running Mercurial on several
systems, all mounting the same network filesystem. The
kernel's <code class="literal">inotify</code> system has no way of
knowing about changes made on another system. Most local
filesystems (e.g. ext3, XFS, ReiserFS) should work
fine.</p></li></ul></div><p id="x_510"><a name="x_510"></a>The <code class="literal">inotify</code> extension is
not yet shipped with Mercurial as of May 2007, so it's a little
more involved to set up than other extensions. But the
performance improvement is worth it!</p><p id="x_511"><a name="x_511"></a>The extension currently comes in two parts: a set of patches
to the Mercurial source code, and a library of Python bindings
to the <code class="literal">inotify</code> subsystem.</p><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_512"><a name="x_512"></a> There are <span class="emphasis"><em>two</em></span> Python
<code class="literal">inotify</code> binding libraries. One of them is
called <code class="literal">pyinotify</code>, and is packaged by some
Linux distributions as <code class="literal">python-inotify</code>.
This is <span class="emphasis"><em>not</em></span> the one you'll need, as it is
too buggy and inefficient to be practical.</p></td></tr></table></div><p id="x_513"><a name="x_513"></a>To get going, it's best to already have a functioning copy
of Mercurial installed.</p><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_514"><a name="x_514"></a> If you follow the instructions below, you'll be
<span class="emphasis"><em>replacing</em></span> and overwriting any existing
installation of Mercurial that you might already have, using
the latest “<span class="quote">bleeding edge</span>” Mercurial code. Don't
say you weren't warned!</p></td></tr></table></div><div class="orderedlist"><ol type="1"><li><p id="x_515"><a name="x_515"></a>Clone the Python <code class="literal">inotify</code>
binding repository. Build and install it.</p><pre id="id438117" class="programlisting">hg clone http://hg.kublai.com/python/inotify
cd inotify
python setup.py build --force
sudo python setup.py install --skip-build</pre></li><li><p id="x_516"><a name="x_516"></a>Clone the <code class="filename">crew</code> Mercurial repository.
Clone the <code class="literal">inotify</code> patch
repository so that Mercurial Queues will be able to apply
patches to your cope of the <code class="filename">crew</code> repository.</p><pre id="id438158" class="programlisting">hg clone http://hg.intevation.org/mercurial/crew
hg clone crew inotify
hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</pre></li><li><p id="x_517"><a name="x_517"></a>Make sure that you have the Mercurial Queues
extension, <code class="literal">mq</code>, enabled. If
you've never used MQ, read <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:start" title="Getting started with Mercurial Queues">the section called “Getting started with Mercurial Queues”</a> to get started
quickly.</p></li><li><p id="x_518"><a name="x_518"></a>Go into the <code class="filename">inotify</code> repo, and apply all
of the <code class="literal">inotify</code> patches
using the <code class="option">hg
-a</code> option to the <span class="command"><strong>qpush</strong></span> command.</p><pre id="id438230" class="programlisting">cd inotify
hg qpush -a</pre></li><li><p id="x_519"><a name="x_519"></a> If you get an error message from <span class="command"><strong>qpush</strong></span>, you should not continue.
Instead, ask for help.</p></li><li><p id="x_51a"><a name="x_51a"></a>Build and install the patched version of
Mercurial.</p><pre id="id438263" class="programlisting">python setup.py build --force
sudo python setup.py install --skip-build</pre></li></ol></div><p id="x_51b"><a name="x_51b"></a>Once you've build a suitably patched version of Mercurial,
all you need to do to enable the <code class="literal">inotify</code> extension is add an entry to
your <code class="filename">~/.hgrc</code>.</p><pre id="id438295" class="programlisting">[extensions] inotify =</pre><p id="x_51c"><a name="x_51c"></a>When the <code class="literal">inotify</code> extension
is enabled, Mercurial will automatically and transparently start
the status daemon the first time you run a command that needs
status in a repository. It runs one status daemon per
repository.</p><p id="x_51d"><a name="x_51d"></a>The status daemon is started silently, and runs in the
background. If you look at a list of running processes after
you've enabled the <code class="literal">inotify</code>
extension and run a few commands in different repositories,
you'll thus see a few <code class="literal">hg</code> processes sitting
around, waiting for updates from the kernel and queries from
Mercurial.</p><p id="x_51e"><a name="x_51e"></a>The first time you run a Mercurial command in a repository
when you have the <code class="literal">inotify</code>
extension enabled, it will run with about the same performance
as a normal Mercurial command. This is because the status
daemon needs to perform a normal status scan so that it has a
baseline against which to apply later updates from the kernel.
However, <span class="emphasis"><em>every</em></span> subsequent command that does
any kind of status check should be noticeably faster on
repositories of even fairly modest size. Better yet, the bigger
your repository is, the greater a performance advantage you'll
see. The <code class="literal">inotify</code> daemon makes
status operations almost instantaneous on repositories of all
sizes!</p><p id="x_51f"><a name="x_51f"></a>If you like, you can manually start a status daemon using
the <span class="command"><strong>inserve</strong></span> command.
This gives you slightly finer control over how the daemon ought
to run. This command will of course only be available when the
<code class="literal">inotify</code> extension is
enabled.</p><p id="x_520"><a name="x_520"></a>When you're using the <code class="literal">inotify</code> extension, you should notice
<span class="emphasis"><em>no difference at all</em></span> in Mercurial's
behavior, with the sole exception of status-related commands
running a whole lot faster than they used to. You should
specifically expect that commands will not print different
output; neither should they give different results. If either of
these situations occurs, please report a bug.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:hgext:extdiff">Flexible diff support with the <code class="literal">extdiff</code> extension</h2></div></div></div><p id="x_521"><a name="x_521"></a>Mercurial's built-in <span class="command"><strong>hg
diff</strong></span> command outputs plaintext unified diffs.</p><pre id="id438805" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg diff</code></strong>
diff -r cfed5c378cc5 myfile
--- a/myfile Tue May 05 06:55:34 2009 +0000
+++ b/myfile Tue May 05 06:55:34 2009 +0000
@@ -1,1 +1,2 @@
The first line.
+The second line.
</pre><p id="x_522"><a name="x_522"></a>If you would like to use an external tool to display
modifications, you'll want to use the <code class="literal">extdiff</code> extension. This will let you
use, for example, a graphical diff tool.</p><p id="x_523"><a name="x_523"></a>The <code class="literal">extdiff</code> extension is
bundled with Mercurial, so it's easy to set up. In the <code class="literal">extensions</code> section of your
<code class="filename">~/.hgrc</code>, simply add a
one-line entry to enable the extension.</p><pre id="id438765" class="programlisting">[extensions]
extdiff =</pre><p id="x_524"><a name="x_524"></a>This introduces a command named <span class="command"><strong>extdiff</strong></span>, which by default uses
your system's <span class="command"><strong>diff</strong></span> command to generate a
unified diff in the same form as the built-in <span class="command"><strong>hg diff</strong></span> command.</p><pre id="id438707" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg extdiff</code></strong>
--- a.cfed5c378cc5/myfile 2009-05-05 06:55:34.000000000 +0000
+++ /tmp/extdiffXdA7FH/a/myfile 2009-05-05 06:55:34.000000000 +0000
@@ -1 +1,2 @@
The first line.
+The second line.
</pre><p id="x_525"><a name="x_525"></a>The result won't be exactly the same as with the built-in
<span class="command"><strong>hg diff</strong></span> variations, because the
output of <span class="command"><strong>diff</strong></span> varies from one system to
another, even when passed the same options.</p><p id="x_526"><a name="x_526"></a>As the “<span class="quote"><code class="literal">making snapshot</code></span>
lines of output above imply, the <span class="command"><strong>extdiff</strong></span> command works by
creating two snapshots of your source tree. The first snapshot
is of the source revision; the second, of the target revision or
working directory. The <span class="command"><strong>extdiff</strong></span> command generates
these snapshots in a temporary directory, passes the name of
each directory to an external diff viewer, then deletes the
temporary directory. For efficiency, it only snapshots the
directories and files that have changed between the two
revisions.</p><p id="x_527"><a name="x_527"></a>Snapshot directory names have the same base name as your
repository. If your repository path is <code class="filename">/quux/bar/foo</code>, then <code class="filename">foo</code> will be the name of each
snapshot directory. Each snapshot directory name has its
changeset ID appended, if appropriate. If a snapshot is of
revision <code class="literal">a631aca1083f</code>, the directory will be
named <code class="filename">foo.a631aca1083f</code>.
A snapshot of the working directory won't have a changeset ID
appended, so it would just be <code class="filename">foo</code> in this example. To see what
this looks like in practice, look again at the <span class="command"><strong>extdiff</strong></span> example above. Notice
that the diff has the snapshot directory names embedded in its
header.</p><p id="x_528"><a name="x_528"></a>The <span class="command"><strong>extdiff</strong></span> command
accepts two important options. The <code class="option">hg -p</code> option
lets you choose a program to view differences with, instead of
<span class="command"><strong>diff</strong></span>. With the <code class="option">hg -o</code> option,
you can change the options that <span class="command"><strong>extdiff</strong></span> passes to the program
(by default, these options are
<span class="quote"><code class="literal">-Npru</code></span>”, which only make sense
if you're running <span class="command"><strong>diff</strong></span>). In other respects,
the <span class="command"><strong>extdiff</strong></span> command
acts similarly to the built-in <span class="command"><strong>hg
diff</strong></span> command: you use the same option names, syntax,
and arguments to specify the revisions you want, the files you
want, and so on.</p><p id="x_529"><a name="x_529"></a>As an example, here's how to run the normal system
<span class="command"><strong>diff</strong></span> command, getting it to generate context
diffs (using the <code class="option">-c</code> option)
instead of unified diffs, and five lines of context instead of
the default three (passing <code class="literal">5</code> as the argument
to the <code class="option">-C</code> option).</p><pre id="id439206" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg extdiff -o -NprcC5</code></strong>
*** a.cfed5c378cc5/myfile Tue May 5 06:55:34 2009
--- /tmp/extdiffXdA7FH/a/myfile Tue May 5 06:55:34 2009
***************
*** 1 ****
--- 1,2 ----
The first line.
+ The second line.
</pre><p id="x_52a"><a name="x_52a"></a>Launching a visual diff tool is just as easy. Here's how to
launch the <span class="command"><strong>kdiff3</strong></span> viewer.</p><pre id="id439133" class="programlisting">hg extdiff -p kdiff3 -o</pre><p id="x_52b"><a name="x_52b"></a>If your diff viewing command can't deal with directories,
you can easily work around this with a little scripting. For an
example of such scripting in action with the <code class="literal">mq</code> extension and the
<span class="command"><strong>interdiff</strong></span> command, see <a class="xref" href="advanced-uses-of-mercurial-queues.html#mq-collab:tips:interdiff" title="Viewing the history of a patch">the section called “Viewing the history of a patch”</a>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id439166">Defining command aliases</h3></div></div></div><p id="x_52c"><a name="x_52c"></a>It can be cumbersome to remember the options to both the
<span class="command"><strong>extdiff</strong></span> command and
the diff viewer you want to use, so the <code class="literal">extdiff</code> extension lets you define
<span class="emphasis"><em>new</em></span> commands that will invoke your diff
viewer with exactly the right options.</p><p id="x_52d"><a name="x_52d"></a>All you need to do is edit your <code class="filename">~/.hgrc</code>, and add a section named
<code class="literal">extdiff</code>. Inside this
section, you can define multiple commands. Here's how to add
a <code class="literal">kdiff3</code> command. Once you've defined
this, you can type “<span class="quote"><code class="literal">hg kdiff3</code></span>
and the <code class="literal">extdiff</code> extension
will run <span class="command"><strong>kdiff3</strong></span> for you.</p><pre id="id438959" class="programlisting">[extdiff]
cmd.kdiff3 =</pre><p id="x_52e"><a name="x_52e"></a>If you leave the right hand side of the definition empty,
as above, the <code class="literal">extdiff</code>
extension uses the name of the command you defined as the name
of the external program to run. But these names don't have to
be the same. Here, we define a command named
<span class="quote"><code class="literal">hg wibble</code></span>”, which runs
<span class="command"><strong>kdiff3</strong></span>.</p><pre id="id438995" class="programlisting">[extdiff]
cmd.wibble = kdiff3</pre><p id="x_52f"><a name="x_52f"></a>You can also specify the default options that you want to
invoke your diff viewing program with. The prefix to use is
<span class="quote"><code class="literal">opts.</code></span>”, followed by the name
of the command to which the options apply. This example
defines a “<span class="quote"><code class="literal">hg vimdiff</code></span>” command
that runs the <span class="command"><strong>vim</strong></span> editor's
<code class="literal">DirDiff</code> extension.</p><pre id="id439036" class="programlisting">[extdiff]
cmd.vimdiff = vim
opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:hgext:transplant">Cherrypicking changes with the <code class="literal">transplant</code> extension</h2></div></div></div><p id="x_530"><a name="x_530"></a>Need to have a long chat with Brendan about this.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:hgext:patchbomb">Send changes via email with the <code class="literal">patchbomb</code> extension</h2></div></div></div><p id="x_531"><a name="x_531"></a>Many projects have a culture of “<span class="quote">change
review</span>”, in which people send their modifications to a
mailing list for others to read and comment on before they
commit the final version to a shared repository. Some projects
have people who act as gatekeepers; they apply changes from
other people to a repository to which those others don't have
access.</p><p id="x_532"><a name="x_532"></a>Mercurial makes it easy to send changes over email for
review or application, via its <code class="literal">patchbomb</code> extension. The extension is
so named because changes are formatted as patches, and it's usual
to send one changeset per email message. Sending a long series
of changes by email is thus much like “<span class="quote">bombing</span>” the
recipient's inbox, hence “<span class="quote">patchbomb</span>”.</p><p id="x_533"><a name="x_533"></a>As usual, the basic configuration of the <code class="literal">patchbomb</code> extension takes just one or
two lines in your <code class="filename">
/.hgrc</code>.</p><pre id="id439232" class="programlisting">[extensions]
patchbomb =</pre><p id="x_534"><a name="x_534"></a>Once you've enabled the extension, you will have a new
command available, named <span class="command"><strong>email</strong></span>.</p><p id="x_535"><a name="x_535"></a>The safest and best way to invoke the <span class="command"><strong>email</strong></span> command is to
<span class="emphasis"><em>always</em></span> run it first with the <code class="option">hg -n</code> option.
This will show you what the command <span class="emphasis"><em>would</em></span>
send, without actually sending anything. Once you've had a
quick glance over the changes and verified that you are sending
the right ones, you can rerun the same command, with the <code class="option">hg -n</code> option
removed.</p><p id="x_536"><a name="x_536"></a>The <span class="command"><strong>email</strong></span> command
accepts the same kind of revision syntax as every other
Mercurial command. For example, this command will send every
revision between 7 and <code class="literal">tip</code>, inclusive.</p><pre id="id439312" class="programlisting">hg email -n 7:tip</pre><p id="x_537"><a name="x_537"></a>You can also specify a <span class="emphasis"><em>repository</em></span> to
compare with. If you provide a repository but no revisions, the
<span class="command"><strong>email</strong></span> command will
send all revisions in the local repository that are not present
in the remote repository. If you additionally specify revisions
or a branch name (the latter using the <code class="option">hg -b</code> option),
this will constrain the revisions sent.</p><p id="x_538"><a name="x_538"></a>It's perfectly safe to run the <span class="command"><strong>email</strong></span> command without the
names of the people you want to send to: if you do this, it will
just prompt you for those values interactively. (If you're
using a Linux or Unix-like system, you should have enhanced
<code class="literal">readline</code>-style editing capabilities when
entering those headers, too, which is useful.)</p><p id="x_539"><a name="x_539"></a>When you are sending just one revision, the <span class="command"><strong>email</strong></span> command will by
default use the first line of the changeset description as the
subject of the single email message it sends.</p><p id="x_53a"><a name="x_53a"></a>If you send multiple revisions, the <span class="command"><strong>email</strong></span> command will usually
send one message per changeset. It will preface the series with
an introductory message, in which you should describe the
purpose of the series of changes you're sending.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id439402">Changing the behavior of patchbombs</h3></div></div></div><p id="x_53b"><a name="x_53b"></a>Not every project has exactly the same conventions for
sending changes in email; the <code class="literal">patchbomb</code> extension tries to
accommodate a number of variations through command line
options.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_53c"><a name="x_53c"></a>You can write a subject for the introductory
message on the command line using the <code class="option">hg -s</code>
option. This takes one argument, the text of the subject
to use.</p></li><li><p id="x_53d"><a name="x_53d"></a>To change the email address from which the
messages originate, use the <code class="option">hg -f</code>
option. This takes one argument, the email address to
use.</p></li><li><p id="x_53e"><a name="x_53e"></a>The default behavior is to send unified diffs
(see <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:patch" title="Understanding patches">the section called “Understanding patches”</a> for a
description of the
format), one per message. You can send a binary bundle
instead with the <code class="option">hg -b</code>
option.</p></li><li><p id="x_53f"><a name="x_53f"></a>Unified diffs are normally prefaced with a
metadata header. You can omit this, and send unadorned
diffs, with the <code class="option">hg
--plain</code> option.</p></li><li><p id="x_540"><a name="x_540"></a>Diffs are normally sent “<span class="quote">inline</span>”,
in the same body part as the description of a patch. This
makes it easiest for the largest number of readers to
quote and respond to parts of a diff, as some mail clients
will only quote the first MIME body part in a message. If
you'd prefer to send the description and the diff in
separate body parts, use the <code class="option">hg -a</code>
option.</p></li><li><p id="x_541"><a name="x_541"></a>Instead of sending mail messages, you can
write them to an <code class="literal">mbox</code>-format mail
folder using the <code class="option">hg -m</code>
option. That option takes one argument, the name of the
file to write to.</p></li><li><p id="x_542"><a name="x_542"></a>If you would like to add a
<span class="command"><strong>diffstat</strong></span>-format summary to each patch,
and one to the introductory message, use the <code class="option">hg -d</code>
option. The <span class="command"><strong>diffstat</strong></span> command displays
a table containing the name of each file patched, the
number of lines affected, and a histogram showing how much
each file is modified. This gives readers a qualitative
glance at how complex a patch is.</p></li></ul></div></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="advanced-uses-of-mercurial-queues.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="migrating-to-mercurial.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 13. Advanced uses of Mercurial Queues </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix A. Migrating to Mercurial</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,350 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 13. Advanced uses of Mercurial Queues</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="managing-change-with-mercurial-queues.html" title="Chapter 12. Managing change with Mercurial Queues"><link rel="next" href="adding-functionality-with-extensions.html" title="Chapter 14. Adding functionality with extensions"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 13. Advanced uses of Mercurial Queues</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="managing-change-with-mercurial-queues.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="adding-functionality-with-extensions.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:mq-collab"><div class="titlepage"><div><div><h2 class="title">Chapter 13. Advanced uses of Mercurial Queues</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id433631">The problem of many targets</a></span></dt><dd><dl><dt><span class="sect2"><a href="advanced-uses-of-mercurial-queues.html#id433704">Tempting approaches that don't work well</a></span></dt></dl></dd><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id433787">Conditionally applying patches with guards</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id433935">Controlling the guards on a patch</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id434471">Selecting the guards to use</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id435148">MQ's rules for applying patches</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id434989">Trimming the work environment</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id435034">Dividing up the series
file</a></span></dt><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id435315">Maintaining the patch series</a></span></dt><dd><dl><dt><span class="sect2"><a href="advanced-uses-of-mercurial-queues.html#id435424">The art of writing backport patches</a></span></dt></dl></dd><dt><span class="sect1"><a href="advanced-uses-of-mercurial-queues.html#id435495">Useful tips for developing with MQ</a></span></dt><dd><dl><dt><span class="sect2"><a href="advanced-uses-of-mercurial-queues.html#id435501">Organising patches in directories</a></span></dt><dt><span class="sect2"><a href="advanced-uses-of-mercurial-queues.html#mq-collab:tips:interdiff">Viewing the history of a patch</a></span></dt></dl></dd></dl></div><p id="x_15d"><a name="x_15d"></a>While it's easy to pick up straightforward uses of Mercurial
Queues, use of a little discipline and some of MQ's less
frequently used capabilities makes it possible to work in
complicated development environments.</p><p id="x_15e"><a name="x_15e"></a>In this chapter, I will use as an example a technique I have
used to manage the development of an Infiniband device driver for
the Linux kernel. The driver in question is large (at least as
drivers go), with 25,000 lines of code spread across 35 source
files. It is maintained by a small team of developers.</p><p id="x_15f"><a name="x_15f"></a>While much of the material in this chapter is specific to
Linux, the same principles apply to any code base for which you're
not the primary owner, and upon which you need to do a lot of
development.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id433631">The problem of many targets</h2></div></div></div><p id="x_160"><a name="x_160"></a>The Linux kernel changes rapidly, and has never been
internally stable; developers frequently make drastic changes
between releases. This means that a version of the driver that
works well with a particular released version of the kernel will
not even <span class="emphasis"><em>compile</em></span> correctly against,
typically, any other version.</p><p id="x_161"><a name="x_161"></a>To maintain a driver, we have to keep a number of distinct
versions of Linux in mind.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_162"><a name="x_162"></a>One target is the main Linux kernel development
tree. Maintenance of the code is in this case partly shared
by other developers in the kernel community, who make
<span class="quote">drive-by</span>” modifications to the driver as they
develop and refine kernel subsystems.</p></li><li><p id="x_163"><a name="x_163"></a>We also maintain a number of
<span class="quote">backports</span>” to older versions of the Linux
kernel, to support the needs of customers who are running
older Linux distributions that do not incorporate our
drivers. (To <span class="emphasis"><em>backport</em></span> a piece of code
is to modify it to work in an older version of its target
environment than the version it was developed for.)</p></li><li><p id="x_164"><a name="x_164"></a>Finally, we make software releases on a schedule
that is necessarily not aligned with those used by Linux
distributors and kernel developers, so that we can deliver
new features to customers without forcing them to upgrade
their entire kernels or distributions.</p></li></ul></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id433704">Tempting approaches that don't work well</h3></div></div></div><p id="x_165"><a name="x_165"></a>There are two “<span class="quote">standard</span>” ways to maintain a
piece of software that has to target many different
environments.</p><p id="x_166"><a name="x_166"></a>The first is to maintain a number of branches, each
intended for a single target. The trouble with this approach
is that you must maintain iron discipline in the flow of
changes between repositories. A new feature or bug fix must
start life in a “<span class="quote">pristine</span>” repository, then
percolate out to every backport repository. Backport changes
are more limited in the branches they should propagate to; a
backport change that is applied to a branch where it doesn't
belong will probably stop the driver from compiling.</p><p id="x_167"><a name="x_167"></a>The second is to maintain a single source tree filled with
conditional statements that turn chunks of code on or off
depending on the intended target. Because these
<span class="quote">ifdefs</span>” are not allowed in the Linux kernel
tree, a manual or automatic process must be followed to strip
them out and yield a clean tree. A code base maintained in
this fashion rapidly becomes a rat's nest of conditional
blocks that are difficult to understand and maintain.</p><p id="x_168"><a name="x_168"></a>Neither of these approaches is well suited to a situation
where you don't “<span class="quote">own</span>” the canonical copy of a
source tree. In the case of a Linux driver that is
distributed with the standard kernel, Linus's tree contains
the copy of the code that will be treated by the world as
canonical. The upstream version of “<span class="quote">my</span>” driver
can be modified by people I don't know, without me even
finding out about it until after the changes show up in
Linus's tree.</p><p id="x_169"><a name="x_169"></a>These approaches have the added weakness of making it
difficult to generate well-formed patches to submit
upstream.</p><p id="x_16a"><a name="x_16a"></a>In principle, Mercurial Queues seems like a good candidate
to manage a development scenario such as the above. While
this is indeed the case, MQ contains a few added features that
make the job more pleasant.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id433787">Conditionally applying patches with guards</h2></div></div></div><p id="x_16b"><a name="x_16b"></a>Perhaps the best way to maintain sanity with so many targets
is to be able to choose specific patches to apply for a given
situation. MQ provides a feature called “<span class="quote">guards</span>
(which originates with quilt's <code class="literal">guards</code>
command) that does just this. To start off, let's create a
simple repository for experimenting in.</p><pre id="id434160" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qinit</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg qnew hello.patch</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo hello &gt; hello</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add hello</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg qrefresh</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg qnew goodbye.patch</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo goodbye &gt; goodbye</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add goodbye</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg qrefresh</code></strong>
</pre><p id="x_16c"><a name="x_16c"></a>This gives us a tiny repository that contains two patches
that don't have any dependencies on each other, because they
touch different files.</p><p id="x_16d"><a name="x_16d"></a>The idea behind conditional application is that you can
<span class="quote">tag</span>” a patch with a <span class="emphasis"><em>guard</em></span>,
which is simply a text string of your choosing, then tell MQ to
select specific guards to use when applying patches. MQ will
then either apply, or skip over, a guarded patch, depending on
the guards that you have selected.</p><p id="x_16e"><a name="x_16e"></a>A patch can have an arbitrary number of guards; each one is
<span class="emphasis"><em>positive</em></span> (“<span class="quote">apply this patch if this
guard is selected</span>”) or <span class="emphasis"><em>negative</em></span>
(“<span class="quote">skip this patch if this guard is selected</span>”). A
patch with no guards is always applied.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id433935">Controlling the guards on a patch</h2></div></div></div><p id="x_16f"><a name="x_16f"></a>The <span class="command"><strong>qguard</strong></span> command lets
you determine which guards should apply to a patch, or display
the guards that are already in effect. Without any arguments, it
displays the guards on the current topmost patch.</p><pre id="id434459" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qguard</code></strong>
goodbye.patch: unguarded
</pre><p id="x_170"><a name="x_170"></a>To set a positive guard on a patch, prefix the name of the
guard with a “<span class="quote"><code class="literal">+</code></span>”.</p><pre id="id434060" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qguard +foo</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg qguard</code></strong>
goodbye.patch: +foo
</pre><p id="x_171"><a name="x_171"></a>To set a negative guard
on a patch, prefix the name of the guard with a
<span class="quote"><code class="literal">-</code></span>”.</p><pre id="id434440" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qguard hello.patch -quux</code></strong>
hg qguard: option -u not recognized
hg qguard [-l] [-n] -- [PATCH] [+GUARD]... [-GUARD]...
set or print guards for a patch
Guards control whether a patch can be pushed. A patch with no
guards is always pushed. A patch with a positive guard ("+foo") is
pushed only if the qselect command has activated it. A patch with
a negative guard ("-foo") is never pushed if the qselect command
has activated it.
With no arguments, print the currently active guards.
With arguments, set guards for the named patch.
NOTE: Specifying negative guards now requires '--'.
To set guards on another patch:
hg qguard -- other.patch +2.6.17 -stable
options:
-l --list list all patches and guards
-n --none drop all guards
use "hg -v help qguard" to show global options
<code class="prompt">$</code> <strong class="userinput"><code>hg qguard hello.patch</code></strong>
hello.patch: unguarded
</pre><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_172"><a name="x_172"></a> The <span class="command"><strong>qguard</strong></span> command
<span class="emphasis"><em>sets</em></span> the guards on a patch; it doesn't
<span class="emphasis"><em>modify</em></span> them. What this means is that if
you run <span class="command"><strong>hg qguard +a +b</strong></span> on a
patch, then <span class="command"><strong>hg qguard +c</strong></span> on
the same patch, the <span class="emphasis"><em>only</em></span> guard that will
be set on it afterwards is <code class="literal">+c</code>.</p></td></tr></table></div><p id="x_173"><a name="x_173"></a>Mercurial stores guards in the <code class="filename">series</code> file; the form in which they
are stored is easy both to understand and to edit by hand. (In
other words, you don't have to use the <span class="command"><strong>qguard</strong></span> command if you don't want
to; it's okay to simply edit the <code class="filename">series</code> file.)</p><pre id="id434417" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat .hg/patches/series</code></strong>
hello.patch
goodbye.patch #+foo
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id434471">Selecting the guards to use</h2></div></div></div><p id="x_174"><a name="x_174"></a>The <span class="command"><strong>qselect</strong></span> command
determines which guards are active at a given time. The effect
of this is to determine which patches MQ will apply the next
time you run <span class="command"><strong>qpush</strong></span>. It has
no other effect; in particular, it doesn't do anything to
patches that are already applied.</p><p id="x_175"><a name="x_175"></a>With no arguments, the <span class="command"><strong>qselect</strong></span> command lists the guards
currently in effect, one per line of output. Each argument is
treated as the name of a guard to apply.</p><pre id="id434859" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qpop -a</code></strong>
patch queue now empty
<code class="prompt">$</code> <strong class="userinput"><code>hg qselect</code></strong>
no active guards
<code class="prompt">$</code> <strong class="userinput"><code>hg qselect foo</code></strong>
number of unguarded, unapplied patches has changed from 1 to 2
<code class="prompt">$</code> <strong class="userinput"><code>hg qselect</code></strong>
foo
</pre><p id="x_176"><a name="x_176"></a>In case you're interested, the currently selected guards are
stored in the <code class="filename">guards</code> file.</p><pre id="id434741" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat .hg/patches/guards</code></strong>
foo
</pre><p id="x_177"><a name="x_177"></a>We can see the effect the selected guards have when we run
<span class="command"><strong>qpush</strong></span>.</p><pre id="id434698" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qpush -a</code></strong>
applying hello.patch
applying goodbye.patch
now at: goodbye.patch
</pre><p id="x_178"><a name="x_178"></a>A guard cannot start with a
<span class="quote"><code class="literal">+</code></span>” or
<span class="quote"><code class="literal">-</code></span>” character. The name of a
guard must not contain white space, but most other characters
are acceptable. If you try to use a guard with an invalid name,
MQ will complain:</p><pre id="id434609" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qselect +foo</code></strong>
abort: guard '+foo' starts with invalid character: '+'
</pre><p id="x_179"><a name="x_179"></a>Changing the selected guards changes the patches that are
applied.</p><pre id="id435172" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qselect quux</code></strong>
number of guarded, applied patches has changed from 0 to 1
<code class="prompt">$</code> <strong class="userinput"><code>hg qpop -a</code></strong>
patch queue now empty
<code class="prompt">$</code> <strong class="userinput"><code>hg qpush -a</code></strong>
applying hello.patch
skipping goodbye.patch - guarded by ['+foo']
now at: hello.patch
</pre><p id="x_17a"><a name="x_17a"></a>You can see in the example below that negative guards take
precedence over positive guards.</p><pre id="id435108" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg qselect foo bar</code></strong>
number of unguarded, unapplied patches has changed from 0 to 1
<code class="prompt">$</code> <strong class="userinput"><code>hg qpop -a</code></strong>
patch queue now empty
<code class="prompt">$</code> <strong class="userinput"><code>hg qpush -a</code></strong>
applying hello.patch
applying goodbye.patch
now at: goodbye.patch
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id435148">MQ's rules for applying patches</h2></div></div></div><p id="x_17b"><a name="x_17b"></a>The rules that MQ uses when deciding whether to apply a
patch are as follows.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_17c"><a name="x_17c"></a>A patch that has no guards is always
applied.</p></li><li><p id="x_17d"><a name="x_17d"></a>If the patch has any negative guard that matches
any currently selected guard, the patch is skipped.</p></li><li><p id="x_17e"><a name="x_17e"></a>If the patch has any positive guard that matches
any currently selected guard, the patch is applied.</p></li><li><p id="x_17f"><a name="x_17f"></a>If the patch has positive or negative guards,
but none matches any currently selected guard, the patch is
skipped.</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id434989">Trimming the work environment</h2></div></div></div><p id="x_180"><a name="x_180"></a>In working on the device driver I mentioned earlier, I don't
apply the patches to a normal Linux kernel tree. Instead, I use
a repository that contains only a snapshot of the source files
and headers that are relevant to Infiniband development. This
repository is 1% the size of a kernel repository, so it's easier
to work with.</p><p id="x_181"><a name="x_181"></a>I then choose a “<span class="quote">base</span>” version on top of which
the patches are applied. This is a snapshot of the Linux kernel
tree as of a revision of my choosing. When I take the snapshot,
I record the changeset ID from the kernel repository in the
commit message. Since the snapshot preserves the
<span class="quote">shape</span>” and content of the relevant parts of the
kernel tree, I can apply my patches on top of either my tiny
repository or a normal kernel tree.</p><p id="x_182"><a name="x_182"></a>Normally, the base tree atop which the patches apply should
be a snapshot of a very recent upstream tree. This best
facilitates the development of patches that can easily be
submitted upstream with few or no modifications.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id435034">Dividing up the <code class="filename">series</code>
file</h2></div></div></div><p id="x_183"><a name="x_183"></a>I categorise the patches in the <code class="filename">series</code> file into a number of logical
groups. Each section of like patches begins with a block of
comments that describes the purpose of the patches that
follow.</p><p id="x_184"><a name="x_184"></a>The sequence of patch groups that I maintain follows. The
ordering of these groups is important; I'll describe why after I
introduce the groups.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_185"><a name="x_185"></a>The “<span class="quote">accepted</span>” group. Patches that
the development team has submitted to the maintainer of the
Infiniband subsystem, and which he has accepted, but which
are not present in the snapshot that the tiny repository is
based on. These are “<span class="quote">read only</span>” patches,
present only to transform the tree into a similar state as
it is in the upstream maintainer's repository.</p></li><li><p id="x_186"><a name="x_186"></a>The “<span class="quote">rework</span>” group. Patches that I
have submitted, but that the upstream maintainer has
requested modifications to before he will accept
them.</p></li><li><p id="x_187"><a name="x_187"></a>The “<span class="quote">pending</span>” group. Patches that
I have not yet submitted to the upstream maintainer, but
which we have finished working on. These will be “<span class="quote">read
only</span>” for a while. If the upstream maintainer
accepts them upon submission, I'll move them to the end of
the “<span class="quote">accepted</span>” group. If he requests that I
modify any, I'll move them to the beginning of the
<span class="quote">rework</span>” group.</p></li><li><p id="x_188"><a name="x_188"></a>The “<span class="quote">in progress</span>” group. Patches
that are actively being developed, and should not be
submitted anywhere yet.</p></li><li><p id="x_189"><a name="x_189"></a>The “<span class="quote">backport</span>” group. Patches that
adapt the source tree to older versions of the kernel
tree.</p></li><li><p id="x_18a"><a name="x_18a"></a>The “<span class="quote">do not ship</span>” group. Patches
that for some reason should never be submitted upstream.
For example, one such patch might change embedded driver
identification strings to make it easier to distinguish, in
the field, between an out-of-tree version of the driver and
a version shipped by a distribution vendor.</p></li></ul></div><p id="x_18b"><a name="x_18b"></a>Now to return to the reasons for ordering groups of patches
in this way. We would like the lowest patches in the stack to
be as stable as possible, so that we will not need to rework
higher patches due to changes in context. Putting patches that
will never be changed first in the <code class="filename">series</code> file serves this
purpose.</p><p id="x_18c"><a name="x_18c"></a>We would also like the patches that we know we'll need to
modify to be applied on top of a source tree that resembles the
upstream tree as closely as possible. This is why we keep
accepted patches around for a while.</p><p id="x_18d"><a name="x_18d"></a>The “<span class="quote">backport</span>” and “<span class="quote">do not ship</span>
patches float at the end of the <code class="filename">series</code> file. The backport patches
must be applied on top of all other patches, and the “<span class="quote">do
not ship</span>” patches might as well stay out of harm's
way.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id435315">Maintaining the patch series</h2></div></div></div><p id="x_18e"><a name="x_18e"></a>In my work, I use a number of guards to control which
patches are to be applied.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_18f"><a name="x_18f"></a><span class="quote">Accepted</span>” patches are guarded with
<code class="literal">accepted</code>. I enable this guard most of
the time. When I'm applying the patches on top of a tree
where the patches are already present, I can turn this patch
off, and the patches that follow it will apply
cleanly.</p></li><li><p id="x_190"><a name="x_190"></a>Patches that are “<span class="quote">finished</span>”, but
not yet submitted, have no guards. If I'm applying the
patch stack to a copy of the upstream tree, I don't need to
enable any guards in order to get a reasonably safe source
tree.</p></li><li><p id="x_191"><a name="x_191"></a>Those patches that need reworking before being
resubmitted are guarded with
<code class="literal">rework</code>.</p></li><li><p id="x_192"><a name="x_192"></a>For those patches that are still under
development, I use <code class="literal">devel</code>.</p></li><li><p id="x_193"><a name="x_193"></a>A backport patch may have several guards, one
for each version of the kernel to which it applies. For
example, a patch that backports a piece of code to 2.6.9
will have a <code class="literal">2.6.9</code> guard.</p></li></ul></div><p id="x_194"><a name="x_194"></a>This variety of guards gives me considerable flexibility in
determining what kind of source tree I want to end up with. For
most situations, the selection of appropriate guards is
automated during the build process, but I can manually tune the
guards to use for less common circumstances.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id435424">The art of writing backport patches</h3></div></div></div><p id="x_195"><a name="x_195"></a>Using MQ, writing a backport patch is a simple process.
All such a patch has to do is modify a piece of code that uses
a kernel feature not present in the older version of the
kernel, so that the driver continues to work correctly under
that older version.</p><p id="x_196"><a name="x_196"></a>A useful goal when writing a good backport patch is to
make your code look as if it was written for the older version
of the kernel you're targeting. The less obtrusive the patch,
the easier it will be to understand and maintain. If you're
writing a collection of backport patches to avoid the
<span class="quote">rat's nest</span>” effect of lots of
<code class="literal">#ifdef</code>s (hunks of source code that are only
used conditionally) in your code, don't introduce
version-dependent <code class="literal">#ifdef</code>s into the patches.
Instead, write several patches, each of which makes
unconditional changes, and control their application using
guards.</p><p id="x_197"><a name="x_197"></a>There are two reasons to divide backport patches into a
distinct group, away from the “<span class="quote">regular</span>” patches
whose effects they modify. The first is that intermingling the
two makes it more difficult to use a tool like the <code class="literal">patchbomb</code> extension to automate the
process of submitting the patches to an upstream maintainer.
The second is that a backport patch could perturb the context
in which a subsequent regular patch is applied, making it
impossible to apply the regular patch cleanly
<span class="emphasis"><em>without</em></span> the earlier backport patch
already being applied.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id435495">Useful tips for developing with MQ</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id435501">Organising patches in directories</h3></div></div></div><p id="x_198"><a name="x_198"></a>If you're working on a substantial project with MQ, it's
not difficult to accumulate a large number of patches. For
example, I have one patch repository that contains over 250
patches.</p><p id="x_199"><a name="x_199"></a>If you can group these patches into separate logical
categories, you can if you like store them in different
directories; MQ has no problems with patch names that contain
path separators.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="mq-collab:tips:interdiff">Viewing the history of a patch</h3></div></div></div><p id="x_19a"><a name="x_19a"></a>If you're developing a set of patches over a long time,
it's a good idea to maintain them in a repository, as
discussed in <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:repo" title="Managing patches in a repository">the section called “Managing patches in a repository”</a>. If you do
so, you'll quickly
discover that using the <span class="command"><strong>hg
diff</strong></span> command to look at the history of changes to
a patch is unworkable. This is in part because you're looking
at the second derivative of the real code (a diff of a diff),
but also because MQ adds noise to the process by modifying
time stamps and directory names when it updates a
patch.</p><p id="x_19b"><a name="x_19b"></a>However, you can use the <code class="literal">extdiff</code> extension, which is bundled
with Mercurial, to turn a diff of two versions of a patch into
something readable. To do this, you will need a third-party
package called <code class="literal">patchutils</code>
[<span class="citation">web:patchutils</span>]. This provides a command
named <span class="command"><strong>interdiff</strong></span>, which shows the
differences between two diffs as a diff. Used on two versions
of the same diff, it generates a diff that represents the diff
from the first to the second version.</p><p id="x_19c"><a name="x_19c"></a>You can enable the <code class="literal">extdiff</code> extension in the usual way,
by adding a line to the <code class="literal">extensions</code> section of your
<code class="filename">~/.hgrc</code>.</p><pre id="id435628" class="programlisting">[extensions]
extdiff =</pre><p id="x_19d"><a name="x_19d"></a>The <span class="command"><strong>interdiff</strong></span> command expects to be
passed the names of two files, but the <code class="literal">extdiff</code> extension passes the program
it runs a pair of directories, each of which can contain an
arbitrary number of files. We thus need a small program that
will run <span class="command"><strong>interdiff</strong></span> on each pair of files in
these two directories. This program is available as <code class="filename">hg-interdiff</code> in the <code class="filename">examples</code> directory of the
source code repository that accompanies this book. </p><p id="x_19e"><a name="x_19e"></a>With the <code class="filename">hg-interdiff</code>
program in your shell's search path, you can run it as
follows, from inside an MQ patch directory:</p><pre id="id435697" class="programlisting">hg extdiff -p hg-interdiff -r A:B my-change.patch</pre><p id="x_19f"><a name="x_19f"></a>Since you'll probably want to use this long-winded command
a lot, you can get <code class="literal">hgext</code> to
make it available as a normal Mercurial command, again by
editing your <code class="filename">~/.hgrc</code>.</p><pre id="id435727" class="programlisting">[extdiff]
cmd.interdiff = hg-interdiff</pre><p id="x_1a0"><a name="x_1a0"></a>This directs <code class="literal">hgext</code> to
make an <code class="literal">interdiff</code> command available, so you
can now shorten the previous invocation of <span class="command"><strong>extdiff</strong></span> to something a
little more wieldy.</p><pre id="id435764" class="programlisting">hg interdiff -r A:B my-change.patch</pre><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_1a1"><a name="x_1a1"></a> The <span class="command"><strong>interdiff</strong></span> command works well
only if the underlying files against which versions of a
patch are generated remain the same. If you create a patch,
modify the underlying files, and then regenerate the patch,
<span class="command"><strong>interdiff</strong></span> may not produce useful
output.</p></td></tr></table></div><p id="x_1a2"><a name="x_1a2"></a>The <code class="literal">extdiff</code> extension is
useful for more than merely improving the presentation of MQ
patches. To read more about it, go to <a class="xref" href="adding-functionality-with-extensions.html#sec:hgext:extdiff" title="Flexible diff support with the extdiff extension">the section called “Flexible diff support with the extdiff extension”</a>.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="managing-change-with-mercurial-queues.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="adding-functionality-with-extensions.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 12. Managing change with Mercurial Queues </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 14. Adding functionality with extensions</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

431
read/behind-the-scenes.html Normal file
View File

@ -0,0 +1,431 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 4. Behind the scenes</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="a-tour-of-mercurial-merging-work.html" title="Chapter 3. A tour of Mercurial: merging work"><link rel="next" href="mercurial-in-daily-use.html" title="Chapter 5. Mercurial in daily use"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 4. Behind the scenes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="a-tour-of-mercurial-merging-work.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="mercurial-in-daily-use.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:concepts"><div class="titlepage"><div><div><h2 class="title">Chapter 4. Behind the scenes</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="behind-the-scenes.html#id357785">Mercurial's historical record</a></span></dt><dd><dl><dt><span class="sect2"><a href="behind-the-scenes.html#id357790">Tracking the history of a single file</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id357874">Managing tracked files</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id357891">Recording changeset information</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id357908">Relationships between revisions</a></span></dt></dl></dd><dt><span class="sect1"><a href="behind-the-scenes.html#id357985">Safe, efficient storage</a></span></dt><dd><dl><dt><span class="sect2"><a href="behind-the-scenes.html#id358000">Efficient storage</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#sec:concepts:txn">Safe operation</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id358067">Fast retrieval</a></span></dt><dd><dl><dt><span class="sect3"><a href="behind-the-scenes.html#id358134">Aside: the influence of video compression</a></span></dt></dl></dd><dt><span class="sect2"><a href="behind-the-scenes.html#id358156">Identification and strong integrity</a></span></dt></dl></dd><dt><span class="sect1"><a href="behind-the-scenes.html#id358194">Revision history, branching, and merging</a></span></dt><dt><span class="sect1"><a href="behind-the-scenes.html#id358265">The working directory</a></span></dt><dd><dl><dt><span class="sect2"><a href="behind-the-scenes.html#id358342">What happens when you commit</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id358441">Creating a new head</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id358589">Merging changes</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id358735">Merging and renames</a></span></dt></dl></dd><dt><span class="sect1"><a href="behind-the-scenes.html#id358761">Other interesting design features</a></span></dt><dd><dl><dt><span class="sect2"><a href="behind-the-scenes.html#id358780">Clever compression</a></span></dt><dd><dl><dt><span class="sect3"><a href="behind-the-scenes.html#id358828">Network recompression</a></span></dt></dl></dd><dt><span class="sect2"><a href="behind-the-scenes.html#id358901">Read/write ordering and atomicity</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id358935">Concurrent access</a></span></dt><dd><dl><dt><span class="sect3"><a href="behind-the-scenes.html#id358982">Safe dirstate access</a></span></dt></dl></dd><dt><span class="sect2"><a href="behind-the-scenes.html#id359009">Avoiding seeks</a></span></dt><dt><span class="sect2"><a href="behind-the-scenes.html#id359061">Other contents of the dirstate</a></span></dt></dl></dd></dl></div><p id="x_2e8"><a name="x_2e8"></a>Unlike many revision control systems, the concepts
upon which Mercurial is built are simple enough that it's easy to
understand how the software really works. Knowing these details
certainly isn't necessary, so it is certainly safe to skip this
chapter. However, I think you will get more out of the software
with a “<span class="quote">mental model</span>” of what's going on.</p><p id="x_2e9"><a name="x_2e9"></a>Being able to understand what's going on behind the
scenes gives me confidence that Mercurial has been carefully
designed to be both <span class="emphasis"><em>safe</em></span> and
<span class="emphasis"><em>efficient</em></span>. And just as importantly, if it's
easy for me to retain a good idea of what the software is doing
when I perform a revision control task, I'm less likely to be
surprised by its behavior.</p><p id="x_2ea"><a name="x_2ea"></a>In this chapter, we'll initially cover the core concepts
behind Mercurial's design, then continue to discuss some of the
interesting details of its implementation.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id357785">Mercurial's historical record</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id357790">Tracking the history of a single file</h3></div></div></div><p id="x_2eb"><a name="x_2eb"></a>When Mercurial tracks modifications to a file, it stores
the history of that file in a metadata object called a
<span class="emphasis"><em>filelog</em></span>. Each entry in the filelog
contains enough information to reconstruct one revision of the
file that is being tracked. Filelogs are stored as files in
the <code class="filename">.hg/store/data</code> directory. A
filelog contains two kinds of information: revision data, and
an index to help Mercurial to find a revision
efficiently.</p><p id="x_2ec"><a name="x_2ec"></a>A file that is large, or has a lot of history, has its
filelog stored in separate data
(“<span class="quote"><code class="literal">.d</code></span>” suffix) and index
(“<span class="quote"><code class="literal">.i</code></span>” suffix) files. For
small files without much history, the revision data and index
are combined in a single “<span class="quote"><code class="literal">.i</code></span>
file. The correspondence between a file in the working
directory and the filelog that tracks its history in the
repository is illustrated in <a class="xref" href="behind-the-scenes.html#fig:concepts:filelog" title="Figure 4.1. Relationships between files in working directory and filelogs in repository">Figure 4.1, “Relationships between files in working directory and
filelogs in repository”</a>.</p><div class="figure"><a name="fig:concepts:filelog"></a><p class="title"><b>Figure 4.1. Relationships between files in working directory and
filelogs in repository</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/filelog.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id357874">Managing tracked files</h3></div></div></div><p id="x_2ee"><a name="x_2ee"></a>Mercurial uses a structure called a
<span class="emphasis"><em>manifest</em></span> to collect together information
about the files that it tracks. Each entry in the manifest
contains information about the files present in a single
changeset. An entry records which files are present in the
changeset, the revision of each file, and a few other pieces
of file metadata.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id357891">Recording changeset information</h3></div></div></div><p id="x_2ef"><a name="x_2ef"></a>The <span class="emphasis"><em>changelog</em></span> contains information
about each changeset. Each revision records who committed a
change, the changeset comment, other pieces of
changeset-related information, and the revision of the
manifest to use.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id357908">Relationships between revisions</h3></div></div></div><p id="x_2f0"><a name="x_2f0"></a>Within a changelog, a manifest, or a filelog, each
revision stores a pointer to its immediate parent (or to its
two parents, if it's a merge revision). As I mentioned above,
there are also relationships between revisions
<span class="emphasis"><em>across</em></span> these structures, and they are
hierarchical in nature.</p><p id="x_2f1"><a name="x_2f1"></a>For every changeset in a repository, there is exactly one
revision stored in the changelog. Each revision of the
changelog contains a pointer to a single revision of the
manifest. A revision of the manifest stores a pointer to a
single revision of each filelog tracked when that changeset
was created. These relationships are illustrated in
<a class="xref" href="behind-the-scenes.html#fig:concepts:metadata" title="Figure 4.2. Metadata relationships">Figure 4.2, “Metadata relationships”</a>.</p><div class="figure"><a name="fig:concepts:metadata"></a><p class="title"><b>Figure 4.2. Metadata relationships</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/metadata.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_2f3"><a name="x_2f3"></a>As the illustration shows, there is
<span class="emphasis"><em>not</em></span> a “<span class="quote">one to one</span>
relationship between revisions in the changelog, manifest, or
filelog. If a file that
Mercurial tracks hasn't changed between two changesets, the
entry for that file in the two revisions of the manifest will
point to the same revision of its filelog<sup>[<a name="id357972" href="#ftn.id357972" class="footnote">3</a>]</sup>.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id357985">Safe, efficient storage</h2></div></div></div><p id="x_2f4"><a name="x_2f4"></a>The underpinnings of changelogs, manifests, and filelogs are
provided by a single structure called the
<span class="emphasis"><em>revlog</em></span>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358000">Efficient storage</h3></div></div></div><p id="x_2f5"><a name="x_2f5"></a>The revlog provides efficient storage of revisions using a
<span class="emphasis"><em>delta</em></span> mechanism. Instead of storing a
complete copy of a file for each revision, it stores the
changes needed to transform an older revision into the new
revision. For many kinds of file data, these deltas are
typically a fraction of a percent of the size of a full copy
of a file.</p><p id="x_2f6"><a name="x_2f6"></a>Some obsolete revision control systems can only work with
deltas of text files. They must either store binary files as
complete snapshots or encoded into a text representation, both
of which are wasteful approaches. Mercurial can efficiently
handle deltas of files with arbitrary binary contents; it
doesn't need to treat text as special.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:concepts:txn">Safe operation</h3></div></div></div><p id="x_2f7"><a name="x_2f7"></a>Mercurial only ever <span class="emphasis"><em>appends</em></span> data to
the end of a revlog file. It never modifies a section of a
file after it has written it. This is both more robust and
efficient than schemes that need to modify or rewrite
data.</p><p id="x_2f8"><a name="x_2f8"></a>In addition, Mercurial treats every write as part of a
<span class="emphasis"><em>transaction</em></span> that can span a number of
files. A transaction is <span class="emphasis"><em>atomic</em></span>: either
the entire transaction succeeds and its effects are all
visible to readers in one go, or the whole thing is undone.
This guarantee of atomicity means that if you're running two
copies of Mercurial, where one is reading data and one is
writing it, the reader will never see a partially written
result that might confuse it.</p><p id="x_2f9"><a name="x_2f9"></a>The fact that Mercurial only appends to files makes it
easier to provide this transactional guarantee. The easier it
is to do stuff like this, the more confident you should be
that it's done correctly.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358067">Fast retrieval</h3></div></div></div><p id="x_2fa"><a name="x_2fa"></a>Mercurial cleverly avoids a pitfall common to
all earlier revision control systems: the problem of
<span class="emphasis"><em>inefficient retrieval</em></span>. Most revision
control systems store the contents of a revision as an
incremental series of modifications against a
<span class="quote">snapshot</span>”. (Some base the snapshot on the
oldest revision, others on the newest.) To reconstruct a
specific revision, you must first read the snapshot, and then
every one of the revisions between the snapshot and your
target revision. The more history that a file accumulates,
the more revisions you must read, hence the longer it takes to
reconstruct a particular revision.</p><div class="figure"><a name="fig:concepts:snapshot"></a><p class="title"><b>Figure 4.3. Snapshot of a revlog, with incremental deltas</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/snapshot.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_2fc"><a name="x_2fc"></a>The innovation that Mercurial applies to this problem is
simple but effective. Once the cumulative amount of delta
information stored since the last snapshot exceeds a fixed
threshold, it stores a new snapshot (compressed, of course),
instead of another delta. This makes it possible to
reconstruct <span class="emphasis"><em>any</em></span> revision of a file
quickly. This approach works so well that it has since been
copied by several other revision control systems.</p><p id="x_2fd"><a name="x_2fd"></a><a class="xref" href="behind-the-scenes.html#fig:concepts:snapshot" title="Figure 4.3. Snapshot of a revlog, with incremental deltas">Figure 4.3, “Snapshot of a revlog, with incremental deltas”</a> illustrates
the idea. In an entry in a revlog's index file, Mercurial
stores the range of entries from the data file that it must
read to reconstruct a particular revision.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id358134">Aside: the influence of video compression</h4></div></div></div><p id="x_2fe"><a name="x_2fe"></a>If you're familiar with video compression or
have ever watched a TV feed through a digital cable or
satellite service, you may know that most video compression
schemes store each frame of video as a delta against its
predecessor frame.</p><p id="x_2ff"><a name="x_2ff"></a>Mercurial borrows this idea to make it
possible to reconstruct a revision from a snapshot and a
small number of deltas.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358156">Identification and strong integrity</h3></div></div></div><p id="x_300"><a name="x_300"></a>Along with delta or snapshot information, a revlog entry
contains a cryptographic hash of the data that it represents.
This makes it difficult to forge the contents of a revision,
and easy to detect accidental corruption.</p><p id="x_301"><a name="x_301"></a>Hashes provide more than a mere check against corruption;
they are used as the identifiers for revisions. The changeset
identification hashes that you see as an end user are from
revisions of the changelog. Although filelogs and the
manifest also use hashes, Mercurial only uses these behind the
scenes.</p><p id="x_302"><a name="x_302"></a>Mercurial verifies that hashes are correct when it
retrieves file revisions and when it pulls changes from
another repository. If it encounters an integrity problem, it
will complain and stop whatever it's doing.</p><p id="x_303"><a name="x_303"></a>In addition to the effect it has on retrieval efficiency,
Mercurial's use of periodic snapshots makes it more robust
against partial data corruption. If a revlog becomes partly
corrupted due to a hardware error or system bug, it's often
possible to reconstruct some or most revisions from the
uncorrupted sections of the revlog, both before and after the
corrupted section. This would not be possible with a
delta-only storage model.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id358194">Revision history, branching, and merging</h2></div></div></div><p id="x_304"><a name="x_304"></a>Every entry in a Mercurial revlog knows the identity of its
immediate ancestor revision, usually referred to as its
<span class="emphasis"><em>parent</em></span>. In fact, a revision contains room
for not one parent, but two. Mercurial uses a special hash,
called the “<span class="quote">null ID</span>”, to represent the idea
<span class="quote">there is no parent here</span>”. This hash is simply a
string of zeroes.</p><p id="x_305"><a name="x_305"></a>In <a class="xref" href="behind-the-scenes.html#fig:concepts:revlog" title="Figure 4.4. The conceptual structure of a revlog">Figure 4.4, “The conceptual structure of a revlog”</a>, you can see
an example of the conceptual structure of a revlog. Filelogs,
manifests, and changelogs all have this same structure; they
differ only in the kind of data stored in each delta or
snapshot.</p><p id="x_306"><a name="x_306"></a>The first revision in a revlog (at the bottom of the image)
has the null ID in both of its parent slots. For a
<span class="quote">normal</span>” revision, its first parent slot contains
the ID of its parent revision, and its second contains the null
ID, indicating that the revision has only one real parent. Any
two revisions that have the same parent ID are branches. A
revision that represents a merge between branches has two normal
revision IDs in its parent slots.</p><div class="figure"><a name="fig:concepts:revlog"></a><p class="title"><b>Figure 4.4. The conceptual structure of a revlog</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/revlog.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id358265">The working directory</h2></div></div></div><p id="x_307"><a name="x_307"></a>In the working directory, Mercurial stores a snapshot of the
files from the repository as of a particular changeset.</p><p id="x_308"><a name="x_308"></a>The working directory “<span class="quote">knows</span>” which changeset
it contains. When you update the working directory to contain a
particular changeset, Mercurial looks up the appropriate
revision of the manifest to find out which files it was tracking
at the time that changeset was committed, and which revision of
each file was then current. It then recreates a copy of each of
those files, with the same contents it had when the changeset
was committed.</p><p id="x_309"><a name="x_309"></a>The <span class="emphasis"><em>dirstate</em></span> is a special
structure that contains Mercurial's knowledge of the working
directory. It is maintained as a file named
<code class="filename">.hg/dirstate</code> inside a repository. The
dirstate details which changeset the working directory is
updated to, and all of the files that Mercurial is tracking in
the working directory. It also lets Mercurial quickly notice
changed files, by recording their checkout times and
sizes.</p><p id="x_30a"><a name="x_30a"></a>Just as a revision of a revlog has room for two parents, so
that it can represent either a normal revision (with one parent)
or a merge of two earlier revisions, the dirstate has slots for
two parents. When you use the <span class="command"><strong>hg
update</strong></span> command, the changeset that you update to is
stored in the “<span class="quote">first parent</span>” slot, and the null ID
in the second. When you <span class="command"><strong>hg
merge</strong></span> with another changeset, the first parent
remains unchanged, and the second parent is filled in with the
changeset you're merging with. The <span class="command"><strong>hg
parents</strong></span> command tells you what the parents of the
dirstate are.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358342">What happens when you commit</h3></div></div></div><p id="x_30b"><a name="x_30b"></a>The dirstate stores parent information for more than just
book-keeping purposes. Mercurial uses the parents of the
dirstate as <span class="emphasis"><em>the parents of a new
changeset</em></span> when you perform a commit.</p><div class="figure"><a name="fig:concepts:wdir"></a><p class="title"><b>Figure 4.5. The working directory can have two parents</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/wdir.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_30d"><a name="x_30d"></a><a class="xref" href="behind-the-scenes.html#fig:concepts:wdir" title="Figure 4.5. The working directory can have two parents">Figure 4.5, “The working directory can have two parents”</a> shows the
normal state of the working directory, where it has a single
changeset as parent. That changeset is the
<span class="emphasis"><em>tip</em></span>, the newest changeset in the
repository that has no children.</p><div class="figure"><a name="fig:concepts:wdir-after-commit"></a><p class="title"><b>Figure 4.6. The working directory gains new parents after a
commit</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/wdir-after-commit.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_30f"><a name="x_30f"></a>It's useful to think of the working directory as
<span class="quote">the changeset I'm about to commit</span>”. Any files
that you tell Mercurial that you've added, removed, renamed,
or copied will be reflected in that changeset, as will
modifications to any files that Mercurial is already tracking;
the new changeset will have the parents of the working
directory as its parents.</p><p id="x_310"><a name="x_310"></a>After a commit, Mercurial will update the
parents of the working directory, so that the first parent is
the ID of the new changeset, and the second is the null ID.
This is shown in <a class="xref" href="behind-the-scenes.html#fig:concepts:wdir-after-commit" title="Figure 4.6. The working directory gains new parents after a commit">Figure 4.6, “The working directory gains new parents after a
commit”</a>. Mercurial
doesn't touch any of the files in the working directory when
you commit; it just modifies the dirstate to note its new
parents.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358441">Creating a new head</h3></div></div></div><p id="x_311"><a name="x_311"></a>It's perfectly normal to update the working directory to a
changeset other than the current tip. For example, you might
want to know what your project looked like last Tuesday, or
you could be looking through changesets to see which one
introduced a bug. In cases like this, the natural thing to do
is update the working directory to the changeset you're
interested in, and then examine the files in the working
directory directly to see their contents as they were when you
committed that changeset. The effect of this is shown in
<a class="xref" href="behind-the-scenes.html#fig:concepts:wdir-pre-branch" title="Figure 4.7. The working directory, updated to an older changeset">Figure 4.7, “The working directory, updated to an older
changeset”</a>.</p><div class="figure"><a name="fig:concepts:wdir-pre-branch"></a><p class="title"><b>Figure 4.7. The working directory, updated to an older
changeset</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/wdir-pre-branch.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_313"><a name="x_313"></a>Having updated the working directory to an
older changeset, what happens if you make some changes, and
then commit? Mercurial behaves in the same way as I outlined
above. The parents of the working directory become the
parents of the new changeset. This new changeset has no
children, so it becomes the new tip. And the repository now
contains two changesets that have no children; we call these
<span class="emphasis"><em>heads</em></span>. You can see the structure that
this creates in <a class="xref" href="behind-the-scenes.html#fig:concepts:wdir-branch" title="Figure 4.8. After a commit made while synced to an older changeset">Figure 4.8, “After a commit made while synced to an older
changeset”</a>.</p><div class="figure"><a name="fig:concepts:wdir-branch"></a><p class="title"><b>Figure 4.8. After a commit made while synced to an older
changeset</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/wdir-branch.png" alt="XXX add text"></div></div></div><br class="figure-break"><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_315"><a name="x_315"></a>If you're new to Mercurial, you should keep
in mind a common “<span class="quote">error</span>”, which is to use the
<span class="command"><strong>hg pull</strong></span> command without any
options. By default, the <span class="command"><strong>hg
pull</strong></span> command <span class="emphasis"><em>does not</em></span>
update the working directory, so you'll bring new changesets
into your repository, but the working directory will stay
synced at the same changeset as before the pull. If you
make some changes and commit afterwards, you'll thus create
a new head, because your working directory isn't synced to
whatever the current tip is. To combine the operation of a
pull, followed by an update, run <span class="command"><strong>hg pull
-u</strong></span>.</p><p id="x_316"><a name="x_316"></a>I put the word “<span class="quote">error</span>” in quotes
because all that you need to do to rectify the situation
where you created a new head by accident is
<span class="command"><strong>hg merge</strong></span>, then <span class="command"><strong>hg commit</strong></span>. In other words, this
almost never has negative consequences; it's just something
of a surprise for newcomers. I'll discuss other ways to
avoid this behavior, and why Mercurial behaves in this
initially surprising way, later on.</p></td></tr></table></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358589">Merging changes</h3></div></div></div><p id="x_317"><a name="x_317"></a>When you run the <span class="command"><strong>hg
merge</strong></span> command, Mercurial leaves the first parent
of the working directory unchanged, and sets the second parent
to the changeset you're merging with, as shown in <a class="xref" href="behind-the-scenes.html#fig:concepts:wdir-merge" title="Figure 4.9. Merging two heads">Figure 4.9, “Merging two heads”</a>.</p><div class="figure"><a name="fig:concepts:wdir-merge"></a><p class="title"><b>Figure 4.9. Merging two heads</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/wdir-merge.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_319"><a name="x_319"></a>Mercurial also has to modify the working directory, to
merge the files managed in the two changesets. Simplified a
little, the merging process goes like this, for every file in
the manifests of both changesets.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_31a"><a name="x_31a"></a>If neither changeset has modified a file, do
nothing with that file.</p></li><li><p id="x_31b"><a name="x_31b"></a>If one changeset has modified a file, and the
other hasn't, create the modified copy of the file in the
working directory.</p></li><li><p id="x_31c"><a name="x_31c"></a>If one changeset has removed a file, and the
other hasn't (or has also deleted it), delete the file
from the working directory.</p></li><li><p id="x_31d"><a name="x_31d"></a>If one changeset has removed a file, but the
other has modified the file, ask the user what to do: keep
the modified file, or remove it?</p></li><li><p id="x_31e"><a name="x_31e"></a>If both changesets have modified a file,
invoke an external merge program to choose the new
contents for the merged file. This may require input from
the user.</p></li><li><p id="x_31f"><a name="x_31f"></a>If one changeset has modified a file, and the
other has renamed or copied the file, make sure that the
changes follow the new name of the file.</p></li></ul></div><p id="x_320"><a name="x_320"></a>There are more details—merging has plenty of corner
cases—but these are the most common choices that are
involved in a merge. As you can see, most cases are
completely automatic, and indeed most merges finish
automatically, without requiring your input to resolve any
conflicts.</p><p id="x_321"><a name="x_321"></a>When you're thinking about what happens when you commit
after a merge, once again the working directory is “<span class="quote">the
changeset I'm about to commit</span>”. After the <span class="command"><strong>hg merge</strong></span> command completes, the
working directory has two parents; these will become the
parents of the new changeset.</p><p id="x_322"><a name="x_322"></a>Mercurial lets you perform multiple merges, but
you must commit the results of each individual merge as you
go. This is necessary because Mercurial only tracks two
parents for both revisions and the working directory. While
it would be technically feasible to merge multiple changesets
at once, Mercurial avoids this for simplicity. With multi-way
merges, the risks of user confusion, nasty conflict
resolution, and making a terrible mess of a merge would grow
intolerable.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358735">Merging and renames</h3></div></div></div><p id="x_69a"><a name="x_69a"></a>A surprising number of revision control systems pay little
or no attention to a file's <span class="emphasis"><em>name</em></span> over
time. For instance, it used to be common that if a file got
renamed on one side of a merge, the changes from the other
side would be silently dropped.</p><p id="x_69b"><a name="x_69b"></a>Mercurial records metadata when you tell it to perform a
rename or copy. It uses this metadata during a merge to do the
right thing in the case of a merge. For instance, if I rename
a file, and you edit it without renaming it, when we merge our
work the file will be renamed and have your edits
applied.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id358761">Other interesting design features</h2></div></div></div><p id="x_323"><a name="x_323"></a>In the sections above, I've tried to highlight some of the
most important aspects of Mercurial's design, to illustrate that
it pays careful attention to reliability and performance.
However, the attention to detail doesn't stop there. There are
a number of other aspects of Mercurial's construction that I
personally find interesting. I'll detail a few of them here,
separate from the “<span class="quote">big ticket</span>” items above, so that
if you're interested, you can gain a better idea of the amount
of thinking that goes into a well-designed system.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358780">Clever compression</h3></div></div></div><p id="x_324"><a name="x_324"></a>When appropriate, Mercurial will store both snapshots and
deltas in compressed form. It does this by always
<span class="emphasis"><em>trying to</em></span> compress a snapshot or delta,
but only storing the compressed version if it's smaller than
the uncompressed version.</p><p id="x_325"><a name="x_325"></a>This means that Mercurial does “<span class="quote">the right
thing</span>” when storing a file whose native form is
compressed, such as a <code class="literal">zip</code> archive or a JPEG
image. When these types of files are compressed a second
time, the resulting file is usually bigger than the
once-compressed form, and so Mercurial will store the plain
<code class="literal">zip</code> or JPEG.</p><p id="x_326"><a name="x_326"></a>Deltas between revisions of a compressed file are usually
larger than snapshots of the file, and Mercurial again does
<span class="quote">the right thing</span>” in these cases. It finds that
such a delta exceeds the threshold at which it should store a
complete snapshot of the file, so it stores the snapshot,
again saving space compared to a naive delta-only
approach.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id358828">Network recompression</h4></div></div></div><p id="x_327"><a name="x_327"></a>When storing revisions on disk, Mercurial uses the
<span class="quote">deflate</span>” compression algorithm (the same one
used by the popular <code class="literal">zip</code> archive format),
which balances good speed with a respectable compression
ratio. However, when transmitting revision data over a
network connection, Mercurial uncompresses the compressed
revision data.</p><p id="x_328"><a name="x_328"></a>If the connection is over HTTP, Mercurial recompresses
the entire stream of data using a compression algorithm that
gives a better compression ratio (the Burrows-Wheeler
algorithm from the widely used <code class="literal">bzip2</code>
compression package). This combination of algorithm and
compression of the entire stream (instead of a revision at a
time) substantially reduces the number of bytes to be
transferred, yielding better network performance over most
kinds of network.</p><p id="x_329"><a name="x_329"></a>If the connection is over
<span class="command"><strong>ssh</strong></span>, Mercurial
<span class="emphasis"><em>doesn't</em></span> recompress the stream, because
<span class="command"><strong>ssh</strong></span> can already do this itself. You can
tell Mercurial to always use <span class="command"><strong>ssh</strong></span>'s
compression feature by editing the
<code class="filename">.hgrc</code> file in your home directory as
follows.</p><pre id="id358894" class="programlisting">[ui]
ssh = ssh -C</pre></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358901">Read/write ordering and atomicity</h3></div></div></div><p id="x_32a"><a name="x_32a"></a>Appending to files isn't the whole story when
it comes to guaranteeing that a reader won't see a partial
write. If you recall <a class="xref" href="behind-the-scenes.html#fig:concepts:metadata" title="Figure 4.2. Metadata relationships">Figure 4.2, “Metadata relationships”</a>,
revisions in the changelog point to revisions in the manifest,
and revisions in the manifest point to revisions in filelogs.
This hierarchy is deliberate.</p><p id="x_32b"><a name="x_32b"></a>A writer starts a transaction by writing filelog and
manifest data, and doesn't write any changelog data until
those are finished. A reader starts by reading changelog
data, then manifest data, followed by filelog data.</p><p id="x_32c"><a name="x_32c"></a>Since the writer has always finished writing filelog and
manifest data before it writes to the changelog, a reader will
never read a pointer to a partially written manifest revision
from the changelog, and it will never read a pointer to a
partially written filelog revision from the manifest.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id358935">Concurrent access</h3></div></div></div><p id="x_32d"><a name="x_32d"></a>The read/write ordering and atomicity guarantees mean that
Mercurial never needs to <span class="emphasis"><em>lock</em></span> a
repository when it's reading data, even if the repository is
being written to while the read is occurring. This has a big
effect on scalability; you can have an arbitrary number of
Mercurial processes safely reading data from a repository
all at once, no matter whether it's being written to or
not.</p><p id="x_32e"><a name="x_32e"></a>The lockless nature of reading means that if you're
sharing a repository on a multi-user system, you don't need to
grant other local users permission to
<span class="emphasis"><em>write</em></span> to your repository in order for
them to be able to clone it or pull changes from it; they only
need <span class="emphasis"><em>read</em></span> permission. (This is
<span class="emphasis"><em>not</em></span> a common feature among revision
control systems, so don't take it for granted! Most require
readers to be able to lock a repository to access it safely,
and this requires write permission on at least one directory,
which of course makes for all kinds of nasty and annoying
security and administrative problems.)</p><p id="x_32f"><a name="x_32f"></a>Mercurial uses locks to ensure that only one process can
write to a repository at a time (the locking mechanism is safe
even over filesystems that are notoriously hostile to locking,
such as NFS). If a repository is locked, a writer will wait
for a while to retry if the repository becomes unlocked, but
if the repository remains locked for too long, the process
attempting to write will time out after a while. This means
that your daily automated scripts won't get stuck forever and
pile up if a system crashes unnoticed, for example. (Yes, the
timeout is configurable, from zero to infinity.)</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id358982">Safe dirstate access</h4></div></div></div><p id="x_330"><a name="x_330"></a>As with revision data, Mercurial doesn't take a lock to
read the dirstate file; it does acquire a lock to write it.
To avoid the possibility of reading a partially written copy
of the dirstate file, Mercurial writes to a file with a
unique name in the same directory as the dirstate file, then
renames the temporary file atomically to
<code class="filename">dirstate</code>. The file named
<code class="filename">dirstate</code> is thus guaranteed to be
complete, not partially written.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id359009">Avoiding seeks</h3></div></div></div><p id="x_331"><a name="x_331"></a>Critical to Mercurial's performance is the avoidance of
seeks of the disk head, since any seek is far more expensive
than even a comparatively large read operation.</p><p id="x_332"><a name="x_332"></a>This is why, for example, the dirstate is stored in a
single file. If there were a dirstate file per directory that
Mercurial tracked, the disk would seek once per directory.
Instead, Mercurial reads the entire single dirstate file in
one step.</p><p id="x_333"><a name="x_333"></a>Mercurial also uses a “<span class="quote">copy on write</span>” scheme
when cloning a repository on local storage. Instead of
copying every revlog file from the old repository into the new
repository, it makes a “<span class="quote">hard link</span>”, which is a
shorthand way to say “<span class="quote">these two names point to the same
file</span>”. When Mercurial is about to write to one of a
revlog's files, it checks to see if the number of names
pointing at the file is greater than one. If it is, more than
one repository is using the file, so Mercurial makes a new
copy of the file that is private to this repository.</p><p id="x_334"><a name="x_334"></a>A few revision control developers have pointed out that
this idea of making a complete private copy of a file is not
very efficient in its use of storage. While this is true,
storage is cheap, and this method gives the highest
performance while deferring most book-keeping to the operating
system. An alternative scheme would most likely reduce
performance and increase the complexity of the software, but
speed and simplicity are key to the “<span class="quote">feel</span>” of
day-to-day use.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id359061">Other contents of the dirstate</h3></div></div></div><p id="x_335"><a name="x_335"></a>Because Mercurial doesn't force you to tell it when you're
modifying a file, it uses the dirstate to store some extra
information so it can determine efficiently whether you have
modified a file. For each file in the working directory, it
stores the time that it last modified the file itself, and the
size of the file at that time.</p><p id="x_336"><a name="x_336"></a>When you explicitly <span class="command"><strong>hg
add</strong></span>, <span class="command"><strong>hg remove</strong></span>,
<span class="command"><strong>hg rename</strong></span> or <span class="command"><strong>hg copy</strong></span> files, Mercurial updates the
dirstate so that it knows what to do with those files when you
commit.</p><p id="x_337"><a name="x_337"></a>The dirstate helps Mercurial to efficiently
check the status of files in a repository.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_726"><a name="x_726"></a>When Mercurial checks the state of a file in the
working directory, it first checks a file's modification
time against the time in the dirstate that records when
Mercurial last wrote the file. If the last modified time
is the same as the time when Mercurial wrote the file, the
file must not have been modified, so Mercurial does not
need to check any further.</p></li><li><p id="x_727"><a name="x_727"></a>If the file's size has changed, the file must have
been modified. If the modification time has changed, but
the size has not, only then does Mercurial need to
actually read the contents of the file to see if it has
changed.</p></li></ul></div><p id="x_728"><a name="x_728"></a>Storing the modification time and size dramatically
reduces the number of read operations that Mercurial needs to
perform when we run commands like <span class="command"><strong>hg status</strong></span>.
This results in large performance improvements.</p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id357972" href="#id357972" class="para">3</a>] </sup>It is possible (though unusual) for the manifest to
remain the same between two changesets, in which case the
changelog entries for those changesets will point to the
same revision of the manifest.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="a-tour-of-mercurial-merging-work.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="mercurial-in-daily-use.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 3. A tour of Mercurial: merging work </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 5. Mercurial in daily use</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,967 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 6. Collaborating with other people</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="mercurial-in-daily-use.html" title="Chapter 5. Mercurial in daily use"><link rel="next" href="file-names-and-pattern-matching.html" title="Chapter 7. File names and pattern matching"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 6. Collaborating with other people</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="mercurial-in-daily-use.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="file-names-and-pattern-matching.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="cha:collab"><div class="titlepage"><div><div><h2 class="title">Chapter 6. Collaborating with other people</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="collaborating-with-other-people.html#id370764">Mercurial's web interface</a></span></dt><dt><span class="sect1"><a href="collaborating-with-other-people.html#id371206">Collaboration models</a></span></dt><dd><dl><dt><span class="sect2"><a href="collaborating-with-other-people.html#id371225">Factors to keep in mind</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id371265">Informal anarchy</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id371355">A single central repository</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id371424">A hosted central repository</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id371466">Working with multiple branches</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372365">Feature branches</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372420">The release train</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372519">The Linux kernel model</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372641">Pull-only versus shared-push collaboration</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372699">Where collaboration meets branch management</a></span></dt></dl></dd><dt><span class="sect1"><a href="collaborating-with-other-people.html#id372723">The technical side of sharing</a></span></dt><dt><span class="sect1"><a href="collaborating-with-other-people.html#sec:collab:serve">Informal sharing with hg
serve</a></span></dt><dd><dl><dt><span class="sect2"><a href="collaborating-with-other-people.html#id372918">A few things to keep in mind</a></span></dt></dl></dd><dt><span class="sect1"><a href="collaborating-with-other-people.html#sec:collab:ssh">Using the Secure Shell (ssh) protocol</a></span></dt><dd><dl><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373065">How to read and write ssh URLs</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373261">Finding an ssh client for your system</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373312">Generating a key pair</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373466">Using an authentication agent</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373568">Configuring the server side properly</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id373965">Using compression with ssh</a></span></dt></dl></dd><dt><span class="sect1"><a href="collaborating-with-other-people.html#sec:collab:cgi">Serving over HTTP using CGI</a></span></dt><dd><dl><dt><span class="sect2"><a href="collaborating-with-other-people.html#id374172">Web server configuration checklist</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id374257">Basic CGI configuration</a></span></dt><dd><dl><dt><span class="sect3"><a href="collaborating-with-other-people.html#sec:collab:wtf">What could possibly go
wrong?</a></span></dt><dt><span class="sect3"><a href="collaborating-with-other-people.html#id374655">Configuring lighttpd</a></span></dt></dl></dd><dt><span class="sect2"><a href="collaborating-with-other-people.html#id374764">Sharing multiple repositories with one CGI script</a></span></dt><dd><dl><dt><span class="sect3"><a href="collaborating-with-other-people.html#id375138">Explicitly specifying which repositories to
publish</a></span></dt></dl></dd><dt><span class="sect2"><a href="collaborating-with-other-people.html#id375233">Downloading source archives</a></span></dt><dt><span class="sect2"><a href="collaborating-with-other-people.html#id375279">Web configuration options</a></span></dt><dd><dl><dt><span class="sect3"><a href="collaborating-with-other-people.html#id375762">Options specific to an individual repository</a></span></dt><dt><span class="sect3"><a href="collaborating-with-other-people.html#id375833">Options specific to the hg
serve command</a></span></dt><dt><span class="sect3"><a href="collaborating-with-other-people.html#id375978">Choosing the right ~/.hgrc file to add web items to</a></span></dt></dl></dd></dl></dd><dt><span class="sect1"><a href="collaborating-with-other-people.html#id376085">System-wide configuration</a></span></dt><dd><dl><dt><span class="sect2"><a href="collaborating-with-other-people.html#id376128">Making Mercurial more trusting</a></span></dt></dl></dd></dl></div><p id="x_44a"><a name="x_44a"></a>As a completely decentralised tool, Mercurial doesn't impose
any policy on how people ought to work with each other. However,
if you're new to distributed revision control, it helps to have
some tools and examples in mind when you're thinking about
possible workflow models.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id370764">Mercurial's web interface</h2></div></div></div><p id="x_44b"><a name="x_44b"></a>Mercurial has a powerful web interface that provides several
useful capabilities.</p><p id="x_44c"><a name="x_44c"></a>For interactive use, the web interface lets you browse a
single repository or a collection of repositories. You can view
the history of a repository, examine each change (comments and
diffs), and view the contents of each directory and file. You
can even get a view of history that gives a graphical view of
the relationships between individual changes and merges.</p><p id="x_44d"><a name="x_44d"></a>Also for human consumption, the web interface provides
Atom and RSS feeds of the changes in a repository. This lets you
<span class="quote">subscribe</span>” to a repository using your favorite
feed reader, and be automatically notified of activity in that
repository as soon as it happens. I find this capability much
more convenient than the model of subscribing to a mailing list
to which notifications are sent, as it requires no additional
configuration on the part of whoever is serving the
repository.</p><p id="x_44e"><a name="x_44e"></a>The web interface also lets remote users clone a repository,
pull changes from it, and (when the server is configured to
permit it) push changes back to it. Mercurial's HTTP tunneling
protocol aggressively compresses data, so that it works
efficiently even over low-bandwidth network connections.</p><p id="x_44f"><a name="x_44f"></a>The easiest way to get started with the web interface is to
use your web browser to visit an existing repository, such as
the master Mercurial repository at <a class="ulink" href="http://www.selenic.com/repo/hg" target="_top">http://www.selenic.com/repo/hg</a>.</p><p id="x_450"><a name="x_450"></a>If you're interested in providing a web interface
to your own repositories, there are several good ways to do
this.</p><p id="x_69d"><a name="x_69d"></a>The easiest and fastest way to get started in an informal
environment is to use the <span class="command"><strong>hg
serve</strong></span> command, which is best suited to short-term
<span class="quote">lightweight</span>” serving. See <a class="xref" href="collaborating-with-other-people.html#sec:collab:serve" title="Informal sharing with hg serve">the section called “Informal sharing with hg
serve”</a> below for details of how to use
this command.</p><p id="x_69e"><a name="x_69e"></a>For longer-lived repositories that you'd like to
have permanently available, there are several public hosting
services available. Some are free to open source projects,
while others offer paid commercial hosting. An up-to-date list
is available at <a class="ulink" href="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting" target="_top">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</a>.</p><p id="x_6a0"><a name="x_6a0"></a>If you would prefer to host your own repositories, Mercurial
has built-in support for several popular hosting technologies,
most notably CGI (Common Gateway Interface), and WSGI (Web
Services Gateway Interface). See <a class="xref" href="collaborating-with-other-people.html#sec:collab:cgi" title="Serving over HTTP using CGI">the section called “Serving over HTTP using CGI”</a> for details of CGI and WSGI
configuration.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id371206">Collaboration models</h2></div></div></div><p id="x_451"><a name="x_451"></a>With a suitably flexible tool, making decisions about
workflow is much more of a social engineering challenge than a
technical one. Mercurial imposes few limitations on how you can
structure the flow of work in a project, so it's up to you and
your group to set up and live with a model that matches your own
particular needs.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id371225">Factors to keep in mind</h3></div></div></div><p id="x_452"><a name="x_452"></a>The most important aspect of any model that you must keep
in mind is how well it matches the needs and capabilities of
the people who will be using it. This might seem
self-evident; even so, you still can't afford to forget it for
a moment.</p><p id="x_453"><a name="x_453"></a>I once put together a workflow model that seemed to make
perfect sense to me, but that caused a considerable amount of
consternation and strife within my development team. In spite
of my attempts to explain why we needed a complex set of
branches, and how changes ought to flow between them, a few
team members revolted. Even though they were smart people,
they didn't want to pay attention to the constraints we were
operating under, or face the consequences of those constraints
in the details of the model that I was advocating.</p><p id="x_454"><a name="x_454"></a>Don't sweep foreseeable social or technical problems under
the rug. Whatever scheme you put into effect, you should plan
for mistakes and problem scenarios. Consider adding automated
machinery to prevent, or quickly recover from, trouble that
you can anticipate. As an example, if you intend to have a
branch with not-for-release changes in it, you'd do well to
think early about the possibility that someone might
accidentally merge those changes into a release branch. You
could avoid this particular problem by writing a hook that
prevents changes from being merged from an inappropriate
branch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id371265">Informal anarchy</h3></div></div></div><p id="x_455"><a name="x_455"></a>I wouldn't suggest an “<span class="quote">anything goes</span>
approach as something sustainable, but it's a model that's
easy to grasp, and it works perfectly well in a few unusual
situations.</p><p id="x_456"><a name="x_456"></a>As one example, many projects have a loose-knit group of
collaborators who rarely physically meet each other. Some
groups like to overcome the isolation of working at a distance
by organizing occasional “<span class="quote">sprints</span>”. In a sprint,
a number of people get together in a single location (a
company's conference room, a hotel meeting room, that kind of
place) and spend several days more or less locked in there,
hacking intensely on a handful of projects.</p><p id="x_457"><a name="x_457"></a>A sprint or a hacking session in a coffee shop are the perfect places to use the
<span class="command"><strong>hg serve</strong></span> command, since
<span class="command"><strong>hg serve</strong></span> does not require any
fancy server infrastructure. You can get started with
<span class="command"><strong>hg serve</strong></span> in moments, by
reading <a class="xref" href="collaborating-with-other-people.html#sec:collab:serve" title="Informal sharing with hg serve">the section called “Informal sharing with hg
serve”</a> below. Then simply
tell the person next to you that you're running a server, send
the URL to them in an instant message, and you immediately
have a quick-turnaround way to work together. They can type
your URL into their web browser and quickly review your
changes; or they can pull a bugfix from you and verify it; or
they can clone a branch containing a new feature and try it
out.</p><p id="x_458"><a name="x_458"></a>The charm, and the problem, with doing things
in an ad hoc fashion like this is that only people who know
about your changes, and where they are, can see them. Such an
informal approach simply doesn't scale beyond a handful
people, because each individual needs to know about
<span class="emphasis"><em>n</em></span> different repositories to pull
from.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id371355">A single central repository</h3></div></div></div><p id="x_459"><a name="x_459"></a>For smaller projects migrating from a centralised revision
control tool, perhaps the easiest way to get started is to
have changes flow through a single shared central repository.
This is also the most common “<span class="quote">building block</span>” for
more ambitious workflow schemes.</p><p id="x_45a"><a name="x_45a"></a>Contributors start by cloning a copy of this repository.
They can pull changes from it whenever they need to, and some
(perhaps all) developers have permission to push a change back
when they're ready for other people to see it.</p><p id="x_45b"><a name="x_45b"></a>Under this model, it can still often make sense for people
to pull changes directly from each other, without going
through the central repository. Consider a case in which I
have a tentative bug fix, but I am worried that if I were to
publish it to the central repository, it might subsequently
break everyone else's trees as they pull it. To reduce the
potential for damage, I can ask you to clone my repository
into a temporary repository of your own and test it. This
lets us put off publishing the potentially unsafe change until
it has had a little testing.</p><p id="x_45c"><a name="x_45c"></a>If a team is hosting its own repository in this
kind of scenario, people will usually use the
<span class="command"><strong>ssh</strong></span> protocol to securely push changes to
the central repository, as documented in <a class="xref" href="collaborating-with-other-people.html#sec:collab:ssh" title="Using the Secure Shell (ssh) protocol">the section called “Using the Secure Shell (ssh) protocol”</a>. It's also usual to publish a
read-only copy of the repository over HTTP, as in
<a class="xref" href="collaborating-with-other-people.html#sec:collab:cgi" title="Serving over HTTP using CGI">the section called “Serving over HTTP using CGI”</a>. Publishing over HTTP
satisfies the needs of people who don't have push access, and
those who want to use web browsers to browse the repository's
history.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id371424">A hosted central repository</h3></div></div></div><p id="x_6a1"><a name="x_6a1"></a>A wonderful thing about public hosting services like
<a class="ulink" href="http://bitbucket.org/" target="_top">Bitbucket</a> is that
not only do they handle the fiddly server configuration
details, such as user accounts, authentication, and secure
wire protocols, they provide additional infrastructure to make
this model work well.</p><p id="x_6a2"><a name="x_6a2"></a>For instance, a well-engineered hosting service will let
people clone their own copies of a repository with a single
click. This lets people work in separate spaces and share
their changes when they're ready.</p><p id="x_6a3"><a name="x_6a3"></a>In addition, a good hosting service will let people
communicate with each other, for instance to say “<span class="quote">there
are changes ready for you to review in this
tree</span>”.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id371466">Working with multiple branches</h3></div></div></div><p id="x_45d"><a name="x_45d"></a>Projects of any significant size naturally tend to make
progress on several fronts simultaneously. In the case of
software, it's common for a project to go through periodic
official releases. A release might then go into
<span class="quote">maintenance mode</span>” for a while after its first
publication; maintenance releases tend to contain only bug
fixes, not new features. In parallel with these maintenance
releases, one or more future releases may be under
development. People normally use the word
<span class="quote">branch</span>” to refer to one of these many slightly
different directions in which development is
proceeding.</p><p id="x_45e"><a name="x_45e"></a>Mercurial is particularly well suited to managing a number
of simultaneous, but not identical, branches. Each
<span class="quote">development direction</span>” can live in its own
central repository, and you can merge changes from one to
another as the need arises. Because repositories are
independent of each other, unstable changes in a development
branch will never affect a stable branch unless someone
explicitly merges those changes into the stable branch.</p><p id="x_45f"><a name="x_45f"></a>Here's an example of how this can work in practice. Let's
say you have one “<span class="quote">main branch</span>” on a central
server.</p><pre id="id371865" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init main</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd main</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'This is a boring feature.' &gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'We have reached an important milestone!'</code></strong>
adding myfile
</pre><p id="x_460"><a name="x_460"></a>People clone it, make changes locally, test them, and push
them back.</p><p id="x_461"><a name="x_461"></a>Once the main branch reaches a release milestone, you can
use the <span class="command"><strong>hg tag</strong></span> command to
give a permanent name to the milestone revision.</p><pre id="id371755" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tag v1.0</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 1:47867ad65069
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:20 2009 +0000
summary: Added tag v1.0 for changeset cefe13bbe8af
<code class="prompt">$</code> <strong class="userinput"><code>hg tags</code></strong>
tip 1:47867ad65069
v1.0 0:cefe13bbe8af
</pre><p id="x_462"><a name="x_462"></a>Let's say some ongoing
development occurs on the main branch.</p><pre id="id372110" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../main</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'This is exciting and new!' &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Add a new feature'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
This is a boring feature.
This is exciting and new!
</pre><p id="x_463"><a name="x_463"></a>Using the tag that was recorded at the milestone, people
who clone that repository at any time in the future can use
<span class="command"><strong>hg update</strong></span> to get a copy of
the working directory exactly as it was when that tagged
revision was committed.</p><pre id="id372066" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone -U main main-old</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd main-old</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg update v1.0</code></strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
This is a boring feature.
</pre><p id="x_464"><a name="x_464"></a>In addition, immediately after the main branch is tagged,
we can then clone the main branch on the server to a new
<span class="quote">stable</span>” branch, also on the server.</p><pre id="id372035" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone -rv1.0 main stable</code></strong>
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_465"><a name="x_465"></a>If we need to make a change to the stable
branch, we can then clone <span class="emphasis"><em>that</em></span>
repository, make our changes, commit, and push our changes
back there.</p><pre id="id372474" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg clone stable stable-fix</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd stable-fix</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'This is a fix to a boring feature.' &gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Fix a bug'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg push</code></strong>
pushing to /tmp/branching3sONTi/stable
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
</pre><p id="x_466"><a name="x_466"></a>Because Mercurial repositories are independent, and
Mercurial doesn't move changes around automatically, the
stable and main branches are <span class="emphasis"><em>isolated</em></span>
from each other. The changes that we made on the main branch
don't “<span class="quote">leak</span>” to the stable branch, and vice
versa.</p><p id="x_467"><a name="x_467"></a>We'll often want all of our bugfixes on the stable
branch to show up on the main branch, too. Rather than
rewrite a bugfix on the main branch, we can simply pull and
merge changes from the stable to the main branch, and
Mercurial will bring those bugfixes in for us.</p><pre id="id372450" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../main</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg pull ../stable</code></strong>
pulling from ../stable
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
<code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
merging myfile
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Bring in bugfix from stable branch'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
This is a fix to a boring feature.
This is exciting and new!
</pre><p id="x_468"><a name="x_468"></a>The main branch will still contain changes that
are not on the stable branch, but it will also contain all of
the bugfixes from the stable branch. The stable branch
remains unaffected by these changes, since changes are only
flowing from the stable to the main branch, and not the other
way.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372365">Feature branches</h3></div></div></div><p id="x_469"><a name="x_469"></a>For larger projects, an effective way to manage change is
to break up a team into smaller groups. Each group has a
shared branch of its own, cloned from a single
<span class="quote">master</span>” branch used by the entire project.
People working on an individual branch are typically quite
isolated from developments on other branches.</p><div class="figure"><a name="fig:collab:feature-branches"></a><p class="title"><b>Figure 6.1. Feature branches</b></p><div class="figure-contents"><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="100%"><tr><td><img src="figs/feature-branches.png" width="100%" alt="XXX add text"></td></tr></table></div></div></div><br class="figure-break"><p id="x_46b"><a name="x_46b"></a>When a particular feature is deemed to be in suitable
shape, someone on that feature team pulls and merges from the
master branch into the feature branch, then pushes back up to
the master branch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372420">The release train</h3></div></div></div><p id="x_46c"><a name="x_46c"></a>Some projects are organized on a “<span class="quote">train</span>
basis: a release is scheduled to happen every few months, and
whatever features are ready when the “<span class="quote">train</span>” is
ready to leave are allowed in.</p><p id="x_46d"><a name="x_46d"></a>This model resembles working with feature branches. The
difference is that when a feature branch misses a train,
someone on the feature team pulls and merges the changes that
went out on that train release into the feature branch, and
the team continues its work on top of that release so that
their feature can make the next release.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372519">The Linux kernel model</h3></div></div></div><p id="x_46e"><a name="x_46e"></a>The development of the Linux kernel has a shallow
hierarchical structure, surrounded by a cloud of apparent
chaos. Because most Linux developers use
<span class="command"><strong>git</strong></span>, a distributed revision control tool
with capabilities similar to Mercurial, it's useful to
describe the way work flows in that environment; if you like
the ideas, the approach translates well across tools.</p><p id="x_46f"><a name="x_46f"></a>At the center of the community sits Linus Torvalds, the
creator of Linux. He publishes a single source repository
that is considered the “<span class="quote">authoritative</span>” current
tree by the entire developer community. Anyone can clone
Linus's tree, but he is very choosy about whose trees he pulls
from.</p><p id="x_470"><a name="x_470"></a>Linus has a number of “<span class="quote">trusted lieutenants</span>”.
As a general rule, he pulls whatever changes they publish, in
most cases without even reviewing those changes. Some of
those lieutenants are generally agreed to be
<span class="quote">maintainers</span>”, responsible for specific
subsystems within the kernel. If a random kernel hacker wants
to make a change to a subsystem that they want to end up in
Linus's tree, they must find out who the subsystem's
maintainer is, and ask that maintainer to take their change.
If the maintainer reviews their changes and agrees to take
them, they'll pass them along to Linus in due course.</p><p id="x_471"><a name="x_471"></a>Individual lieutenants have their own approaches to
reviewing, accepting, and publishing changes; and for deciding
when to feed them to Linus. In addition, there are several
well known branches that people use for different purposes.
For example, a few people maintain “<span class="quote">stable</span>
repositories of older versions of the kernel, to which they
apply critical fixes as needed. Some maintainers publish
multiple trees: one for experimental changes; one for changes
that they are about to feed upstream; and so on. Others just
publish a single tree.</p><p id="x_472"><a name="x_472"></a>This model has two notable features. The first is that
it's “<span class="quote">pull only</span>”. You have to ask, convince, or
beg another developer to take a change from you, because there
are almost no trees to which more than one person can push,
and there's no way to push changes into a tree that someone
else controls.</p><p id="x_473"><a name="x_473"></a>The second is that it's based on reputation and acclaim.
If you're an unknown, Linus will probably ignore changes from
you without even responding. But a subsystem maintainer will
probably review them, and will likely take them if they pass
their criteria for suitability. The more “<span class="quote">good</span>
changes you contribute to a maintainer, the more likely they
are to trust your judgment and accept your changes. If you're
well-known and maintain a long-lived branch for something
Linus hasn't yet accepted, people with similar interests may
pull your changes regularly to keep up with your work.</p><p id="x_474"><a name="x_474"></a>Reputation and acclaim don't necessarily cross subsystem
or “<span class="quote">people</span>” boundaries. If you're a respected
but specialised storage hacker, and you try to fix a
networking bug, that change will receive a level of scrutiny
from a network maintainer comparable to a change from a
complete stranger.</p><p id="x_475"><a name="x_475"></a>To people who come from more orderly project backgrounds,
the comparatively chaotic Linux kernel development process
often seems completely insane. It's subject to the whims of
individuals; people make sweeping changes whenever they deem
it appropriate; and the pace of development is astounding.
And yet Linux is a highly successful, well-regarded piece of
software.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372641">Pull-only versus shared-push collaboration</h3></div></div></div><p id="x_476"><a name="x_476"></a>A perpetual source of heat in the open source community is
whether a development model in which people only ever pull
changes from others is “<span class="quote">better than</span>” one in which
multiple people can push changes to a shared
repository.</p><p id="x_477"><a name="x_477"></a>Typically, the backers of the shared-push model use tools
that actively enforce this approach. If you're using a
centralised revision control tool such as Subversion, there's
no way to make a choice over which model you'll use: the tool
gives you shared-push, and if you want to do anything else,
you'll have to roll your own approach on top (such as applying
a patch by hand).</p><p id="x_478"><a name="x_478"></a>A good distributed revision control tool will
support both models. You and your collaborators can then
structure how you work together based on your own needs and
preferences, not on what contortions your tools force you
into.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372699">Where collaboration meets branch management</h3></div></div></div><p id="x_479"><a name="x_479"></a>Once you and your team set up some shared
repositories and start propagating changes back and forth
between local and shared repos, you begin to face a related,
but slightly different challenge: that of managing the
multiple directions in which your team may be moving at once.
Even though this subject is intimately related to how your
team collaborates, it's dense enough to merit treatment of its
own, in <a class="xref" href="managing-releases-and-branchy-development.html" title="Chapter 8. Managing releases and branchy development">Chapter 8, <i>Managing releases and branchy development</i></a>.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id372723">The technical side of sharing</h2></div></div></div><p id="x_47a"><a name="x_47a"></a>The remainder of this chapter is devoted to the question of
sharing changes with your collaborators.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:collab:serve">Informal sharing with <span class="command"><strong>hg
serve</strong></span></h2></div></div></div><p id="x_47b"><a name="x_47b"></a>Mercurial's <span class="command"><strong>hg serve</strong></span>
command is wonderfully suited to small, tight-knit, and
fast-paced group environments. It also provides a great way to
get a feel for using Mercurial commands over a network.</p><p id="x_47c"><a name="x_47c"></a>Run <span class="command"><strong>hg serve</strong></span> inside a
repository, and in under a second it will bring up a specialised
HTTP server; this will accept connections from any client, and
serve up data for that repository until you terminate it.
Anyone who knows the URL of the server you just started, and can
talk to your computer over the network, can then use a web
browser or Mercurial to read data from that repository. A URL
for a <span class="command"><strong>hg serve</strong></span> instance running
on a laptop is likely to look something like
<code class="literal">http://my-laptop.local:8000/</code>.</p><p id="x_47d"><a name="x_47d"></a>The <span class="command"><strong>hg serve</strong></span> command is
<span class="emphasis"><em>not</em></span> a general-purpose web server. It can do
only two things:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_47e"><a name="x_47e"></a>Allow people to browse the history of the
repository it's serving, from their normal web
browsers.</p></li><li><p id="x_47f"><a name="x_47f"></a>Speak Mercurial's wire protocol, so that people
can <span class="command"><strong>hg clone</strong></span> or <span class="command"><strong>hg pull</strong></span> changes from that
repository.</p></li></ul></div><p id="x_480"><a name="x_480"></a>In particular, <span class="command"><strong>hg serve</strong></span>
won't allow remote users to <span class="emphasis"><em>modify</em></span> your
repository. It's intended for read-only use.</p><p id="x_481"><a name="x_481"></a>If you're getting started with Mercurial, there's nothing to
prevent you from using <span class="command"><strong>hg serve</strong></span>
to serve up a repository on your own computer, then use commands
like <span class="command"><strong>hg clone</strong></span>, <span class="command"><strong>hg incoming</strong></span>, and so on to talk to that
server as if the repository was hosted remotely. This can help
you to quickly get acquainted with using commands on
network-hosted repositories.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id372918">A few things to keep in mind</h3></div></div></div><p id="x_482"><a name="x_482"></a>Because it provides unauthenticated read access to all
clients, you should only use <span class="command"><strong>hg
serve</strong></span> in an environment where you either don't
care, or have complete control over, who can access your
network and pull data from your repository.</p><p id="x_483"><a name="x_483"></a>The <span class="command"><strong>hg serve</strong></span> command
knows nothing about any firewall software you might have
installed on your system or network. It cannot detect or
control your firewall software. If other people are unable to
talk to a running <span class="command"><strong>hg serve</strong></span>
instance, the second thing you should do
(<span class="emphasis"><em>after</em></span> you make sure that they're using
the correct URL) is check your firewall configuration.</p><p id="x_484"><a name="x_484"></a>By default, <span class="command"><strong>hg serve</strong></span>
listens for incoming connections on port 8000. If another
process is already listening on the port you want to use, you
can specify a different port to listen on using the <code class="option">-p</code> option.</p><p id="x_485"><a name="x_485"></a>Normally, when <span class="command"><strong>hg serve</strong></span>
starts, it prints no output, which can be a bit unnerving. If
you'd like to confirm that it is indeed running correctly, and
find out what URL you should send to your collaborators, start
it with the <code class="option">-v</code>
option.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:collab:ssh">Using the Secure Shell (ssh) protocol</h2></div></div></div><p id="x_486"><a name="x_486"></a>You can pull and push changes securely over a network
connection using the Secure Shell (<code class="literal">ssh</code>)
protocol. To use this successfully, you may have to do a little
bit of configuration on the client or server sides.</p><p id="x_487"><a name="x_487"></a>If you're not familiar with ssh, it's the name of
both a command and a network protocol that let you securely
communicate with another computer. To use it with Mercurial,
you'll be setting up one or more user accounts on a server so
that remote users can log in and execute commands.</p><p id="x_488"><a name="x_488"></a>(If you <span class="emphasis"><em>are</em></span> familiar with ssh, you'll
probably find some of the material that follows to be elementary
in nature.)</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373065">How to read and write ssh URLs</h3></div></div></div><p id="x_489"><a name="x_489"></a>An ssh URL tends to look like this:</p><pre id="id373079" class="programlisting">ssh://bos@hg.serpentine.com:22/hg/hgbook</pre><div class="orderedlist"><ol type="1"><li><p id="x_48a"><a name="x_48a"></a>The “<span class="quote"><code class="literal">ssh://</code></span>
part tells Mercurial to use the ssh protocol.</p></li><li><p id="x_48b"><a name="x_48b"></a>The “<span class="quote"><code class="literal">bos@</code></span>
component indicates what username to log into the server
as. You can leave this out if the remote username is the
same as your local username.</p></li><li><p id="x_48c"><a name="x_48c"></a>The
<span class="quote"><code class="literal">hg.serpentine.com</code></span>” gives
the hostname of the server to log into.</p></li><li><p id="x_48d"><a name="x_48d"></a>The “<span class="quote">:22</span>” identifies the port
number to connect to the server on. The default port is
22, so you only need to specify a colon and port number if
you're <span class="emphasis"><em>not</em></span> using port 22.</p></li><li><p id="x_48e"><a name="x_48e"></a>The remainder of the URL is the local path to
the repository on the server.</p></li></ol></div><p id="x_48f"><a name="x_48f"></a>There's plenty of scope for confusion with the path
component of ssh URLs, as there is no standard way for tools
to interpret it. Some programs behave differently than others
when dealing with these paths. This isn't an ideal situation,
but it's unlikely to change. Please read the following
paragraphs carefully.</p><p id="x_490"><a name="x_490"></a>Mercurial treats the path to a repository on the server as
relative to the remote user's home directory. For example, if
user <code class="literal">foo</code> on the server has a home directory
of <code class="filename">/home/foo</code>, then an
ssh URL that contains a path component of <code class="filename">bar</code> <span class="emphasis"><em>really</em></span>
refers to the directory <code class="filename">/home/foo/bar</code>.</p><p id="x_491"><a name="x_491"></a>If you want to specify a path relative to another user's
home directory, you can use a path that starts with a tilde
character followed by the user's name (let's call them
<code class="literal">otheruser</code>), like this.</p><pre id="id373236" class="programlisting">ssh://server/~otheruser/hg/repo</pre><p id="x_492"><a name="x_492"></a>And if you really want to specify an
<span class="emphasis"><em>absolute</em></span> path on the server, begin the
path component with two slashes, as in this example.</p><pre id="id373254" class="programlisting">ssh://server//absolute/path</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373261">Finding an ssh client for your system</h3></div></div></div><p id="x_493"><a name="x_493"></a>Almost every Unix-like system comes with OpenSSH
preinstalled. If you're using such a system, run
<code class="literal">which ssh</code> to find out if the
<span class="command"><strong>ssh</strong></span> command is installed (it's usually in
<code class="filename">/usr/bin</code>). In the
unlikely event that it isn't present, take a look at your
system documentation to figure out how to install it.</p><p id="x_494"><a name="x_494"></a>On Windows, the TortoiseHg package is bundled
with a version of Simon Tatham's excellent
<span class="command"><strong>plink</strong></span> command, and you should not need to
do any further configuration.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373312">Generating a key pair</h3></div></div></div><p id="x_499"><a name="x_499"></a>To avoid the need to repetitively type a
password every time you need to use your ssh client, I
recommend generating a key pair.</p><div class="tip"><table border="0" summary="Tip: Key pairs are not mandatory"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Key pairs are not mandatory</th></tr><tr><td align="left" valign="top"><p id="x_6a4"><a name="x_6a4"></a>Mercurial knows nothing about ssh authentication or key
pairs. You can, if you like, safely ignore this section and
the one that follows until you grow tired of repeatedly
typing ssh passwords.</p></td></tr></table></div><div class="itemizedlist"><ul type="disc"><li><p id="x_6a5"><a name="x_6a5"></a>On a Unix-like system, the
<span class="command"><strong>ssh-keygen</strong></span> command will do the
trick.</p><p id="x_6a6"><a name="x_6a6"></a>On Windows, if you're using TortoiseHg, you may need
to download a command named <span class="command"><strong>puttygen</strong></span>
from <a class="ulink" href="http://www.chiark.greenend.org.uk/~sgtatham/putty" target="_top">the
PuTTY web site</a> to generate a key pair. See
<a class="ulink" href="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen" target="_top">the
<span class="command"><strong>puttygen</strong></span> documentation</a> for
details of how use the command.</p></li></ul></div><p id="x_49a"><a name="x_49a"></a>When you generate a key pair, it's usually
<span class="emphasis"><em>highly</em></span> advisable to protect it with a
passphrase. (The only time that you might not want to do this
is when you're using the ssh protocol for automated tasks on a
secure network.)</p><p id="x_49b"><a name="x_49b"></a>Simply generating a key pair isn't enough, however.
You'll need to add the public key to the set of authorised
keys for whatever user you're logging in remotely as. For
servers using OpenSSH (the vast majority), this will mean
adding the public key to a list in a file called <code class="filename">authorized_keys</code> in their <code class="filename">.ssh</code>
directory.</p><p id="x_49c"><a name="x_49c"></a>On a Unix-like system, your public key will have a
<code class="filename">.pub</code> extension. If you're using
<span class="command"><strong>puttygen</strong></span> on Windows, you can save the
public key to a file of your choosing, or paste it from the
window it's displayed in straight into the <code class="filename">authorized_keys</code> file.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373466">Using an authentication agent</h3></div></div></div><p id="x_49d"><a name="x_49d"></a>An authentication agent is a daemon that stores
passphrases in memory (so it will forget passphrases if you
log out and log back in again). An ssh client will notice if
it's running, and query it for a passphrase. If there's no
authentication agent running, or the agent doesn't store the
necessary passphrase, you'll have to type your passphrase
every time Mercurial tries to communicate with a server on
your behalf (e.g. whenever you pull or push changes).</p><p id="x_49e"><a name="x_49e"></a>The downside of storing passphrases in an agent is that
it's possible for a well-prepared attacker to recover the
plain text of your passphrases, in some cases even if your
system has been power-cycled. You should make your own
judgment as to whether this is an acceptable risk. It
certainly saves a lot of repeated typing.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_49f"><a name="x_49f"></a>On Unix-like systems, the agent is called
<span class="command"><strong>ssh-agent</strong></span>, and it's often run
automatically for you when you log in. You'll need to use
the <span class="command"><strong>ssh-add</strong></span> command to add passphrases
to the agent's store.</p></li><li><p id="x_6a7"><a name="x_6a7"></a>On Windows, if you're using TortoiseHg, the
<span class="command"><strong>pageant</strong></span> command acts as the agent. As
with <span class="command"><strong>puttygen</strong></span>, you'll need to <a class="ulink" href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html" target="_top">download
<span class="command"><strong>pageant</strong></span></a> from the PuTTY web
site and read <a class="ulink" href="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant" target="_top">its
documentation</a>. The <span class="command"><strong>pageant</strong></span>
command adds an icon to your system tray that will let you
manage stored passphrases.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373568">Configuring the server side properly</h3></div></div></div><p id="x_4a0"><a name="x_4a0"></a>Because ssh can be fiddly to set up if you're new to it,
a variety of things can go wrong. Add Mercurial
on top, and there's plenty more scope for head-scratching.
Most of these potential problems occur on the server side, not
the client side. The good news is that once you've gotten a
configuration working, it will usually continue to work
indefinitely.</p><p id="x_4a1"><a name="x_4a1"></a>Before you try using Mercurial to talk to an ssh server,
it's best to make sure that you can use the normal
<span class="command"><strong>ssh</strong></span> or <span class="command"><strong>putty</strong></span> command to
talk to the server first. If you run into problems with using
these commands directly, Mercurial surely won't work. Worse,
it will obscure the underlying problem. Any time you want to
debug ssh-related Mercurial problems, you should drop back to
making sure that plain ssh client commands work first,
<span class="emphasis"><em>before</em></span> you worry about whether there's a
problem with Mercurial.</p><p id="x_4a2"><a name="x_4a2"></a>The first thing to be sure of on the server side is that
you can actually log in from another machine at all. If you
can't use <span class="command"><strong>ssh</strong></span> or <span class="command"><strong>putty</strong></span>
to log in, the error message you get may give you a few hints
as to what's wrong. The most common problems are as
follows.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4a3"><a name="x_4a3"></a>If you get a “<span class="quote">connection refused</span>
error, either there isn't an SSH daemon running on the
server at all, or it's inaccessible due to firewall
configuration.</p></li><li><p id="x_4a4"><a name="x_4a4"></a>If you get a “<span class="quote">no route to host</span>
error, you either have an incorrect address for the server
or a seriously locked down firewall that won't admit its
existence at all.</p></li><li><p id="x_4a5"><a name="x_4a5"></a>If you get a “<span class="quote">permission denied</span>
error, you may have mistyped the username on the server,
or you could have mistyped your key's passphrase or the
remote user's password.</p></li></ul></div><p id="x_4a6"><a name="x_4a6"></a>In summary, if you're having trouble talking to the
server's ssh daemon, first make sure that one is running at
all. On many systems it will be installed, but disabled, by
default. Once you're done with this step, you should then
check that the server's firewall is configured to allow
incoming connections on the port the ssh daemon is listening
on (usually 22). Don't worry about more exotic possibilities
for misconfiguration until you've checked these two
first.</p><p id="x_4a7"><a name="x_4a7"></a>If you're using an authentication agent on the client side
to store passphrases for your keys, you ought to be able to
log into the server without being prompted for a passphrase or
a password. If you're prompted for a passphrase, there are a
few possible culprits.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4a8"><a name="x_4a8"></a>You might have forgotten to use
<span class="command"><strong>ssh-add</strong></span> or <span class="command"><strong>pageant</strong></span>
to store the passphrase.</p></li><li><p id="x_4a9"><a name="x_4a9"></a>You might have stored the passphrase for the
wrong key.</p></li></ul></div><p id="x_4aa"><a name="x_4aa"></a>If you're being prompted for the remote user's password,
there are another few possible problems to check.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4ab"><a name="x_4ab"></a>Either the user's home directory or their
<code class="filename">.ssh</code>
directory might have excessively liberal permissions. As
a result, the ssh daemon will not trust or read their
<code class="filename">authorized_keys</code> file.
For example, a group-writable home or <code class="filename">.ssh</code>
directory will often cause this symptom.</p></li><li><p id="x_4ac"><a name="x_4ac"></a>The user's <code class="filename">authorized_keys</code> file may have
a problem. If anyone other than the user owns or can write
to that file, the ssh daemon will not trust or read
it.</p></li></ul></div><p id="x_4ad"><a name="x_4ad"></a>In the ideal world, you should be able to run the
following command successfully, and it should print exactly
one line of output, the current date and time.</p><pre id="id373809" class="programlisting">ssh myserver date</pre><p id="x_4ae"><a name="x_4ae"></a>If, on your server, you have login scripts that print
banners or other junk even when running non-interactive
commands like this, you should fix them before you continue,
so that they only print output if they're run interactively.
Otherwise these banners will at least clutter up Mercurial's
output. Worse, they could potentially cause problems with
running Mercurial commands remotely. Mercurial tries to
detect and ignore banners in non-interactive
<span class="command"><strong>ssh</strong></span> sessions, but it is not foolproof. (If
you're editing your login scripts on your server, the usual
way to see if a login script is running in an interactive
shell is to check the return code from the command
<code class="literal">tty -s</code>.)</p><p id="x_4af"><a name="x_4af"></a>Once you've verified that plain old ssh is working with
your server, the next step is to ensure that Mercurial runs on
the server. The following command should run
successfully:</p><pre id="id373847" class="programlisting">ssh myserver hg version</pre><p id="x_4b0"><a name="x_4b0"></a>If you see an error message instead of normal <span class="command"><strong>hg version</strong></span> output, this is usually
because you haven't installed Mercurial to <code class="filename">/usr/bin</code>. Don't worry if this
is the case; you don't need to do that. But you should check
for a few possible problems.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4b1"><a name="x_4b1"></a>Is Mercurial really installed on the server at
all? I know this sounds trivial, but it's worth
checking!</p></li><li><p id="x_4b2"><a name="x_4b2"></a>Maybe your shell's search path (usually set
via the <code class="envar">PATH</code> environment variable) is
simply misconfigured.</p></li><li><p id="x_4b3"><a name="x_4b3"></a>Perhaps your <code class="envar">PATH</code> environment
variable is only being set to point to the location of the
<span class="command"><strong>hg</strong></span> executable if the login session is
interactive. This can happen if you're setting the path
in the wrong shell login script. See your shell's
documentation for details.</p></li><li><p id="x_4b4"><a name="x_4b4"></a>The <code class="envar">PYTHONPATH</code> environment
variable may need to contain the path to the Mercurial
Python modules. It might not be set at all; it could be
incorrect; or it may be set only if the login is
interactive.</p></li></ul></div><p id="x_4b5"><a name="x_4b5"></a>If you can run <span class="command"><strong>hg version</strong></span>
over an ssh connection, well done! You've got the server and
client sorted out. You should now be able to use Mercurial to
access repositories hosted by that username on that server.
If you run into problems with Mercurial and ssh at this point,
try using the <code class="option">--debug</code>
option to get a clearer picture of what's going on.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id373965">Using compression with ssh</h3></div></div></div><p id="x_4b6"><a name="x_4b6"></a>Mercurial does not compress data when it uses the ssh
protocol, because the ssh protocol can transparently compress
data. However, the default behavior of ssh clients is
<span class="emphasis"><em>not</em></span> to request compression.</p><p id="x_4b7"><a name="x_4b7"></a>Over any network other than a fast LAN (even a wireless
network), using compression is likely to significantly speed
up Mercurial's network operations. For example, over a WAN,
someone measured compression as reducing the amount of time
required to clone a particularly large repository from 51
minutes to 17 minutes.</p><p id="x_4b8"><a name="x_4b8"></a>Both <span class="command"><strong>ssh</strong></span> and <span class="command"><strong>plink</strong></span>
accept a <code class="option">-C</code> option which
turns on compression. You can easily edit your <code class="filename">~/.hgrc</code> to enable compression for
all of Mercurial's uses of the ssh protocol. Here is how to
do so for regular <span class="command"><strong>ssh</strong></span> on Unix-like systems,
for example.</p><pre id="id374033" class="programlisting">[ui]
ssh = ssh -C</pre><p id="x_4b9"><a name="x_4b9"></a>If you use <span class="command"><strong>ssh</strong></span> on a
Unix-like system, you can configure it to always use
compression when talking to your server. To do this, edit
your <code class="filename">.ssh/config</code> file
(which may not yet exist), as follows.</p><pre id="id374061" class="programlisting">Host hg
Compression yes
HostName hg.example.com</pre><p id="x_4ba"><a name="x_4ba"></a>This defines a hostname alias,
<code class="literal">hg</code>. When you use that hostname on the
<span class="command"><strong>ssh</strong></span> command line or in a Mercurial
<code class="literal">ssh</code>-protocol URL, it will cause
<span class="command"><strong>ssh</strong></span> to connect to
<code class="literal">hg.example.com</code> and use compression. This
gives you both a shorter name to type and compression, each of
which is a good thing in its own right.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:collab:cgi">Serving over HTTP using CGI</h2></div></div></div><p id="x_6a8"><a name="x_6a8"></a>The simplest way to host one or more repositories in a
permanent way is to use a web server and Mercurial's CGI
support.</p><p id="x_4bb"><a name="x_4bb"></a>Depending on how ambitious you are, configuring Mercurial's
CGI interface can take anything from a few moments to several
hours.</p><p id="x_4bc"><a name="x_4bc"></a>We'll begin with the simplest of examples, and work our way
towards a more complex configuration. Even for the most basic
case, you're almost certainly going to need to read and modify
your web server's configuration.</p><div class="note"><table border="0" summary="Note: High pain tolerance required"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">High pain tolerance required</th></tr><tr><td align="left" valign="top"><p id="x_4bd"><a name="x_4bd"></a>Configuring a web server is a complex, fiddly,
and highly system-dependent activity. I can't possibly give
you instructions that will cover anything like all of the
cases you will encounter. Please use your discretion and
judgment in following the sections below. Be prepared to make
plenty of mistakes, and to spend a lot of time reading your
server's error logs.</p><p id="x_6a9"><a name="x_6a9"></a>If you don't have a strong stomach for tweaking
configurations over and over, or a compelling need to host
your own services, you might want to try one of the public
hosting services that I mentioned earlier.</p></td></tr></table></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id374172">Web server configuration checklist</h3></div></div></div><p id="x_4be"><a name="x_4be"></a>Before you continue, do take a few moments to check a few
aspects of your system's setup.</p><div class="orderedlist"><ol type="1"><li><p id="x_4bf"><a name="x_4bf"></a>Do you have a web server installed
at all? Mac OS X and some Linux distributions ship with
Apache, but many other systems may not have a web server
installed.</p></li><li><p id="x_4c0"><a name="x_4c0"></a>If you have a web server installed, is it
actually running? On most systems, even if one is
present, it will be disabled by default.</p></li><li><p id="x_4c1"><a name="x_4c1"></a>Is your server configured to allow you to run
CGI programs in the directory where you plan to do so?
Most servers default to explicitly disabling the ability
to run CGI programs.</p></li></ol></div><p id="x_4c2"><a name="x_4c2"></a>If you don't have a web server installed, and don't have
substantial experience configuring Apache, you should consider
using the <code class="literal">lighttpd</code> web server instead of
Apache. Apache has a well-deserved reputation for baroque and
confusing configuration. While <code class="literal">lighttpd</code> is
less capable in some ways than Apache, most of these
capabilities are not relevant to serving Mercurial
repositories. And <code class="literal">lighttpd</code> is undeniably
<span class="emphasis"><em>much</em></span> easier to get started with than
Apache.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id374257">Basic CGI configuration</h3></div></div></div><p id="x_4c3"><a name="x_4c3"></a>On Unix-like systems, it's common for users to have a
subdirectory named something like <code class="filename">public_html</code> in their home
directory, from which they can serve up web pages. A file
named <code class="filename">foo</code> in this directory will be
accessible at a URL of the form
<code class="literal">http://www.example.com/username/foo</code>.</p><p id="x_4c4"><a name="x_4c4"></a>To get started, find the <code class="filename">hgweb.cgi</code> script that should be
present in your Mercurial installation. If you can't quickly
find a local copy on your system, simply download one from the
master Mercurial repository at <a class="ulink" href="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi" target="_top">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</a>.</p><p id="x_4c5"><a name="x_4c5"></a>You'll need to copy this script into your <code class="filename">public_html</code> directory, and
ensure that it's executable.</p><pre id="id374331" class="programlisting">cp .../hgweb.cgi ~/public_html
chmod 755 ~/public_html/hgweb.cgi</pre><p id="x_4c6"><a name="x_4c6"></a>The <code class="literal">755</code> argument to
<span class="command"><strong>chmod</strong></span> is a little more general than just
making the script executable: it ensures that the script is
executable by anyone, and that “<span class="quote">group</span>” and
<span class="quote">other</span>” write permissions are
<span class="emphasis"><em>not</em></span> set. If you were to leave those
write permissions enabled, Apache's <code class="literal">suexec</code>
subsystem would likely refuse to execute the script. In fact,
<code class="literal">suexec</code> also insists that the
<span class="emphasis"><em>directory</em></span> in which the script resides
must not be writable by others.</p><pre id="id374386" class="programlisting">chmod 755 ~/public_html</pre><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="sec:collab:wtf">What could <span class="emphasis"><em>possibly</em></span> go
wrong?</h4></div></div></div><p id="x_4c7"><a name="x_4c7"></a>Once you've copied the CGI script into place,
go into a web browser, and try to open the URL
<code class="literal">http://myhostname/~myuser/hgweb.cgi</code>,
<span class="emphasis"><em>but</em></span> brace yourself for instant failure.
There's a high probability that trying to visit this URL
will fail, and there are many possible reasons for this. In
fact, you're likely to stumble over almost every one of the
possible errors below, so please read carefully. The
following are all of the problems I ran into on a system
running Fedora 7, with a fresh installation of Apache, and a
user account that I created specially to perform this
exercise.</p><p id="x_4c8"><a name="x_4c8"></a>Your web server may have per-user directories disabled.
If you're using Apache, search your config file for a
<code class="literal">UserDir</code> directive. If there's none
present, per-user directories will be disabled. If one
exists, but its value is <code class="literal">disabled</code>, then
per-user directories will be disabled. Otherwise, the
string after <code class="literal">UserDir</code> gives the name of
the subdirectory that Apache will look in under your home
directory, for example <code class="filename">public_html</code>.</p><p id="x_4c9"><a name="x_4c9"></a>Your file access permissions may be too restrictive.
The web server must be able to traverse your home directory
and directories under your <code class="filename">public_html</code> directory, and
read files under the latter too. Here's a quick recipe to
help you to make your permissions more appropriate.</p><pre id="id374480" class="programlisting">chmod 755 ~
find ~/public_html -type d -print0 | xargs -0r chmod 755
find ~/public_html -type f -print0 | xargs -0r chmod 644</pre><p id="x_4ca"><a name="x_4ca"></a>The other possibility with permissions is that you might
get a completely empty window when you try to load the
script. In this case, it's likely that your access
permissions are <span class="emphasis"><em>too permissive</em></span>. Apache's
<code class="literal">suexec</code> subsystem won't execute a script
that's group- or world-writable, for example.</p><p id="x_4cb"><a name="x_4cb"></a>Your web server may be configured to disallow execution
of CGI programs in your per-user web directory. Here's
Apache's default per-user configuration from my Fedora
system.</p><pre id="id374862" class="programlisting">&lt;Directory /home/*/public_html&gt;
AllowOverride FileInfo AuthConfig Limit
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
&lt;Limit GET POST OPTIONS&gt;
Order allow,deny
Allow from all
&lt;/Limit&gt;
&lt;LimitExcept GET POST OPTIONS&gt;
Order deny,allow Deny from all
&lt;/LimitExcept&gt;
&lt;/Directory&gt;</pre><p id="x_4cc"><a name="x_4cc"></a>If you find a similar-looking
<code class="literal">Directory</code> group in your Apache
configuration, the directive to look at inside it is
<code class="literal">Options</code>. Add <code class="literal">ExecCGI</code>
to the end of this list if it's missing, and restart the web
server.</p><p id="x_4cd"><a name="x_4cd"></a>If you find that Apache serves you the text of the CGI
script instead of executing it, you may need to either
uncomment (if already present) or add a directive like
this.</p><pre id="id374571" class="programlisting">AddHandler cgi-script .cgi</pre><p id="x_4ce"><a name="x_4ce"></a>The next possibility is that you might be served with a
colourful Python backtrace claiming that it can't import a
<code class="literal">mercurial</code>-related module. This is
actually progress! The server is now capable of executing
your CGI script. This error is only likely to occur if
you're running a private installation of Mercurial, instead
of a system-wide version. Remember that the web server runs
the CGI program without any of the environment variables
that you take for granted in an interactive session. If
this error happens to you, edit your copy of <code class="filename">hgweb.cgi</code> and follow the
directions inside it to correctly set your
<code class="envar">PYTHONPATH</code> environment variable.</p><p id="x_4cf"><a name="x_4cf"></a>Finally, you are <span class="emphasis"><em>certain</em></span> to be
served with another colourful Python backtrace: this one
will complain that it can't find <code class="filename">/path/to/repository</code>. Edit
your <code class="filename">hgweb.cgi</code> script
and replace the <code class="filename">/path/to/repository</code> string
with the complete path to the repository you want to serve
up.</p><p id="x_4d0"><a name="x_4d0"></a>At this point, when you try to reload the page, you
should be presented with a nice HTML view of your
repository's history. Whew!</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id374655">Configuring lighttpd</h4></div></div></div><p id="x_4d1"><a name="x_4d1"></a>To be exhaustive in my experiments, I tried configuring
the increasingly popular <code class="literal">lighttpd</code> web
server to serve the same repository as I described with
Apache above. I had already overcome all of the problems I
outlined with Apache, many of which are not server-specific.
As a result, I was fairly sure that my file and directory
permissions were good, and that my <code class="filename">hgweb.cgi</code> script was properly
edited.</p><p id="x_4d2"><a name="x_4d2"></a>Once I had Apache running, getting
<code class="literal">lighttpd</code> to serve the repository was a
snap (in other words, even if you're trying to use
<code class="literal">lighttpd</code>, you should read the Apache
section). I first had to edit the
<code class="literal">mod_access</code> section of its config file to
enable <code class="literal">mod_cgi</code> and
<code class="literal">mod_userdir</code>, both of which were disabled
by default on my system. I then added a few lines to the
end of the config file, to configure these modules.</p><pre id="id374722" class="programlisting">userdir.path = "public_html"
cgi.assign = (".cgi" =&gt; "" )</pre><p id="x_4d3"><a name="x_4d3"></a>With this done, <code class="literal">lighttpd</code> ran
immediately for me. If I had configured
<code class="literal">lighttpd</code> before Apache, I'd almost
certainly have run into many of the same system-level
configuration problems as I did with Apache. However, I
found <code class="literal">lighttpd</code> to be noticeably easier to
configure than Apache, even though I've used Apache for over
a decade, and this was my first exposure to
<code class="literal">lighttpd</code>.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id374764">Sharing multiple repositories with one CGI script</h3></div></div></div><p id="x_4d4"><a name="x_4d4"></a>The <code class="filename">hgweb.cgi</code> script
only lets you publish a single repository, which is an
annoying restriction. If you want to publish more than one
without wracking yourself with multiple copies of the same
script, each with different names, a better choice is to use
the <code class="filename">hgwebdir.cgi</code>
script.</p><p id="x_4d5"><a name="x_4d5"></a>The procedure to configure <code class="filename">hgwebdir.cgi</code> is only a little more
involved than for <code class="filename">hgweb.cgi</code>. First, you must obtain
a copy of the script. If you don't have one handy, you can
download a copy from the master Mercurial repository at <a class="ulink" href="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi" target="_top">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</a>.</p><p id="x_4d6"><a name="x_4d6"></a>You'll need to copy this script into your <code class="filename">public_html</code> directory, and
ensure that it's executable.</p><pre id="id374844" class="programlisting">cp .../hgwebdir.cgi ~/public_html
chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</pre><p id="x_4d7"><a name="x_4d7"></a>With basic configuration out of the way, try to
visit <code class="literal">http://myhostname/~myuser/hgwebdir.cgi</code>
in your browser. It should
display an empty list of repositories. If you get a blank
window or error message, try walking through the list of
potential problems in <a class="xref" href="collaborating-with-other-people.html#sec:collab:wtf" title="What could possibly go wrong?">the section called “What could possibly go
wrong?”</a>.</p><p id="x_4d8"><a name="x_4d8"></a>The <code class="filename">hgwebdir.cgi</code>
script relies on an external configuration file. By default,
it searches for a file named <code class="filename">hgweb.config</code> in the same directory
as itself. You'll need to create this file, and make it
world-readable. The format of the file is similar to a
Windows “<span class="quote">ini</span>” file, as understood by Python's
<code class="literal">ConfigParser</code>
[<span class="citation">web:configparser</span>] module.</p><p id="x_4d9"><a name="x_4d9"></a>The easiest way to configure <code class="filename">hgwebdir.cgi</code> is with a section
named <code class="literal">collections</code>. This will automatically
publish <span class="emphasis"><em>every</em></span> repository under the
directories you name. The section should look like
this:</p><pre id="id374946" class="programlisting">[collections]
/my/root = /my/root</pre><p id="x_4da"><a name="x_4da"></a>Mercurial interprets this by looking at the directory name
on the <span class="emphasis"><em>right</em></span> hand side of the
<span class="quote"><code class="literal">=</code></span>” sign; finding repositories
in that directory hierarchy; and using the text on the
<span class="emphasis"><em>left</em></span> to strip off matching text from the
names it will actually list in the web interface. The
remaining component of a path after this stripping has
occurred is called a “<span class="quote">virtual path</span>”.</p><p id="x_4db"><a name="x_4db"></a>Given the example above, if we have a
repository whose local path is <code class="filename">/my/root/this/repo</code>, the CGI
script will strip the leading <code class="filename">/my/root</code> from the name, and
publish the repository with a virtual path of <code class="filename">this/repo</code>. If the base URL for
our CGI script is
<code class="literal">http://myhostname/~myuser/hgwebdir.cgi</code>, the
complete URL for that repository will be
<code class="literal">http://myhostname/~myuser/hgwebdir.cgi/this/repo</code>.</p><p id="x_4dc"><a name="x_4dc"></a>If we replace <code class="filename">/my/root</code> on the left hand side
of this example with <code class="filename">/my</code>, then <code class="filename">hgwebdir.cgi</code> will only strip off
<code class="filename">/my</code> from the repository
name, and will give us a virtual path of <code class="filename">root/this/repo</code> instead of
<code class="filename">this/repo</code>.</p><p id="x_4dd"><a name="x_4dd"></a>The <code class="filename">hgwebdir.cgi</code>
script will recursively search each directory listed in the
<code class="literal">collections</code> section of its configuration
file, but it will <code class="literal">not</code> recurse into the
repositories it finds.</p><p id="x_4de"><a name="x_4de"></a>The <code class="literal">collections</code> mechanism makes it easy
to publish many repositories in a “<span class="quote">fire and
forget</span>” manner. You only need to set up the CGI
script and configuration file one time. Afterwards, you can
publish or unpublish a repository at any time by simply moving
it into, or out of, the directory hierarchy in which you've
configured <code class="filename">hgwebdir.cgi</code> to
look.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id375138">Explicitly specifying which repositories to
publish</h4></div></div></div><p id="x_4df"><a name="x_4df"></a>In addition to the <code class="literal">collections</code>
mechanism, the <code class="filename">hgwebdir.cgi</code> script allows you
to publish a specific list of repositories. To do so,
create a <code class="literal">paths</code> section, with contents of
the following form.</p><pre id="id375172" class="programlisting">[paths]
repo1 = /my/path/to/some/repo
repo2 = /some/path/to/another</pre><p id="x_4e0"><a name="x_4e0"></a>In this case, the virtual path (the component that will
appear in a URL) is on the left hand side of each
definition, while the path to the repository is on the
right. Notice that there does not need to be any
relationship between the virtual path you choose and the
location of a repository in your filesystem.</p><p id="x_4e1"><a name="x_4e1"></a>If you wish, you can use both the
<code class="literal">collections</code> and <code class="literal">paths</code>
mechanisms simultaneously in a single configuration
file.</p><div class="note"><table border="0" summary="Note: Beware duplicate virtual paths"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Beware duplicate virtual paths</th></tr><tr><td align="left" valign="top"><p id="x_4e2"><a name="x_4e2"></a> If several repositories have the same
virtual path, <code class="filename">hgwebdir.cgi</code> will not report
an error. Instead, it will behave unpredictably.</p></td></tr></table></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id375233">Downloading source archives</h3></div></div></div><p id="x_4e3"><a name="x_4e3"></a>Mercurial's web interface lets users download an archive
of any revision. This archive will contain a snapshot of the
working directory as of that revision, but it will not contain
a copy of the repository data.</p><p id="x_4e4"><a name="x_4e4"></a>By default, this feature is not enabled. To enable it,
you'll need to add an <code class="envar">allow_archive</code> item to the
<code class="literal">web</code> section of your <code class="filename">~/.hgrc</code>; see below for details.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id375279">Web configuration options</h3></div></div></div><p id="x_4e5"><a name="x_4e5"></a>Mercurial's web interfaces (the <span class="command"><strong>hg
serve</strong></span> command, and the <code class="filename">hgweb.cgi</code> and <code class="filename">hgwebdir.cgi</code> scripts) have a
number of configuration options that you can set. These
belong in a section named <code class="literal">web</code>.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4e6"><a name="x_4e6"></a><code class="envar">allow_archive</code>: Determines
which (if any) archive download mechanisms Mercurial
supports. If you enable this feature, users of the web
interface will be able to download an archive of whatever
revision of a repository they are viewing. To enable the
archive feature, this item must take the form of a
sequence of words drawn from the list below.</p><div class="itemizedlist"><ul type="circle"><li><p id="x_4e7"><a name="x_4e7"></a><code class="literal">bz2</code>: A
<span class="command"><strong>tar</strong></span> archive, compressed using
<code class="literal">bzip2</code> compression. This has the
best compression ratio, but uses the most CPU time on
the server.</p></li><li><p id="x_4e8"><a name="x_4e8"></a><code class="literal">gz</code>: A
<span class="command"><strong>tar</strong></span> archive, compressed using
<code class="literal">gzip</code> compression.</p></li><li><p id="x_4e9"><a name="x_4e9"></a><code class="literal">zip</code>: A
<span class="command"><strong>zip</strong></span> archive, compressed using LZW
compression. This format has the worst compression
ratio, but is widely used in the Windows world.</p></li></ul></div><p id="x_4ea"><a name="x_4ea"></a> If you provide an empty list, or don't have an
<code class="envar">allow_archive</code> entry at
all, this feature will be disabled. Here is an example of
how to enable all three supported formats.</p><pre id="id375435" class="programlisting">[web]
allow_archive = bz2 gz zip</pre></li><li><p id="x_4eb"><a name="x_4eb"></a><code class="envar">allowpull</code>:
Boolean. Determines whether the web interface allows
remote users to <span class="command"><strong>hg pull</strong></span>
and <span class="command"><strong>hg clone</strong></span> this
repository over HTTP. If set to <code class="literal">no</code> or
<code class="literal">false</code>, only the
<span class="quote">human-oriented</span>” portion of the web interface
is available.</p></li><li><p id="x_4ec"><a name="x_4ec"></a><code class="envar">contact</code>:
String. A free-form (but preferably brief) string
identifying the person or group in charge of the
repository. This often contains the name and email
address of a person or mailing list. It often makes sense
to place this entry in a repository's own <code class="filename">.hg/hgrc</code> file, but it can make
sense to use in a global <code class="filename">~/.hgrc</code> if every repository
has a single maintainer.</p></li><li><p id="x_4ed"><a name="x_4ed"></a><code class="envar">maxchanges</code>:
Integer. The default maximum number of changesets to
display in a single page of output.</p></li><li><p id="x_4ee"><a name="x_4ee"></a><code class="envar">maxfiles</code>:
Integer. The default maximum number of modified files to
display in a single page of output.</p></li><li><p id="x_4ef"><a name="x_4ef"></a><code class="envar">stripes</code>:
Integer. If the web interface displays alternating
<span class="quote">stripes</span>” to make it easier to visually align
rows when you are looking at a table, this number controls
the number of rows in each stripe.</p></li><li><p id="x_4f0"><a name="x_4f0"></a><code class="envar">style</code>: Controls the template
Mercurial uses to display the web interface. Mercurial
ships with several web templates.</p><div class="itemizedlist"><ul type="circle"><li><p id="x_6aa"><a name="x_6aa"></a><code class="literal">coal</code> is monochromatic.</p></li><li><p id="x_6ab"><a name="x_6ab"></a><code class="literal">gitweb</code> emulates the visual
style of git's web interface.</p></li><li><p id="x_6ac"><a name="x_6ac"></a><code class="literal">monoblue</code> uses solid blues and
greys.</p></li><li><p id="x_6ad"><a name="x_6ad"></a><code class="literal">paper</code> is the default.</p></li><li><p id="x_6ae"><a name="x_6ae"></a><code class="literal">spartan</code> was the default for a
long time.</p></li></ul></div><p id="x_6af"><a name="x_6af"></a>You can
also specify a custom template of your own; see
<a class="xref" href="customizing-the-output-of-mercurial.html" title="Chapter 11. Customizing the output of Mercurial">Chapter 11, <i>Customizing the output of Mercurial</i></a> for details. Here, you can
see how to enable the <code class="literal">gitweb</code>
style.</p><pre id="id375687" class="programlisting">[web]
style = gitweb</pre></li><li><p id="x_4f1"><a name="x_4f1"></a><code class="envar">templates</code>:
Path. The directory in which to search for template
files. By default, Mercurial searches in the directory in
which it was installed.</p></li></ul></div><p id="x_4f2"><a name="x_4f2"></a>If you are using <code class="filename">hgwebdir.cgi</code>, you can place a few
configuration items in a <code class="literal">web</code>
section of the <code class="filename">hgweb.config</code> file instead of a
<code class="filename">~/.hgrc</code> file, for
convenience. These items are <code class="envar">motd</code> and <code class="envar">style</code>.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id375762">Options specific to an individual repository</h4></div></div></div><p id="x_4f3"><a name="x_4f3"></a>A few <code class="literal">web</code> configuration
items ought to be placed in a repository's local <code class="filename">.hg/hgrc</code>, rather than a user's
or global <code class="filename">~/.hgrc</code>.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4f4"><a name="x_4f4"></a><code class="envar">description</code>: String. A
free-form (but preferably brief) string that describes
the contents or purpose of the repository.</p></li><li><p id="x_4f5"><a name="x_4f5"></a><code class="envar">name</code>:
String. The name to use for the repository in the web
interface. This overrides the default name, which is
the last component of the repository's path.</p></li></ul></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id375833">Options specific to the <span class="command"><strong>hg
serve</strong></span> command</h4></div></div></div><p id="x_4f6"><a name="x_4f6"></a>Some of the items in the <code class="literal">web</code> section of a <code class="filename">~/.hgrc</code> file are only for use
with the <span class="command"><strong>hg serve</strong></span>
command.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_4f7"><a name="x_4f7"></a><code class="envar">accesslog</code>:
Path. The name of a file into which to write an access
log. By default, the <span class="command"><strong>hg
serve</strong></span> command writes this information to
standard output, not to a file. Log entries are written
in the standard “<span class="quote">combined</span>” file format used
by almost all web servers.</p></li><li><p id="x_4f8"><a name="x_4f8"></a><code class="envar">address</code>:
String. The local address on which the server should
listen for incoming connections. By default, the server
listens on all addresses.</p></li><li><p id="x_4f9"><a name="x_4f9"></a><code class="envar">errorlog</code>:
Path. The name of a file into which to write an error
log. By default, the <span class="command"><strong>hg
serve</strong></span> command writes this information to
standard error, not to a file.</p></li><li><p id="x_4fa"><a name="x_4fa"></a><code class="envar">ipv6</code>:
Boolean. Whether to use the IPv6 protocol. By default,
IPv6 is not used.</p></li><li><p id="x_4fb"><a name="x_4fb"></a><code class="envar">port</code>:
Integer. The TCP port number on which the server should
listen. The default port number used is 8000.</p></li></ul></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id375978">Choosing the right <code class="filename">~/.hgrc</code> file to add <code class="literal">web</code> items to</h4></div></div></div><p id="x_4fc"><a name="x_4fc"></a>It is important to remember that a web server like
Apache or <code class="literal">lighttpd</code> will run under a user
ID that is different to yours. CGI scripts run by your
server, such as <code class="filename">hgweb.cgi</code>, will usually also run
under that user ID.</p><p id="x_4fd"><a name="x_4fd"></a>If you add <code class="literal">web</code> items to
your own personal <code class="filename">~/.hgrc</code> file, CGI scripts won't read that
<code class="filename">~/.hgrc</code> file. Those
settings will thus only affect the behavior of the <span class="command"><strong>hg serve</strong></span> command when you run it.
To cause CGI scripts to see your settings, either create a
<code class="filename">~/.hgrc</code> file in the
home directory of the user ID that runs your web server, or
add those settings to a system-wide <code class="filename">hgrc</code> file.</p></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id376085">System-wide configuration</h2></div></div></div><p id="x_6b0"><a name="x_6b0"></a>On Unix-like systems shared by multiple users (such as a
server to which people publish changes), it often makes sense to
set up some global default behaviors, such as what theme to use
in web interfaces.</p><p id="x_6b1"><a name="x_6b1"></a>If a file named <code class="filename">/etc/mercurial/hgrc</code>
exists, Mercurial will read it at startup time and apply any
configuration settings it finds in that file. It will also look
for files ending in a <code class="literal">.rc</code> extension in a
directory named <code class="filename">/etc/mercurial/hgrc.d</code>, and
apply any configuration settings it finds in each of those
files.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id376128">Making Mercurial more trusting</h3></div></div></div><p id="x_6b2"><a name="x_6b2"></a>One situation in which a global <code class="filename">hgrc</code>
can be useful is if users are pulling changes owned by other
users. By default, Mercurial will not trust most of the
configuration items in a <code class="filename">.hg/hgrc</code> file
inside a repository that is owned by a different user. If we
clone or pull changes from such a repository, Mercurial will
print a warning stating that it does not trust their
<code class="filename">.hg/hgrc</code>.</p><p id="x_6b3"><a name="x_6b3"></a>If everyone in a particular Unix group is on the same team
and <span class="emphasis"><em>should</em></span> trust each other's
configuration settings, or we want to trust particular users,
we can override Mercurial's skeptical defaults by creating a
system-wide <code class="filename">hgrc</code> file such as the
following:</p><pre id="id376179" class="programlisting"># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc
[trusted]
# Trust all entries in any hgrc file owned by the "editors" or
# "www-data" groups.
groups = editors, www-data
# Trust entries in hgrc files owned by the following users.
users = apache, bobo
</pre></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="mercurial-in-daily-use.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="file-names-and-pattern-matching.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 5. Mercurial in daily use </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 7. File names and pattern matching</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,490 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 11. Customizing the output of Mercurial</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks"><link rel="next" href="managing-change-with-mercurial-queues.html" title="Chapter 12. Managing change with Mercurial Queues"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 11. Customizing the output of Mercurial</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="handling-repository-events-with-hooks.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="managing-change-with-mercurial-queues.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:template"><div class="titlepage"><div><div><h2 class="title">Chapter 11. Customizing the output of Mercurial</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:style">Using precanned output styles</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id414837">Setting a default style</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id414882">Commands that support styles and templates</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id414947">The basics of templating</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:keyword">Common template keywords</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:escape">Escape sequences</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:filter">Filtering keywords to change their results</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417290">Combining filters</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id417618">From templates to styles</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417353">The simplest of style files</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417428">Style file syntax</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id417656">Style files by example</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417669">Identifying mistakes in style files</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417853">Uniquely identifying a repository</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417978">Listing files on multiple lines</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id418118">Mimicking Subversion's output</a></span></dt></dl></dd></dl></div><p id="x_578"><a name="x_578"></a>Mercurial provides a powerful mechanism to let you control how
it displays information. The mechanism is based on templates.
You can use templates to generate specific output for a single
command, or to customize the entire appearance of the built-in web
interface.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:style">Using precanned output styles</h2></div></div></div><p id="x_579"><a name="x_579"></a>Packaged with Mercurial are some output styles that you can
use immediately. A style is simply a precanned template that
someone wrote and installed somewhere that Mercurial can
find.</p><p id="x_57a"><a name="x_57a"></a>Before we take a look at Mercurial's bundled styles, let's
review its normal output.</p><pre id="id415040" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1</code></strong>
changeset: 1:107e439be01c
tag: mytag
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:46 2009 +0000
summary: added line to end of &lt;&lt;hello&gt;&gt; file.
</pre><p id="x_57b"><a name="x_57b"></a>This is somewhat informative, but it takes up a lot of
space—five lines of output per changeset. The
<code class="literal">compact</code> style reduces this to three lines,
presented in a sparse manner.</p><pre id="id415023" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
3[tip] 65efccbd2729 2009-05-05 06:55 +0000 bos
Added tag v0.1 for changeset 59abc8be7140
2[v0.1] 59abc8be7140 2009-05-05 06:55 +0000 bos
Added tag mytag for changeset 107e439be01c
1[mytag] 107e439be01c 2009-05-05 06:55 +0000 bos
added line to end of &lt;&lt;hello&gt;&gt; file.
0 5ce2a492c569 2009-05-05 06:55 +0000 bos
added hello
</pre><p id="x_57c"><a name="x_57c"></a>The <code class="literal">changelog</code> style hints at the
expressive power of Mercurial's templating engine. This style
attempts to follow the GNU Project's changelog
guidelines[<span class="citation">web:changelog</span>].</p><pre id="id414997" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style changelog</code></strong>
2009-05-05 Bryan O'Sullivan &lt;bos@serpentine.com&gt;
* .hgtags:
Added tag v0.1 for changeset 59abc8be7140
[65efccbd2729] [tip]
* .hgtags:
Added tag mytag for changeset 107e439be01c
[59abc8be7140] [v0.1]
* goodbye, hello:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
[107e439be01c] [mytag]
* hello:
added hello
[5ce2a492c569]
</pre><p id="x_57d"><a name="x_57d"></a>You will not be shocked to learn that Mercurial's default
output style is named <code class="literal">default</code>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id414837">Setting a default style</h3></div></div></div><p id="x_57e"><a name="x_57e"></a>You can modify the output style that Mercurial will use
for every command by editing your <code class="filename">~/.hgrc</code> file, naming the style
you would prefer to use.</p><pre id="id414859" class="programlisting">[ui]
style = compact</pre><p id="x_57f"><a name="x_57f"></a>If you write a style of your own, you can use it by either
providing the path to your style file, or copying your style
file into a location where Mercurial can find it (typically
the <code class="literal">templates</code> subdirectory of your
Mercurial install directory).</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id414882">Commands that support styles and templates</h2></div></div></div><p id="x_580"><a name="x_580"></a>All of Mercurial's
<span class="quote"><code class="literal">log</code>-like</span>” commands let you use
styles and templates: <span class="command"><strong>hg
incoming</strong></span>, <span class="command"><strong>hg log</strong></span>,
<span class="command"><strong>hg outgoing</strong></span>, and <span class="command"><strong>hg tip</strong></span>.</p><p id="x_581"><a name="x_581"></a>As I write this manual, these are so far the only commands
that support styles and templates. Since these are the most
important commands that need customizable output, there has been
little pressure from the Mercurial user community to add style
and template support to other commands.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id414947">The basics of templating</h2></div></div></div><p id="x_582"><a name="x_582"></a>At its simplest, a Mercurial template is a piece of text.
Some of the text never changes, while other parts are
<span class="emphasis"><em>expanded</em></span>, or replaced with new text, when
necessary.</p><p id="x_583"><a name="x_583"></a>Before we continue, let's look again at a simple example of
Mercurial's normal output.</p><pre id="id415038" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1</code></strong>
changeset: 1:107e439be01c
tag: mytag
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:46 2009 +0000
summary: added line to end of &lt;&lt;hello&gt;&gt; file.
</pre><p id="x_584"><a name="x_584"></a>Now, let's run the same command, but using a template to
change its output.</p><pre id="id415404" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'i saw a changeset\n'</code></strong>
i saw a changeset
</pre><p id="x_585"><a name="x_585"></a>The example above illustrates the simplest possible
template; it's just a piece of static text, printed once for
each changeset. The <code class="option">--template</code> option to the <span class="command"><strong>hg log</strong></span> command tells Mercurial to use
the given text as the template when printing each
changeset.</p><p id="x_586"><a name="x_586"></a>Notice that the template string above ends with the text
<span class="quote"><code class="literal">\n</code></span>”. This is an
<span class="emphasis"><em>escape sequence</em></span>, telling Mercurial to print
a newline at the end of each template item. If you omit this
newline, Mercurial will run each piece of output together. See
<a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:escape" title="Escape sequences">the section called “Escape sequences”</a> for more details
of escape sequences.</p><p id="x_587"><a name="x_587"></a>A template that prints a fixed string of text all the time
isn't very useful; let's try something a bit more
complex.</p><pre id="id415110" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --template 'i saw a changeset: {desc}\n'</code></strong>
i saw a changeset: Added tag v0.1 for changeset 59abc8be7140
i saw a changeset: Added tag mytag for changeset 107e439be01c
i saw a changeset: added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
i saw a changeset: added hello
</pre><p id="x_588"><a name="x_588"></a>As you can see, the string
<span class="quote"><code class="literal">{desc}</code></span>” in the template has
been replaced in the output with the description of each
changeset. Every time Mercurial finds text enclosed in curly
braces (“<span class="quote"><code class="literal">{</code></span>” and
<span class="quote"><code class="literal">}</code></span>”), it will try to replace the
braces and text with the expansion of whatever is inside. To
print a literal curly brace, you must escape it, as described in
<a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:escape" title="Escape sequences">the section called “Escape sequences”</a>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:keyword">Common template keywords</h2></div></div></div><p id="x_589"><a name="x_589"></a>You can start writing simple templates immediately using the
keywords below.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_58a"><a name="x_58a"></a><code class="literal">author</code>: String. The
unmodified author of the changeset.</p></li><li><p id="x_58b"><a name="x_58b"></a><code class="literal">branches</code>: String. The
name of the branch on which the changeset was committed.
Will be empty if the branch name was
<code class="literal">default</code>.</p></li><li><p id="x_58c"><a name="x_58c"></a><code class="literal">date</code>:
Date information. The date when the changeset was
committed. This is <span class="emphasis"><em>not</em></span> human-readable;
you must pass it through a filter that will render it
appropriately. See <a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:filter" title="Filtering keywords to change their results">the section called “Filtering keywords to change their results”</a> for more information
on filters. The date is expressed as a pair of numbers. The
first number is a Unix UTC timestamp (seconds since January
1, 1970); the second is the offset of the committer's
timezone from UTC, in seconds.</p></li><li><p id="x_58d"><a name="x_58d"></a><code class="literal">desc</code>:
String. The text of the changeset description.</p></li><li><p id="x_58e"><a name="x_58e"></a><code class="literal">files</code>: List of strings.
All files modified, added, or removed by this
changeset.</p></li><li><p id="x_58f"><a name="x_58f"></a><code class="literal">file_adds</code>: List of
strings. Files added by this changeset.</p></li><li><p id="x_590"><a name="x_590"></a><code class="literal">file_dels</code>: List of
strings. Files removed by this changeset.</p></li><li><p id="x_591"><a name="x_591"></a><code class="literal">node</code>:
String. The changeset identification hash, as a
40-character hexadecimal string.</p></li><li><p id="x_592"><a name="x_592"></a><code class="literal">parents</code>: List of
strings. The parents of the changeset.</p></li><li><p id="x_593"><a name="x_593"></a><code class="literal">rev</code>:
Integer. The repository-local changeset revision
number.</p></li><li><p id="x_594"><a name="x_594"></a><code class="literal">tags</code>:
List of strings. Any tags associated with the
changeset.</p></li></ul></div><p id="x_595"><a name="x_595"></a>A few simple experiments will show us what to expect when we
use these keywords; you can see the results below.</p><pre id="id415826" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'author: {author}\n'</code></strong>
author: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'desc:\n{desc}\n'</code></strong>
desc:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'files: {files}\n'</code></strong>
files: goodbye hello
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'file_adds: {file_adds}\n'</code></strong>
file_adds: goodbye
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'file_dels: {file_dels}\n'</code></strong>
file_dels:
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'node: {node}\n'</code></strong>
node: 107e439be01c456e8e32f719558cb7ea693b60fd
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'parents: {parents}\n'</code></strong>
parents:
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'rev: {rev}\n'</code></strong>
rev: 1
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'tags: {tags}\n'</code></strong>
tags: mytag
</pre><p id="x_596"><a name="x_596"></a>As we noted above, the date keyword does not produce
human-readable output, so we must treat it specially. This
involves using a <span class="emphasis"><em>filter</em></span>, about which more
in <a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:filter" title="Filtering keywords to change their results">the section called “Filtering keywords to change their results”</a>.</p><pre id="id415717" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'date: {date}\n'</code></strong>
date: 1241506546.00
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'date: {date|isodate}\n'</code></strong>
date: 2009-05-05 06:55 +0000
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:escape">Escape sequences</h2></div></div></div><p id="x_597"><a name="x_597"></a>Mercurial's templating engine recognises the most commonly
used escape sequences in strings. When it sees a backslash
(“<span class="quote"><code class="literal">\</code></span>”) character, it looks at the
following character and substitutes the two characters with a
single replacement, as described below.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_598"><a name="x_598"></a><code class="literal">\</code>:
Backslash, “<span class="quote"><code class="literal">\</code></span>”, ASCII
134.</p></li><li><p id="x_599"><a name="x_599"></a><code class="literal">\n</code>: Newline,
ASCII 12.</p></li><li><p id="x_59a"><a name="x_59a"></a><code class="literal">\r</code>: Carriage
return, ASCII 15.</p></li><li><p id="x_59b"><a name="x_59b"></a><code class="literal">\t</code>: Tab, ASCII
11.</p></li><li><p id="x_59c"><a name="x_59c"></a><code class="literal">\v</code>: Vertical
tab, ASCII 13.</p></li><li><p id="x_59d"><a name="x_59d"></a><code class="literal">\{</code>: Open curly
brace, “<span class="quote"><code class="literal">{</code></span>”, ASCII
173.</p></li><li><p id="x_59e"><a name="x_59e"></a><code class="literal">\}</code>: Close curly
brace, “<span class="quote"><code class="literal">}</code></span>”, ASCII
175.</p></li></ul></div><p id="x_59f"><a name="x_59f"></a>As indicated above, if you want the expansion of a template
to contain a literal “<span class="quote"><code class="literal">\</code></span>”,
<span class="quote"><code class="literal">{</code></span>”, or
<span class="quote"><code class="literal">{</code></span>” character, you must escape
it.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:filter">Filtering keywords to change their results</h2></div></div></div><p id="x_5a0"><a name="x_5a0"></a>Some of the results of template expansion are not
immediately easy to use. Mercurial lets you specify an optional
chain of <span class="emphasis"><em>filters</em></span> to modify the result of
expanding a keyword. You have already seen a common filter,
<code class="literal">isodate</code>, in
action above, to make a date readable.</p><p id="x_5a1"><a name="x_5a1"></a>Below is a list of the most commonly used filters that
Mercurial supports. While some filters can be applied to any
text, others can only be used in specific circumstances. The
name of each filter is followed first by an indication of where
it can be used, then a description of its effect.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5a2"><a name="x_5a2"></a><code class="literal">addbreaks</code>: Any text. Add
an XHTML “<span class="quote"><code class="literal">&lt;br/&gt;</code></span>” tag
before the end of every line except the last. For example,
<span class="quote"><code class="literal">foo\nbar</code></span>” becomes
<span class="quote"><code class="literal">foo&lt;br/&gt;\nbar</code></span>”.</p></li><li><p id="x_5a3"><a name="x_5a3"></a><code class="literal">age</code>: <code class="literal">date</code> keyword. Render
the age of the date, relative to the current time. Yields a
string like “<span class="quote"><code class="literal">10
minutes</code></span>”.</p></li><li><p id="x_5a4"><a name="x_5a4"></a><code class="literal">basename</code>: Any text, but
most useful for the <code class="literal">files</code> keyword and its
relatives. Treat the text as a path, and return the
basename. For example,
<span class="quote"><code class="literal">foo/bar/baz</code></span>” becomes
<span class="quote"><code class="literal">baz</code></span>”.</p></li><li><p id="x_5a5"><a name="x_5a5"></a><code class="literal">date</code>: <code class="literal">date</code> keyword. Render a
date in a similar format to the Unix <code class="literal">date</code> command, but with
timezone included. Yields a string like “<span class="quote"><code class="literal">Mon
Sep 04 15:13:13 2006 -0700</code></span>”.</p></li><li><p id="x_5a6"><a name="x_5a6"></a><code class="literal">domain</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Finds
the first string that looks like an email address, and
extract just the domain component. For example,
<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">serpentine.com</code></span>”.</p></li><li><p id="x_5a7"><a name="x_5a7"></a><code class="literal">email</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Extract
the first string that looks like an email address. For
example, “<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">bos@serpentine.com</code></span>”.</p></li><li><p id="x_5a8"><a name="x_5a8"></a><code class="literal">escape</code>: Any text.
Replace the special XML/XHTML characters
<span class="quote"><code class="literal">&amp;</code></span>”,
<span class="quote"><code class="literal">&lt;</code></span>” and
<span class="quote"><code class="literal">&gt;</code></span>” with XML
entities.</p></li><li><p id="x_5a9"><a name="x_5a9"></a><code class="literal">fill68</code>: Any text. Wrap
the text to fit in 68 columns. This is useful before you
pass text through the <code class="literal">tabindent</code> filter, and
still want it to fit in an 80-column fixed-font
window.</p></li><li><p id="x_5aa"><a name="x_5aa"></a><code class="literal">fill76</code>: Any text. Wrap
the text to fit in 76 columns.</p></li><li><p id="x_5ab"><a name="x_5ab"></a><code class="literal">firstline</code>: Any text.
Yield the first line of text, without any trailing
newlines.</p></li><li><p id="x_5ac"><a name="x_5ac"></a><code class="literal">hgdate</code>: <code class="literal">date</code> keyword. Render
the date as a pair of readable numbers. Yields a string
like “<span class="quote"><code class="literal">1157407993
25200</code></span>”.</p></li><li><p id="x_5ad"><a name="x_5ad"></a><code class="literal">isodate</code>: <code class="literal">date</code> keyword. Render
the date as a text string in ISO 8601 format. Yields a
string like “<span class="quote"><code class="literal">2006-09-04 15:13:13
-0700</code></span>”.</p></li><li><p id="x_5ae"><a name="x_5ae"></a><code class="literal">obfuscate</code>: Any text, but
most useful for the <code class="literal">author</code> keyword. Yield
the input text rendered as a sequence of XML entities. This
helps to defeat some particularly stupid screen-scraping
email harvesting spambots.</p></li><li><p id="x_5af"><a name="x_5af"></a><code class="literal">person</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Yield
the text before an email address. For example,
<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">Bryan O'Sullivan</code></span>”.</p></li><li><p id="x_5b0"><a name="x_5b0"></a><code class="literal">rfc822date</code>:
<code class="literal">date</code> keyword.
Render a date using the same format used in email headers.
Yields a string like “<span class="quote"><code class="literal">Mon, 04 Sep 2006
15:13:13 -0700</code></span>”.</p></li><li><p id="x_5b1"><a name="x_5b1"></a><code class="literal">short</code>: Changeset
hash. Yield the short form of a changeset hash, i.e. a
12-character hexadecimal string.</p></li><li><p id="x_5b2"><a name="x_5b2"></a><code class="literal">shortdate</code>: <code class="literal">date</code> keyword. Render
the year, month, and day of the date. Yields a string like
<span class="quote"><code class="literal">2006-09-04</code></span>”.</p></li><li><p id="x_5b3"><a name="x_5b3"></a><code class="literal">strip</code>:
Any text. Strip all leading and trailing whitespace from
the string.</p></li><li><p id="x_5b4"><a name="x_5b4"></a><code class="literal">tabindent</code>: Any text.
Yield the text, with every line except the first starting
with a tab character.</p></li><li><p id="x_5b5"><a name="x_5b5"></a><code class="literal">urlescape</code>: Any text.
Escape all characters that are considered
<span class="quote">special</span>” by URL parsers. For example,
<code class="literal">foo bar</code> becomes
<code class="literal">foo%20bar</code>.</p></li><li><p id="x_5b6"><a name="x_5b6"></a><code class="literal">user</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Return
the “<span class="quote">user</span>” portion of an email address. For
example, “<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">bos</code></span>”.</p></li></ul></div><pre id="id417012" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author}\n'</code></strong>
Bryan O'Sullivan &lt;bos@serpentine.com&gt;
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|domain}\n'</code></strong>
serpentine.com
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|email}\n'</code></strong>
bos@serpentine.com
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</code></strong>
&amp;#66;&amp;#114;&amp;#121;&amp;#97;&amp;#110;&amp;#32;&amp;#79;&amp;#39;&amp;#83;&amp;#117;&amp;#108;&amp;#108;&amp;#105;&amp;#11
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|person}\n'</code></strong>
Bryan O'Sullivan
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|user}\n'</code></strong>
bos
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</code></strong>
looks almost right, but actually garbage: 1241506546.00
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|age}\n'</code></strong>
2 seconds
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|date}\n'</code></strong>
Tue May 05 06:55:46 2009 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|hgdate}\n'</code></strong>
1241506546 0
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|isodate}\n'</code></strong>
2009-05-05 06:55 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|rfc822date}\n'</code></strong>
Tue, 05 May 2009 06:55:46 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|shortdate}\n'</code></strong>
2009-05-05
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.&lt;br/&gt;
&lt;br/&gt;
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|escape}\n' | cut -c-76</code></strong>
added line to end of &amp;lt;&amp;lt;hello&amp;gt;&amp;gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|fill68}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|fill76}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some
might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|firstline}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|strip}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope tha
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{node}\n'</code></strong>
107e439be01c456e8e32f719558cb7ea693b60fd
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{node|short}\n'</code></strong>
107e439be01c
</pre><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_5b7"><a name="x_5b7"></a> If you try to apply a filter to a piece of data that it
cannot process, Mercurial will fail and print a Python
exception. For example, trying to run the output of the
<code class="literal">desc</code> keyword into
the <code class="literal">isodate</code>
filter is not a good idea.</p></td></tr></table></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417290">Combining filters</h3></div></div></div><p id="x_5b8"><a name="x_5b8"></a>It is easy to combine filters to yield output in the form
you would like. The following chain of filters tidies up a
description, then makes sure that it fits cleanly into 68
columns, then indents it by a further 8 characters (at least
on Unix-like systems, where a tab is conventionally 8
characters wide).</p><pre id="id417653" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</code></strong>
description:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
</pre><p id="x_5b9"><a name="x_5b9"></a>Note the use of “<span class="quote"><code class="literal">\t</code></span>” (a
tab character) in the template to force the first line to be
indented; this is necessary since <code class="literal">tabindent</code> indents all
lines <span class="emphasis"><em>except</em></span> the first.</p><p id="x_5ba"><a name="x_5ba"></a>Keep in mind that the order of filters in a chain is
significant. The first filter is applied to the result of the
keyword; the second to the result of the first filter; and so
on. For example, using <code class="literal">fill68|tabindent</code>
gives very different results from
<code class="literal">tabindent|fill68</code>.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id417618">From templates to styles</h2></div></div></div><p id="x_5bb"><a name="x_5bb"></a>A command line template provides a quick and simple way to
format some output. Templates can become verbose, though, and
it's useful to be able to give a template a name. A style file
is a template with a name, stored in a file.</p><p id="x_5bc"><a name="x_5bc"></a>More than that, using a style file unlocks the power of
Mercurial's templating engine in ways that are not possible
using the command line <code class="option">--template</code> option.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417353">The simplest of style files</h3></div></div></div><p id="x_5bd"><a name="x_5bd"></a>Our simple style file contains just one line:</p><pre id="id417560" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo 'changeset = "rev: {rev}\n"' &gt; rev</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg log -l1 --style ./rev</code></strong>
rev: 3
</pre><p id="x_5be"><a name="x_5be"></a>This tells Mercurial, “<span class="quote">if you're printing a
changeset, use the text on the right as the
template</span>”.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417428">Style file syntax</h3></div></div></div><p id="x_5bf"><a name="x_5bf"></a>The syntax rules for a style file are simple.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5c0"><a name="x_5c0"></a>The file is processed one line at a
time.</p></li><li><p id="x_5c1"><a name="x_5c1"></a>Leading and trailing white space are
ignored.</p></li><li><p id="x_5c2"><a name="x_5c2"></a>Empty lines are skipped.</p></li><li><p id="x_5c3"><a name="x_5c3"></a>If a line starts with either of the characters
<span class="quote"><code class="literal">#</code></span>” or
<span class="quote"><code class="literal">;</code></span>”, the entire line is
treated as a comment, and skipped as if empty.</p></li><li><p id="x_5c4"><a name="x_5c4"></a>A line starts with a keyword. This must start
with an alphabetic character or underscore, and can
subsequently contain any alphanumeric character or
underscore. (In regexp notation, a keyword must match
<code class="literal">[A-Za-z_][A-Za-z0-9_]*</code>.)</p></li><li><p id="x_5c5"><a name="x_5c5"></a>The next element must be an
<span class="quote"><code class="literal">=</code></span>” character, which can
be preceded or followed by an arbitrary amount of white
space.</p></li><li><p id="x_5c6"><a name="x_5c6"></a>If the rest of the line starts and ends with
matching quote characters (either single or double quote),
it is treated as a template body.</p></li><li><p id="x_5c7"><a name="x_5c7"></a>If the rest of the line <span class="emphasis"><em>does
not</em></span> start with a quote character, it is
treated as the name of a file; the contents of this file
will be read and used as a template body.</p></li></ul></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id417656">Style files by example</h2></div></div></div><p id="x_5c8"><a name="x_5c8"></a>To illustrate how to write a style file, we will construct a
few by example. Rather than provide a complete style file and
walk through it, we'll mirror the usual process of developing a
style file by starting with something very simple, and walking
through a series of successively more complete examples.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417669">Identifying mistakes in style files</h3></div></div></div><p id="x_5c9"><a name="x_5c9"></a>If Mercurial encounters a problem in a style file you are
working on, it prints a terse error message that, once you
figure out what it means, is actually quite useful.</p><pre id="id418030" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat broken.style</code></strong>
changeset =
</pre><p id="x_5ca"><a name="x_5ca"></a>Notice that <code class="filename">broken.style</code> attempts to
define a <code class="literal">changeset</code> keyword, but forgets to
give any content for it. When instructed to use this style
file, Mercurial promptly complains.</p><pre id="id418015" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --style broken.style</code></strong>
abort: broken.style:1: parse error
</pre><p id="x_5cb"><a name="x_5cb"></a>This error message looks intimidating, but it is not too
hard to follow.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5cc"><a name="x_5cc"></a>The first component is simply Mercurial's way
of saying “<span class="quote">I am giving up</span>”.</p><pre id="id417787" class="programlisting">___abort___: broken.style:1: parse error</pre></li><li><p id="x_5cd"><a name="x_5cd"></a>Next comes the name of the style file that
contains the error.</p><pre id="id417803" class="programlisting">abort: ___broken.style___:1: parse error</pre></li><li><p id="x_5ce"><a name="x_5ce"></a>Following the file name is the line number
where the error was encountered.</p><pre id="id417818" class="programlisting">abort: broken.style:___1___: parse error</pre></li><li><p id="x_5cf"><a name="x_5cf"></a>Finally, a description of what went
wrong.</p><pre id="id417834" class="programlisting">abort: broken.style:1: ___parse error___</pre></li><li><p id="x_5d0"><a name="x_5d0"></a>The description of the problem is not always
clear (as in this case), but even when it is cryptic, it
is almost always trivial to visually inspect the offending
line in the style file and see what is wrong.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417853">Uniquely identifying a repository</h3></div></div></div><p id="x_5d1"><a name="x_5d1"></a>If you would like to be able to identify a Mercurial
repository “<span class="quote">fairly uniquely</span>” using a short string
as an identifier, you can use the first revision in the
repository.</p><pre id="id418246" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r0 --template '{node}'</code></strong>
189e736977c29ea3835dfc7e332794a24f479c51</pre><p id="x_5d2"><a name="x_5d2"></a>This is likely to be unique, and so it is
useful in many cases. There are a few caveats.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5d3"><a name="x_5d3"></a>It will not work in a completely empty
repository, because such a repository does not have a
revision zero.</p></li><li><p id="x_5d4"><a name="x_5d4"></a>Neither will it work in the (extremely rare)
case where a repository is a merge of two or more formerly
independent repositories, and you still have those
repositories around.</p></li></ul></div><p id="x_5d5"><a name="x_5d5"></a>Here are some uses to which you could put this
identifier:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5d6"><a name="x_5d6"></a>As a key into a table for a database that
manages repositories on a server.</p></li><li><p id="x_5d7"><a name="x_5d7"></a>As half of a {<span class="emphasis"><em>repository
ID</em></span>, <span class="emphasis"><em>revision ID</em></span>} tuple.
Save this information away when you run an automated build
or other activity, so that you can “<span class="quote">replay</span>
the build later if necessary.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417978">Listing files on multiple lines</h3></div></div></div><p id="x_714"><a name="x_714"></a>Suppose we want to list the files changed by a changeset,
one per line, with a little indentation before each file
name.</p><pre id="id418218" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat &gt; multiline &lt;&lt; EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>changeset = "Changed in {node|short}:\n{files}"</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>file = " {file}\n"</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg log --style multiline</code></strong>
Changed in ae47487e0fed:
.bashrc
.hgrc
test.c
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id418118">Mimicking Subversion's output</h3></div></div></div><p id="x_5d8"><a name="x_5d8"></a>Let's try to emulate the default output format used by
another revision control tool, Subversion.</p><pre id="id418182" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>svn log -r9653</code></strong>
------------------------------------------------------------------------
r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
On reporting a route error, also include the status for the error,
rather than indicating a status of 0 when an error has occurred.
Signed-off-by: Sean Hefty &lt;sean.hefty@intel.com&gt;
------------------------------------------------------------------------
</pre><p id="x_5d9"><a name="x_5d9"></a>Since Subversion's output style is fairly simple, it is
easy to copy-and-paste a hunk of its output into a file, and
replace the text produced above by Subversion with the
template values we'd like to see expanded.</p><pre id="id418368" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat svn.template</code></strong>
r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
{desc|strip|fill76}
------------------------------------------------------------------------
</pre><p id="x_5da"><a name="x_5da"></a>There are a few small ways in which this template deviates
from the output produced by Subversion.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5db"><a name="x_5db"></a>Subversion prints a “<span class="quote">readable</span>
date (the “<span class="quote"><code class="literal">Wed, 27 Sep 2006</code></span>” in the
example output above) in parentheses. Mercurial's
templating engine does not provide a way to display a date
in this format without also printing the time and time
zone.</p></li><li><p id="x_5dc"><a name="x_5dc"></a>We emulate Subversion's printing of
<span class="quote">separator</span>” lines full of
<span class="quote"><code class="literal">-</code></span>” characters by ending
the template with such a line. We use the templating
engine's <code class="literal">header</code>
keyword to print a separator line as the first line of
output (see below), thus achieving similar output to
Subversion.</p></li><li><p id="x_5dd"><a name="x_5dd"></a>Subversion's output includes a count in the
header of the number of lines in the commit message. We
cannot replicate this in Mercurial; the templating engine
does not currently provide a filter that counts the number
of lines the template generates.</p></li></ul></div><p id="x_5de"><a name="x_5de"></a>It took me no more than a minute or two of work to replace
literal text from an example of Subversion's output with some
keywords and filters to give the template above. The style
file simply refers to the template.</p><pre id="id418351" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat svn.style</code></strong>
header = '------------------------------------------------------------------------\n\n'
changeset = svn.template
</pre><p id="x_5df"><a name="x_5df"></a>We could have included the text of the template file
directly in the style file by enclosing it in quotes and
replacing the newlines with
<span class="quote"><code class="literal">\n</code></span>” sequences, but it would
have made the style file too difficult to read. Readability
is a good guide when you're trying to decide whether some text
belongs in a style file, or in a template file that the style
file points to. If the style file will look too big or
cluttered if you insert a literal piece of text, drop it into
a template instead.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="handling-repository-events-with-hooks.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="managing-change-with-mercurial-queues.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 10. Handling repository events with hooks </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 12. Managing change with Mercurial Queues</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,324 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 7. File names and pattern matching</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="collaborating-with-other-people.html" title="Chapter 6. Collaborating with other people"><link rel="next" href="managing-releases-and-branchy-development.html" title="Chapter 8. Managing releases and branchy development"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 7. File names and pattern matching</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="collaborating-with-other-people.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="managing-releases-and-branchy-development.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:names"><div class="titlepage"><div><div><h2 class="title">Chapter 7. File names and pattern matching</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id380420">Simple file naming</a></span></dt><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id380836">Running commands without any file names</a></span></dt><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id381125">Telling you what's going on</a></span></dt><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id381184">Using patterns to identify files</a></span></dt><dd><dl><dt><span class="sect2"><a href="file-names-and-pattern-matching.html#id381291">Shell-style glob patterns</a></span></dt><dd><dl><dt><span class="sect3"><a href="file-names-and-pattern-matching.html#id381653">Watch out!</a></span></dt></dl></dd><dt><span class="sect2"><a href="file-names-and-pattern-matching.html#id381804">Regular expression matching with re
patterns</a></span></dt></dl></dd><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id381878">Filtering files</a></span></dt><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#id382104">Permanently ignoring unwanted files and directories</a></span></dt><dt><span class="sect1"><a href="file-names-and-pattern-matching.html#sec:names:case">Case sensitivity</a></span></dt><dd><dl><dt><span class="sect2"><a href="file-names-and-pattern-matching.html#id382327">Safe, portable repository storage</a></span></dt><dt><span class="sect2"><a href="file-names-and-pattern-matching.html#id382348">Detecting case conflicts</a></span></dt><dt><span class="sect2"><a href="file-names-and-pattern-matching.html#id382414">Fixing a case conflict</a></span></dt></dl></dd></dl></div><p id="x_543"><a name="x_543"></a>Mercurial provides mechanisms that let you work with file
names in a consistent and expressive way.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id380420">Simple file naming</h2></div></div></div><p id="x_544"><a name="x_544"></a>Mercurial uses a unified piece of machinery “<span class="quote">under the
hood</span>” to handle file names. Every command behaves
uniformly with respect to file names. The way in which commands
work with file names is as follows.</p><p id="x_545"><a name="x_545"></a>If you explicitly name real files on the command line,
Mercurial works with exactly those files, as you would expect.
</p><pre id="id381103" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg add COPYING README examples/simple.py</code></strong>
</pre><p>
</p><p id="x_546"><a name="x_546"></a>When you provide a directory name, Mercurial will interpret
this as “<span class="quote">operate on every file in this directory and its
subdirectories</span>”. Mercurial traverses the files and
subdirectories in a directory in alphabetical order. When it
encounters a subdirectory, it will traverse that subdirectory
before continuing with the current directory.</p><pre id="id381083" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status src</code></strong>
? src/main.py
? src/watcher/_watcher.c
? src/watcher/watcher.py
? src/xyzzy.txt
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id380836">Running commands without any file names</h2></div></div></div><p id="x_547"><a name="x_547"></a>Mercurial's commands that work with file names have useful
default behaviors when you invoke them without providing any
file names or patterns. What kind of behavior you should
expect depends on what the command does. Here are a few rules
of thumb you can use to predict what a command is likely to do
if you don't give it any names to work with.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_548"><a name="x_548"></a>Most commands will operate on the entire working
directory. This is what the <span class="command"><strong>hg
add</strong></span> command does, for example.</p></li><li><p id="x_549"><a name="x_549"></a>If the command has effects that are difficult or
impossible to reverse, it will force you to explicitly
provide at least one name or pattern (see below). This
protects you from accidentally deleting files by running
<span class="command"><strong>hg remove</strong></span> with no
arguments, for example.</p></li></ul></div><p id="x_54a"><a name="x_54a"></a>It's easy to work around these default behaviors if they
don't suit you. If a command normally operates on the whole
working directory, you can invoke it on just the current
directory and its subdirectories by giving it the name
<span class="quote"><code class="filename">.</code></span>”.</p><pre id="id381050" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd src</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add -n</code></strong>
adding ../MANIFEST.in
adding ../examples/performant.py
adding ../setup.py
adding main.py
adding watcher/_watcher.c
adding watcher/watcher.py
adding xyzzy.txt
<code class="prompt">$</code> <strong class="userinput"><code>hg add -n .</code></strong>
adding main.py
adding watcher/_watcher.c
adding watcher/watcher.py
adding xyzzy.txt
</pre><p id="x_54b"><a name="x_54b"></a>Along the same lines, some commands normally print file
names relative to the root of the repository, even if you're
invoking them from a subdirectory. Such a command will print
file names relative to your subdirectory if you give it explicit
names. Here, we're going to run <span class="command"><strong>hg
status</strong></span> from a subdirectory, and get it to operate on
the entire working directory while printing file names relative
to our subdirectory, by passing it the output of the <span class="command"><strong>hg root</strong></span> command.</p><pre id="id381404" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
A COPYING
A README
A examples/simple.py
? MANIFEST.in
? examples/performant.py
? setup.py
? src/main.py
? src/watcher/_watcher.c
? src/watcher/watcher.py
? src/xyzzy.txt
<code class="prompt">$</code> <strong class="userinput"><code>hg status `hg root`</code></strong>
A ../COPYING
A ../README
A ../examples/simple.py
? ../MANIFEST.in
? ../examples/performant.py
? ../setup.py
? main.py
? watcher/_watcher.c
? watcher/watcher.py
? xyzzy.txt
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id381125">Telling you what's going on</h2></div></div></div><p id="x_54c"><a name="x_54c"></a>The <span class="command"><strong>hg add</strong></span> example in the
preceding section illustrates something else that's helpful
about Mercurial commands. If a command operates on a file that
you didn't name explicitly on the command line, it will usually
print the name of the file, so that you will not be surprised
what's going on.</p><p id="x_54d"><a name="x_54d"></a>The principle here is of <span class="emphasis"><em>least
surprise</em></span>. If you've exactly named a file on the
command line, there's no point in repeating it back at you. If
Mercurial is acting on a file <span class="emphasis"><em>implicitly</em></span>, e.g.
because you provided no names, or a directory, or a pattern (see
below), it is safest to tell you what files it's operating on.</p><p id="x_54e"><a name="x_54e"></a>For commands that behave this way, you can silence them
using the <code class="option">-q</code> option. You
can also get them to print the name of every file, even those
you've named explicitly, using the <code class="option">-v</code> option.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id381184">Using patterns to identify files</h2></div></div></div><p id="x_54f"><a name="x_54f"></a>In addition to working with file and directory names,
Mercurial lets you use <span class="emphasis"><em>patterns</em></span> to identify
files. Mercurial's pattern handling is expressive.</p><p id="x_550"><a name="x_550"></a>On Unix-like systems (Linux, MacOS, etc.), the job of
matching file names to patterns normally falls to the shell. On
these systems, you must explicitly tell Mercurial that a name is
a pattern. On Windows, the shell does not expand patterns, so
Mercurial will automatically identify names that are patterns,
and expand them for you.</p><p id="x_551"><a name="x_551"></a>To provide a pattern in place of a regular name on the
command line, the mechanism is simple:</p><pre id="id381219" class="programlisting">syntax:patternbody</pre><p id="x_552"><a name="x_552"></a>That is, a pattern is identified by a short text string that
says what kind of pattern this is, followed by a colon, followed
by the actual pattern.</p><p id="x_553"><a name="x_553"></a>Mercurial supports two kinds of pattern syntax. The most
frequently used is called <code class="literal">glob</code>; this is the
same kind of pattern matching used by the Unix shell, and should
be familiar to Windows command prompt users, too.</p><p id="x_554"><a name="x_554"></a>When Mercurial does automatic pattern matching on Windows,
it uses <code class="literal">glob</code> syntax. You can thus omit the
<span class="quote"><code class="literal">glob:</code></span>” prefix on Windows, but
it's safe to use it, too.</p><p id="x_555"><a name="x_555"></a>The <code class="literal">re</code> syntax is more powerful; it lets
you specify patterns using regular expressions, also known as
regexps.</p><p id="x_556"><a name="x_556"></a>By the way, in the examples that follow, notice that I'm
careful to wrap all of my patterns in quote characters, so that
they won't get expanded by the shell before Mercurial sees
them.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id381291">Shell-style <code class="literal">glob</code> patterns</h3></div></div></div><p id="x_557"><a name="x_557"></a>This is an overview of the kinds of patterns you can use
when you're matching on glob patterns.</p><p id="x_558"><a name="x_558"></a>The “<span class="quote"><code class="literal">*</code></span>” character matches
any string, within a single directory.</p><pre id="id381387" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg add 'glob:*.py'</code></strong>
adding main.py
</pre><p id="x_559"><a name="x_559"></a>The “<span class="quote"><code class="literal">**</code></span>” pattern matches
any string, and crosses directory boundaries. It's not a
standard Unix glob token, but it's accepted by several popular
Unix shells, and is very useful.</p><pre id="id381744" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:**.py'</code></strong>
A examples/simple.py
A src/main.py
? examples/performant.py
? setup.py
? src/watcher/watcher.py
</pre><p id="x_55a"><a name="x_55a"></a>The “<span class="quote"><code class="literal">?</code></span>” pattern matches
any single character.</p><pre id="id381494" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:**.?'</code></strong>
? src/watcher/_watcher.c
</pre><p id="x_55b"><a name="x_55b"></a>The “<span class="quote"><code class="literal">[</code></span>” character begins a
<span class="emphasis"><em>character class</em></span>. This matches any single
character within the class. The class ends with a
<span class="quote"><code class="literal">]</code></span>” character. A class may
contain multiple <span class="emphasis"><em>range</em></span>s of the form
<span class="quote"><code class="literal">a-f</code></span>”, which is shorthand for
<span class="quote"><code class="literal">abcdef</code></span>”.</p><pre id="id381693" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:**[nr-t]'</code></strong>
? MANIFEST.in
? src/xyzzy.txt
</pre><p id="x_55c"><a name="x_55c"></a>If the first character after the
<span class="quote"><code class="literal">[</code></span>” in a character class is a
<span class="quote"><code class="literal">!</code></span>”, it
<span class="emphasis"><em>negates</em></span> the class, making it match any
single character not in the class.</p><p id="x_55d"><a name="x_55d"></a>A “<span class="quote"><code class="literal">{</code></span>” begins a group of
subpatterns, where the whole group matches if any subpattern
in the group matches. The “<span class="quote"><code class="literal">,</code></span>
character separates subpatterns, and
<span class="quote"><code class="literal">}</code></span>” ends the group.</p><pre id="id381665" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:*.{in,py}'</code></strong>
? MANIFEST.in
? setup.py
</pre><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id381653">Watch out!</h4></div></div></div><p id="x_55e"><a name="x_55e"></a>Don't forget that if you want to match a pattern in any
directory, you should not be using the
<span class="quote"><code class="literal">*</code></span>” match-any token, as this
will only match within one directory. Instead, use the
<span class="quote"><code class="literal">**</code></span>” token. This small
example illustrates the difference between the two.</p><pre id="id382086" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:*.py'</code></strong>
? setup.py
<code class="prompt">$</code> <strong class="userinput"><code>hg status 'glob:**.py'</code></strong>
A examples/simple.py
A src/main.py
? examples/performant.py
? setup.py
? src/watcher/watcher.py
</pre></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id381804">Regular expression matching with <code class="literal">re</code>
patterns</h3></div></div></div><p id="x_55f"><a name="x_55f"></a>Mercurial accepts the same regular expression syntax as
the Python programming language (it uses Python's regexp
engine internally). This is based on the Perl language's
regexp syntax, which is the most popular dialect in use (it's
also used in Java, for example).</p><p id="x_560"><a name="x_560"></a>I won't discuss Mercurial's regexp dialect in any detail
here, as regexps are not often used. Perl-style regexps are
in any case already exhaustively documented on a multitude of
web sites, and in many books. Instead, I will focus here on a
few things you should know if you find yourself needing to use
regexps with Mercurial.</p><p id="x_561"><a name="x_561"></a>A regexp is matched against an entire file name, relative
to the root of the repository. In other words, even if you're
already in subbdirectory <code class="filename">foo</code>, if you want to match files
under this directory, your pattern must start with
<span class="quote"><code class="literal">foo/</code></span>”.</p><p id="x_562"><a name="x_562"></a>One thing to note, if you're familiar with Perl-style
regexps, is that Mercurial's are <span class="emphasis"><em>rooted</em></span>.
That is, a regexp starts matching against the beginning of a
string; it doesn't look for a match anywhere within the
string. To match anywhere in a string, start your pattern
with “<span class="quote"><code class="literal">.*</code></span>”.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id381878">Filtering files</h2></div></div></div><p id="x_563"><a name="x_563"></a>Not only does Mercurial give you a variety of ways to
specify files; it lets you further winnow those files using
<span class="emphasis"><em>filters</em></span>. Commands that work with file
names accept two filtering options.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_564"><a name="x_564"></a><code class="option">-I</code>, or
<code class="option">--include</code>, lets you
specify a pattern that file names must match in order to be
processed.</p></li><li><p id="x_565"><a name="x_565"></a><code class="option">-X</code>, or
<code class="option">--exclude</code>, gives you a
way to <span class="emphasis"><em>avoid</em></span> processing files, if they
match this pattern.</p></li></ul></div><p id="x_566"><a name="x_566"></a>You can provide multiple <code class="option">-I</code> and <code class="option">-X</code> options on the command line,
and intermix them as you please. Mercurial interprets the
patterns you provide using glob syntax by default (but you can
use regexps if you need to).</p><p id="x_567"><a name="x_567"></a>You can read a <code class="option">-I</code>
filter as “<span class="quote">process only the files that match this
filter</span>”.</p><pre id="id382042" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status -I '*.in'</code></strong>
? MANIFEST.in
</pre><p id="x_568"><a name="x_568"></a>The <code class="option">-X</code> filter is best
read as “<span class="quote">process only the files that don't match this
pattern</span>”.</p><pre id="id382014" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status -X '**.py' src</code></strong>
? src/watcher/_watcher.c
? src/xyzzy.txt
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id382104">Permanently ignoring unwanted files and directories</h2></div></div></div><p id="x_569"><a name="x_569"></a>When you create a new repository, the chances are
that over time it will grow to contain files that ought to
<span class="emphasis"><em>not</em></span> be managed by Mercurial, but which you
don't want to see listed every time you run <span class="command"><strong>hg
status</strong></span>. For instance, “<span class="quote">build products</span>
are files that are created as part of a build but which should
not be managed by a revision control system. The most common
build products are output files produced by software tools such
as compilers. As another example, many text editors litter a
directory with lock files, temporary working files, and backup
files, which it also makes no sense to manage.</p><p id="x_6b4"><a name="x_6b4"></a>To have Mercurial permanently ignore such files, create a
file named <code class="filename">.hgignore</code> in the root of your
repository. You <span class="emphasis"><em>should</em></span> <span class="command"><strong>hg
add</strong></span> this file so that it gets tracked with the rest of
your repository contents, since your collaborators will probably
find it useful too.</p><p id="x_6b5"><a name="x_6b5"></a>By default, the <code class="filename">.hgignore</code> file should
contain a list of regular expressions, one per line. Empty
lines are skipped. Most people prefer to describe the files they
want to ignore using the “<span class="quote">glob</span>” syntax that we
described above, so a typical <code class="filename">.hgignore</code>
file will start with this directive:</p><pre id="id382178" class="programlisting">syntax: glob</pre><p id="x_6b6"><a name="x_6b6"></a>This tells Mercurial to interpret the lines that follow as
glob patterns, not regular expressions.</p><p id="x_6b7"><a name="x_6b7"></a>Here is a typical-looking <code class="filename">.hgignore</code>
file.</p><pre id="id382204" class="programlisting">syntax: glob
# This line is a comment, and will be skipped.
# Empty lines are skipped too.
# Backup files left behind by the Emacs editor.
*~
# Lock files used by the Emacs editor.
# Notice that the "#" character is quoted with a backslash.
# This prevents it from being interpreted as starting a comment.
.\#*
# Temporary files used by the vim editor.
.*.swp
# A hidden file created by the Mac OS X Finder.
.DS_Store
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:names:case">Case sensitivity</h2></div></div></div><p id="x_56a"><a name="x_56a"></a>If you're working in a mixed development environment that
contains both Linux (or other Unix) systems and Macs or Windows
systems, you should keep in the back of your mind the knowledge
that they treat the case (“<span class="quote">N</span>” versus
<span class="quote">n</span>”) of file names in incompatible ways. This is
not very likely to affect you, and it's easy to deal with if it
does, but it could surprise you if you don't know about
it.</p><p id="x_56b"><a name="x_56b"></a>Operating systems and filesystems differ in the way they
handle the <span class="emphasis"><em>case</em></span> of characters in file and
directory names. There are three common ways to handle case in
names.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_56c"><a name="x_56c"></a>Completely case insensitive. Uppercase and
lowercase versions of a letter are treated as identical,
both when creating a file and during subsequent accesses.
This is common on older DOS-based systems.</p></li><li><p id="x_56d"><a name="x_56d"></a>Case preserving, but insensitive. When a file
or directory is created, the case of its name is stored, and
can be retrieved and displayed by the operating system.
When an existing file is being looked up, its case is
ignored. This is the standard arrangement on Windows and
MacOS. The names <code class="filename">foo</code> and
<code class="filename">FoO</code> identify the same file. This
treatment of uppercase and lowercase letters as
interchangeable is also referred to as <span class="emphasis"><em>case
folding</em></span>.</p></li><li><p id="x_56e"><a name="x_56e"></a>Case sensitive. The case of a name
is significant at all times. The names
<code class="filename">foo</code> and <code class="filename">FoO</code>
identify different files. This is the way Linux and Unix
systems normally work.</p></li></ul></div><p id="x_56f"><a name="x_56f"></a>On Unix-like systems, it is possible to have any or all of
the above ways of handling case in action at once. For example,
if you use a USB thumb drive formatted with a FAT32 filesystem
on a Linux system, Linux will handle names on that filesystem in
a case preserving, but insensitive, way.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id382327">Safe, portable repository storage</h3></div></div></div><p id="x_570"><a name="x_570"></a>Mercurial's repository storage mechanism is <span class="emphasis"><em>case
safe</em></span>. It translates file names so that they can
be safely stored on both case sensitive and case insensitive
filesystems. This means that you can use normal file copying
tools to transfer a Mercurial repository onto, for example, a
USB thumb drive, and safely move that drive and repository
back and forth between a Mac, a PC running Windows, and a
Linux box.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id382348">Detecting case conflicts</h3></div></div></div><p id="x_571"><a name="x_571"></a>When operating in the working directory, Mercurial honours
the naming policy of the filesystem where the working
directory is located. If the filesystem is case preserving,
but insensitive, Mercurial will treat names that differ only
in case as the same.</p><p id="x_572"><a name="x_572"></a>An important aspect of this approach is that it is
possible to commit a changeset on a case sensitive (typically
Linux or Unix) filesystem that will cause trouble for users on
case insensitive (usually Windows and MacOS) users. If a
Linux user commits changes to two files, one named
<code class="filename">myfile.c</code> and the other named
<code class="filename">MyFile.C</code>, they will be stored correctly
in the repository. And in the working directories of other
Linux users, they will be correctly represented as separate
files.</p><p id="x_573"><a name="x_573"></a>If a Windows or Mac user pulls this change, they will not
initially have a problem, because Mercurial's repository
storage mechanism is case safe. However, once they try to
<span class="command"><strong>hg update</strong></span> the working
directory to that changeset, or <span class="command"><strong>hg
merge</strong></span> with that changeset, Mercurial will spot the
conflict between the two file names that the filesystem would
treat as the same, and forbid the update or merge from
occurring.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id382414">Fixing a case conflict</h3></div></div></div><p id="x_574"><a name="x_574"></a>If you are using Windows or a Mac in a mixed environment
where some of your collaborators are using Linux or Unix, and
Mercurial reports a case folding conflict when you try to
<span class="command"><strong>hg update</strong></span> or <span class="command"><strong>hg merge</strong></span>, the procedure to fix the
problem is simple.</p><p id="x_575"><a name="x_575"></a>Just find a nearby Linux or Unix box, clone the problem
repository onto it, and use Mercurial's <span class="command"><strong>hg rename</strong></span> command to change the
names of any offending files or directories so that they will
no longer cause case folding conflicts. Commit this change,
<span class="command"><strong>hg pull</strong></span> or <span class="command"><strong>hg push</strong></span> it across to your Windows or
MacOS system, and <span class="command"><strong>hg update</strong></span>
to the revision with the non-conflicting names.</p><p id="x_576"><a name="x_576"></a>The changeset with case-conflicting names will remain in
your project's history, and you still won't be able to
<span class="command"><strong>hg update</strong></span> your working
directory to that changeset on a Windows or MacOS system, but
you can continue development unimpeded.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="collaborating-with-other-people.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="managing-releases-and-branchy-development.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 6. Collaborating with other people </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 8. Managing releases and branchy development</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,883 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 9. Finding and fixing mistakes</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="managing-releases-and-branchy-development.html" title="Chapter 8. Managing releases and branchy development"><link rel="next" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 9. Finding and fixing mistakes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="managing-releases-and-branchy-development.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="handling-repository-events-with-hooks.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:undo"><div class="titlepage"><div><div><h2 class="title">Chapter 9. Finding and fixing mistakes</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id390081">Erasing local history</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id390087">The accidental commit</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:rollback">Rolling back a transaction</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id390858">The erroneous pull</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:rollback-after-push">Rolling back is useless once you've pushed</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id391000">You can only roll back once</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id391367">Reverting the mistaken change</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:mgmt">File management errors</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id392218">Dealing with committed changes</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392287">Backing out a changeset</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392424">Backing out the tip changeset</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392766">Backing out a non-tip change</a></span></dt><dd><dl><dt><span class="sect3"><a href="finding-and-fixing-mistakes.html#id392990">Always use the --merge option</a></span></dt></dl></dd><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id393181">Gaining more control of the backout process</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id393814">Why hg backout works as
it does</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#sec:undo:aaaiiieee">Changes that should never have been</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394303">Backing out a merge</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394612">Protect yourself from escaped
changes</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394667">What to do about sensitive changes that escape</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#sec:undo:bisect">Finding the source of a bug</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394992">Using the hg bisect
command</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396541">Cleaning up after your search</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id396622">Tips for finding bugs effectively</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396628">Give consistent input</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396884">Automate as much as possible</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396713">Check your results</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396770">Beware interference between bugs</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396856">Bracket your search lazily</a></span></dt></dl></dd></dl></div><p id="x_d2"><a name="x_d2"></a>To err might be human, but to really handle the consequences
well takes a top-notch revision control system. In this chapter,
we'll discuss some of the techniques you can use when you find
that a problem has crept into your project. Mercurial has some
highly capable features that will help you to isolate the sources
of problems, and to handle them appropriately.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id390081">Erasing local history</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id390087">The accidental commit</h3></div></div></div><p id="x_d3"><a name="x_d3"></a>I have the occasional but persistent problem of typing
rather more quickly than I can think, which sometimes results
in me committing a changeset that is either incomplete or
plain wrong. In my case, the usual kind of incomplete
changeset is one in which I've created a new source file, but
forgotten to <span class="command"><strong>hg add</strong></span> it. A
<span class="quote">plain wrong</span>” changeset is not as common, but no
less annoying.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:rollback">Rolling back a transaction</h3></div></div></div><p id="x_d4"><a name="x_d4"></a>In <a class="xref" href="behind-the-scenes.html#sec:concepts:txn" title="Safe operation">the section called “Safe operation”</a>, I
mentioned that Mercurial treats each modification of a
repository as a <span class="emphasis"><em>transaction</em></span>. Every time
you commit a changeset or pull changes from another
repository, Mercurial remembers what you did. You can undo,
or <span class="emphasis"><em>roll back</em></span>, exactly one of these
actions using the <span class="command"><strong>hg rollback</strong></span>
command. (See <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:rollback-after-push" title="Rolling back is useless once you've pushed">the section called “Rolling back is useless once you've pushed”</a>
for an important caveat about the use of this command.)</p><p id="x_d5"><a name="x_d5"></a>Here's a mistake that I often find myself making:
committing a change in which I've created a new file, but
forgotten to <span class="command"><strong>hg add</strong></span>
it.</p><pre id="id390839" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
M a
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Add file b'</code></strong>
</pre><p id="x_d6"><a name="x_d6"></a>Looking at the output of <span class="command"><strong>hg
status</strong></span> after the commit immediately confirms the
error.</p><pre id="id390541" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
? b
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 1:f2db1de2ba4f
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:44 2009 +0000
summary: Add file b
</pre><p id="x_d7"><a name="x_d7"></a>The commit captured the changes to the file
<code class="filename">a</code>, but not the new file
<code class="filename">b</code>. If I were to push this changeset to a
repository that I shared with a colleague, the chances are
high that something in <code class="filename">a</code> would refer to
<code class="filename">b</code>, which would not be present in their
repository when they pulled my changes. I would thus become
the object of some indignation.</p><p id="x_d8"><a name="x_d8"></a>However, luck is with me—I've caught my error
before I pushed the changeset. I use the <span class="command"><strong>hg rollback</strong></span> command, and Mercurial
makes that last changeset vanish.</p><pre id="id391066" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
rolling back last transaction
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 0:cde70bc943e1
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:44 2009 +0000
summary: First commit
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
M a
? b
</pre><p id="x_d9"><a name="x_d9"></a>Notice that the changeset is no longer present in the
repository's history, and the working directory once again
thinks that the file <code class="filename">a</code> is modified. The
commit and rollback have left the working directory exactly as
it was prior to the commit; the changeset has been completely
erased. I can now safely <span class="command"><strong>hg
add</strong></span> the file <code class="filename">b</code>, and rerun my
commit.</p><pre id="id391024" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg add b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Add file b, this time for real'</code></strong>
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id390858">The erroneous pull</h3></div></div></div><p id="x_da"><a name="x_da"></a>It's common practice with Mercurial to maintain separate
development branches of a project in different repositories.
Your development team might have one shared repository for
your project's “<span class="quote">0.9</span>” release, and another,
containing different changes, for the “<span class="quote">1.0</span>
release.</p><p id="x_db"><a name="x_db"></a>Given this, you can imagine that the consequences could be
messy if you had a local “<span class="quote">0.9</span>” repository, and
accidentally pulled changes from the shared “<span class="quote">1.0</span>
repository into it. At worst, you could be paying
insufficient attention, and push those changes into the shared
<span class="quote">0.9</span>” tree, confusing your entire team (but don't
worry, we'll return to this horror scenario later). However,
it's more likely that you'll notice immediately, because
Mercurial will display the URL it's pulling from, or you will
see it pull a suspiciously large number of changes into the
repository.</p><p id="x_dc"><a name="x_dc"></a>The <span class="command"><strong>hg rollback</strong></span> command
will work nicely to expunge all of the changesets that you
just pulled. Mercurial groups all changes from one <span class="command"><strong>hg pull</strong></span> into a single transaction,
so one <span class="command"><strong>hg rollback</strong></span> is all you
need to undo this mistake.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:rollback-after-push">Rolling back is useless once you've pushed</h3></div></div></div><p id="x_dd"><a name="x_dd"></a>The value of the <span class="command"><strong>hg
rollback</strong></span> command drops to zero once you've pushed
your changes to another repository. Rolling back a change
makes it disappear entirely, but <span class="emphasis"><em>only</em></span> in
the repository in which you perform the <span class="command"><strong>hg rollback</strong></span>. Because a rollback
eliminates history, there's no way for the disappearance of a
change to propagate between repositories.</p><p id="x_de"><a name="x_de"></a>If you've pushed a change to another
repository—particularly if it's a shared
repository—it has essentially “<span class="quote">escaped into the
wild,</span>” and you'll have to recover from your mistake
in a different way. If you push a changeset somewhere, then
roll it back, then pull from the repository you pushed to, the
changeset you thought you'd gotten rid of will simply reappear
in your repository.</p><p id="x_df"><a name="x_df"></a>(If you absolutely know for sure that the change
you want to roll back is the most recent change in the
repository that you pushed to, <span class="emphasis"><em>and</em></span> you
know that nobody else could have pulled it from that
repository, you can roll back the changeset there, too, but
you really should not expect this to work reliably. Sooner or
later a change really will make it into a repository that you
don't directly control (or have forgotten about), and come
back to bite you.)</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id391000">You can only roll back once</h3></div></div></div><p id="x_e0"><a name="x_e0"></a>Mercurial stores exactly one transaction in its
transaction log; that transaction is the most recent one that
occurred in the repository. This means that you can only roll
back one transaction. If you expect to be able to roll back
one transaction, then its predecessor, this is not the
behavior you will get.</p><pre id="id391424" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
rolling back last transaction
<code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
no rollback information available
</pre><p id="x_e1"><a name="x_e1"></a>Once you've rolled back one transaction in a repository,
you can't roll back again in that repository until you perform
another commit or pull.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id391367">Reverting the mistaken change</h2></div></div></div><p id="x_e2"><a name="x_e2"></a>If you make a modification to a file, and decide that you
really didn't want to change the file at all, and you haven't
yet committed your changes, the <span class="command"><strong>hg
revert</strong></span> command is the one you'll need. It looks at
the changeset that's the parent of the working directory, and
restores the contents of the file to their state as of that
changeset. (That's a long-winded way of saying that, in the
normal case, it undoes your modifications.)</p><p id="x_e3"><a name="x_e3"></a>Let's illustrate how the <span class="command"><strong>hg
revert</strong></span> command works with yet another small example.
We'll begin by modifying a file that Mercurial is already
tracking.</p><pre id="id391316" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat file</code></strong>
original content
<code class="prompt">$</code> <strong class="userinput"><code>echo unwanted change &gt;&gt; file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg diff file</code></strong>
diff -r b52afd4afc59 file
--- a/file Tue May 05 06:55:32 2009 +0000
+++ b/file Tue May 05 06:55:32 2009 +0000
@@ -1,1 +1,2 @@
original content
+unwanted change
</pre><p id="x_e4"><a name="x_e4"></a>If we don't
want that change, we can simply <span class="command"><strong>hg
revert</strong></span> the file.</p><pre id="id391251" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
M file
<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat file</code></strong>
original content
</pre><p id="x_e5"><a name="x_e5"></a>The <span class="command"><strong>hg revert</strong></span> command
provides us with an extra degree of safety by saving our
modified file with a <code class="filename">.orig</code>
extension.</p><pre id="id391767" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
? file.orig
<code class="prompt">$</code> <strong class="userinput"><code>cat file.orig</code></strong>
original content
unwanted change
</pre><div class="tip"><table border="0" summary="Tip: Be careful with .orig files"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Be careful with .orig files</th></tr><tr><td align="left" valign="top"><p id="x_6b8"><a name="x_6b8"></a>It's extremely unlikely that you are either using
Mercurial to manage files with <code class="filename">.orig</code>
extensions or that you even care about the contents of such
files. Just in case, though, it's useful to remember that
<span class="command"><strong>hg revert</strong></span> will
unconditionally overwrite an existing file with a
<code class="filename">.orig</code> extension. For instance, if you
already have a file named <code class="filename">foo.orig</code> when
you revert <code class="filename">foo</code>, the contents of
<code class="filename">foo.orig</code> will be clobbered.</p></td></tr></table></div><p id="x_e6"><a name="x_e6"></a>Here is a summary of the cases that the <span class="command"><strong>hg revert</strong></span> command can deal with. We
will describe each of these in more detail in the section that
follows.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_e7"><a name="x_e7"></a>If you modify a file, it will restore the file
to its unmodified state.</p></li><li><p id="x_e8"><a name="x_e8"></a>If you <span class="command"><strong>hg add</strong></span> a
file, it will undo the “<span class="quote">added</span>” state of the
file, but leave the file itself untouched.</p></li><li><p id="x_e9"><a name="x_e9"></a>If you delete a file without telling Mercurial,
it will restore the file to its unmodified contents.</p></li><li><p id="x_ea"><a name="x_ea"></a>If you use the <span class="command"><strong>hg
remove</strong></span> command to remove a file, it will undo
the “<span class="quote">removed</span>” state of the file, and restore
the file to its unmodified contents.</p></li></ul></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:mgmt">File management errors</h3></div></div></div><p id="x_eb"><a name="x_eb"></a>The <span class="command"><strong>hg revert</strong></span> command is
useful for more than just modified files. It lets you reverse
the results of all of Mercurial's file management
commands—<span class="command"><strong>hg add</strong></span>,
<span class="command"><strong>hg remove</strong></span>, and so on.</p><p id="x_ec"><a name="x_ec"></a>If you <span class="command"><strong>hg add</strong></span> a file,
then decide that in fact you don't want Mercurial to track it,
use <span class="command"><strong>hg revert</strong></span> to undo the
add. Don't worry; Mercurial will not modify the file in any
way. It will just “<span class="quote">unmark</span>” the file.</p><pre id="id391756" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo oops &gt; oops</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add oops</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status oops</code></strong>
A oops
<code class="prompt">$</code> <strong class="userinput"><code>hg revert oops</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
? oops
</pre><p id="x_ed"><a name="x_ed"></a>Similarly, if you ask Mercurial to <span class="command"><strong>hg remove</strong></span> a file, you can use
<span class="command"><strong>hg revert</strong></span> to restore it to
the contents it had as of the parent of the working directory.
</p><pre id="id392036" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg remove file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
R file
<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls file</code></strong>
file
</pre><p>
This works just as
well for a file that you deleted by hand, without telling
Mercurial (recall that in Mercurial terminology, this kind of
file is called “<span class="quote">missing</span>”).</p><pre id="id391954" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>rm file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
! file
<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls file</code></strong>
file
</pre><p id="x_ee"><a name="x_ee"></a>If you revert a <span class="command"><strong>hg copy</strong></span>,
the copied-to file remains in your working directory
afterwards, untracked. Since a copy doesn't affect the
copied-from file in any way, Mercurial doesn't do anything
with the copied-from file.</p><pre id="id392181" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg copy file new-file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg revert new-file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
? new-file
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id392218">Dealing with committed changes</h2></div></div></div><p id="x_f5"><a name="x_f5"></a>Consider a case where you have committed a change
<span class="emphasis"><em>a</em></span>, and another change
<span class="emphasis"><em>b</em></span> on top of it; you then realise that
change <span class="emphasis"><em>a</em></span> was incorrect. Mercurial lets you
<span class="quote">back out</span>” an entire changeset automatically, and
building blocks that let you reverse part of a changeset by
hand.</p><p id="x_f6"><a name="x_f6"></a>Before you read this section, here's something to
keep in mind: the <span class="command"><strong>hg backout</strong></span>
command undoes the effect of a change by
<span class="emphasis"><em>adding</em></span> to your repository's history, not by
modifying or erasing it. It's the right tool to use if you're
fixing bugs, but not if you're trying to undo some change that
has catastrophic consequences. To deal with those, see
<a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:aaaiiieee" title="Changes that should never have been">the section called “Changes that should never have been”</a>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392287">Backing out a changeset</h3></div></div></div><p id="x_f7"><a name="x_f7"></a>The <span class="command"><strong>hg backout</strong></span> command
lets you “<span class="quote">undo</span>” the effects of an entire
changeset in an automated fashion. Because Mercurial's
history is immutable, this command <span class="emphasis"><em>does
not</em></span> get rid of the changeset you want to undo.
Instead, it creates a new changeset that
<span class="emphasis"><em>reverses</em></span> the effect of the to-be-undone
changeset.</p><p id="x_f8"><a name="x_f8"></a>The operation of the <span class="command"><strong>hg
backout</strong></span> command is a little intricate, so let's
illustrate it with some examples. First, we'll create a
repository with some simple changes.</p><pre id="id392685" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init myrepo</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd myrepo</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo first change &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'first change'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo second change &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'second change'</code></strong>
</pre><p id="x_f9"><a name="x_f9"></a>The <span class="command"><strong>hg backout</strong></span> command
takes a single changeset ID as its argument; this is the
changeset to back out. Normally, <span class="command"><strong>hg
backout</strong></span> will drop you into a text editor to write
a commit message, so you can record why you're backing the
change out. In this example, we provide a commit message on
the command line using the <code class="option">-m</code> option.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392424">Backing out the tip changeset</h3></div></div></div><p id="x_fa"><a name="x_fa"></a>We're going to start by backing out the last changeset we
committed.</p><pre id="id392577" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg backout -m 'back out second change' tip</code></strong>
reverting myfile
changeset 2:01adc4672142 backs out changeset 1:7e341ee3be7a
<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
first change
</pre><p id="x_fb"><a name="x_fb"></a>You can see that the second line from
<code class="filename">myfile</code> is no longer present. Taking a
look at the output of <span class="command"><strong>hg log</strong></span>
gives us an idea of what the <span class="command"><strong>hg
backout</strong></span> command has done.
</p><pre id="id392554" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
2[tip] 01adc4672142 2009-05-05 06:55 +0000 bos
back out second change
1 7e341ee3be7a 2009-05-05 06:55 +0000 bos
second change
0 56b97fc928f2 2009-05-05 06:55 +0000 bos
first change
</pre><p>
Notice that the new changeset
that <span class="command"><strong>hg backout</strong></span> has created
is a child of the changeset we backed out. It's easier to see
this in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout" title="Figure 9.1. Backing out a change using the hg backout command">Figure 9.1, “Backing out a change using the hg backout command”</a>, which presents a
graphical view of the change history. As you can see, the
history is nice and linear.</p><div class="figure"><a name="fig:undo:backout"></a><p class="title"><b>Figure 9.1. Backing out a change using the <span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-simple.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392766">Backing out a non-tip change</h3></div></div></div><p id="x_fd"><a name="x_fd"></a>If you want to back out a change other than the last one
you committed, pass the <code class="option">--merge</code> option to the
<span class="command"><strong>hg backout</strong></span> command.</p><pre id="id393141" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone -r1 myrepo non-tip-repo</code></strong>
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd non-tip-repo</code></strong>
</pre><p id="x_fe"><a name="x_fe"></a>This makes backing out any changeset a
<span class="quote">one-shot</span>” operation that's usually simple and
fast.</p><pre id="id392845" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo third change &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'third change'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg backout --merge -m 'back out second change' 1</code></strong>
reverting myfile
created new head
changeset 3:abc7fd860049 backs out changeset 1:7e341ee3be7a
merging with changeset 3:abc7fd860049
merging myfile
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
</pre><p id="x_ff"><a name="x_ff"></a>If you take a look at the contents of
<code class="filename">myfile</code> after the backout finishes, you'll
see that the first and third changes are present, but not the
second.</p><pre id="id392886" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
first change
third change
</pre><p id="x_100"><a name="x_100"></a>As the graphical history in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-non-tip" title="Figure 9.2. Automated backout of a non-tip change using the hg backout command">Figure 9.2, “Automated backout of a non-tip change using the
hg backout command”</a> illustrates, Mercurial
still commits one change in this kind of situation (the
box-shaped node is the ones that Mercurial commits
automatically), but the revision graph now looks different.
Before Mercurial begins the backout process, it first
remembers what the current parent of the working directory is.
It then backs out the target changeset, and commits that as a
changeset. Finally, it merges back to the previous parent of
the working directory, but notice that it <span class="emphasis"><em>does not
commit</em></span> the result of the merge. The repository
now contains two heads, and the working directory is in a
merge state.</p><div class="figure"><a name="fig:undo:backout-non-tip"></a><p class="title"><b>Figure 9.2. Automated backout of a non-tip change using the
<span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-non-tip.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_103"><a name="x_103"></a>The result is that you end up “<span class="quote">back where you
were</span>”, only with some extra history that undoes the
effect of the changeset you wanted to back out.</p><p id="x_6b9"><a name="x_6b9"></a>You might wonder why Mercurial does not commit the result
of the merge that it performed. The reason lies in Mercurial
behaving conservatively: a merge naturally has more scope for
error than simply undoing the effect of the tip changeset,
so your work will be safest if you first inspect (and test!)
the result of the merge, <span class="emphasis"><em>then</em></span> commit
it.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id392990">Always use the <code class="option">--merge</code> option</h4></div></div></div><p id="x_104"><a name="x_104"></a>In fact, since the <code class="option">--merge</code> option will do the
<span class="quote">right thing</span>” whether or not the changeset
you're backing out is the tip (i.e. it won't try to merge if
it's backing out the tip, since there's no need), you should
<span class="emphasis"><em>always</em></span> use this option when you run the
<span class="command"><strong>hg backout</strong></span> command.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id393181">Gaining more control of the backout process</h3></div></div></div><p id="x_105"><a name="x_105"></a>While I've recommended that you always use the <code class="option">--merge</code> option when backing
out a change, the <span class="command"><strong>hg backout</strong></span>
command lets you decide how to merge a backout changeset.
Taking control of the backout process by hand is something you
will rarely need to do, but it can be useful to understand
what the <span class="command"><strong>hg backout</strong></span> command
is doing for you automatically. To illustrate this, let's
clone our first repository, but omit the backout change that
it contains.</p><pre id="id393568" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone -r1 myrepo newrepo</code></strong>
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd newrepo</code></strong>
</pre><p id="x_106"><a name="x_106"></a>As with our
earlier example, We'll commit a third changeset, then back out
its parent, and see what happens.</p><pre id="id393553" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo third change &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'third change'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg backout -m 'back out second change' 1</code></strong>
reverting myfile
created new head
changeset 3:abc7fd860049 backs out changeset 1:7e341ee3be7a
the backout changeset is a new head - do not forget to merge
(use "backout --merge" if you want to auto-merge)
</pre><p id="x_107"><a name="x_107"></a>Our new changeset is again a descendant of the changeset
we backout out; it's thus a new head, <span class="emphasis"><em>not</em></span>
a descendant of the changeset that was the tip. The <span class="command"><strong>hg backout</strong></span> command was quite
explicit in telling us this.</p><pre id="id393314" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
3[tip]:1 abc7fd860049 2009-05-05 06:55 +0000 bos
back out second change
2 bae4005ddac4 2009-05-05 06:55 +0000 bos
third change
1 7e341ee3be7a 2009-05-05 06:55 +0000 bos
second change
0 56b97fc928f2 2009-05-05 06:55 +0000 bos
first change
</pre><p id="x_108"><a name="x_108"></a>Again, it's easier to see what has happened by looking at
a graph of the revision history, in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-manual" title="Figure 9.3. Backing out a change using the hg backout command">Figure 9.3, “Backing out a change using the hg backout command”</a>. This makes it clear
that when we use <span class="command"><strong>hg backout</strong></span>
to back out a change other than the tip, Mercurial adds a new
head to the repository (the change it committed is
box-shaped).</p><div class="figure"><a name="fig:undo:backout-manual"></a><p class="title"><b>Figure 9.3. Backing out a change using the <span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-manual.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_10a"><a name="x_10a"></a>After the <span class="command"><strong>hg backout</strong></span>
command has completed, it leaves the new
<span class="quote">backout</span>” changeset as the parent of the working
directory.</p><pre id="id393912" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 2:bae4005ddac4
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:12 2009 +0000
summary: third change
</pre><p id="x_10b"><a name="x_10b"></a>Now we have two isolated sets of changes.</p><pre id="id393905" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg heads</code></strong>
changeset: 3:abc7fd860049
tag: tip
parent: 1:7e341ee3be7a
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:12 2009 +0000
summary: back out second change
changeset: 2:bae4005ddac4
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:12 2009 +0000
summary: third change
</pre><p id="x_10c"><a name="x_10c"></a>Let's think about what we expect to see as the contents of
<code class="filename">myfile</code> now. The first change should be
present, because we've never backed it out. The second change
should be missing, as that's the change we backed out. Since
the history graph shows the third change as a separate head,
we <span class="emphasis"><em>don't</em></span> expect to see the third change
present in <code class="filename">myfile</code>.</p><pre id="id393884" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
first change
</pre><p id="x_10d"><a name="x_10d"></a>To get the third change back into the file, we just do a
normal merge of our two heads.</p><pre id="id393845" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
abort: outstanding uncommitted changes
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'merged backout with previous tip'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
first change
</pre><p id="x_10e"><a name="x_10e"></a>Afterwards, the graphical history of our
repository looks like
<a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-manual-merge" title="Figure 9.4. Manually merging a backout change">Figure 9.4, “Manually merging a backout change”</a>.</p><div class="figure"><a name="fig:undo:backout-manual-merge"></a><p class="title"><b>Figure 9.4. Manually merging a backout change</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-manual-merge.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id393814">Why <span class="command"><strong>hg backout</strong></span> works as
it does</h3></div></div></div><p id="x_110"><a name="x_110"></a>Here's a brief description of how the <span class="command"><strong>hg backout</strong></span> command works.</p><div class="orderedlist"><ol type="1"><li><p id="x_111"><a name="x_111"></a>It ensures that the working directory is
<span class="quote">clean</span>”, i.e. that the output of <span class="command"><strong>hg status</strong></span> would be empty.</p></li><li><p id="x_112"><a name="x_112"></a>It remembers the current parent of the working
directory. Let's call this changeset
<code class="literal">orig</code>.</p></li><li><p id="x_113"><a name="x_113"></a>It does the equivalent of a <span class="command"><strong>hg update</strong></span> to sync the working
directory to the changeset you want to back out. Let's
call this changeset <code class="literal">backout</code>.</p></li><li><p id="x_114"><a name="x_114"></a>It finds the parent of that changeset. Let's
call that changeset <code class="literal">parent</code>.</p></li><li><p id="x_115"><a name="x_115"></a>For each file that the
<code class="literal">backout</code> changeset affected, it does the
equivalent of a <span class="command"><strong>hg revert -r
parent</strong></span> on that file, to restore it to the
contents it had before that changeset was
committed.</p></li><li><p id="x_116"><a name="x_116"></a>It commits the result as a new changeset.
This changeset has <code class="literal">backout</code> as its
parent.</p></li><li><p id="x_117"><a name="x_117"></a>If you specify <code class="option">--merge</code> on the command
line, it merges with <code class="literal">orig</code>, and commits
the result of the merge.</p></li></ol></div><p id="x_118"><a name="x_118"></a>An alternative way to implement the <span class="command"><strong>hg backout</strong></span> command would be to
<span class="command"><strong>hg export</strong></span> the
to-be-backed-out changeset as a diff, then use the <code class="option">--reverse</code> option to the
<span class="command"><strong>patch</strong></span> command to reverse the effect of the
change without fiddling with the working directory. This
sounds much simpler, but it would not work nearly as
well.</p><p id="x_119"><a name="x_119"></a>The reason that <span class="command"><strong>hg
backout</strong></span> does an update, a commit, a merge, and
another commit is to give the merge machinery the best chance
to do a good job when dealing with all the changes
<span class="emphasis"><em>between</em></span> the change you're backing out and
the current tip.</p><p id="x_11a"><a name="x_11a"></a>If you're backing out a changeset that's 100 revisions
back in your project's history, the chances that the
<span class="command"><strong>patch</strong></span> command will be able to apply a
reverse diff cleanly are not good, because intervening changes
are likely to have “<span class="quote">broken the context</span>” that
<span class="command"><strong>patch</strong></span> uses to determine whether it can
apply a patch (if this sounds like gibberish, see <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:patch" title="Understanding patches">the section called “Understanding patches”</a> for a
discussion of the <span class="command"><strong>patch</strong></span> command). Also,
Mercurial's merge machinery will handle files and directories
being renamed, permission changes, and modifications to binary
files, none of which <span class="command"><strong>patch</strong></span> can deal
with.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:undo:aaaiiieee">Changes that should never have been</h2></div></div></div><p id="x_11b"><a name="x_11b"></a>Most of the time, the <span class="command"><strong>hg
backout</strong></span> command is exactly what you need if you want
to undo the effects of a change. It leaves a permanent record
of exactly what you did, both when committing the original
changeset and when you cleaned up after it.</p><p id="x_11c"><a name="x_11c"></a>On rare occasions, though, you may find that you've
committed a change that really should not be present in the
repository at all. For example, it would be very unusual, and
usually considered a mistake, to commit a software project's
object files as well as its source files. Object files have
almost no intrinsic value, and they're <span class="emphasis"><em>big</em></span>,
so they increase the size of the repository and the amount of
time it takes to clone or pull changes.</p><p id="x_11d"><a name="x_11d"></a>Before I discuss the options that you have if you commit a
<span class="quote">brown paper bag</span>” change (the kind that's so bad
that you want to pull a brown paper bag over your head), let me
first discuss some approaches that probably won't work.</p><p id="x_11e"><a name="x_11e"></a>Since Mercurial treats history as
accumulative—every change builds on top of all changes
that preceded it—you generally can't just make disastrous
changes disappear. The one exception is when you've just
committed a change, and it hasn't been pushed or pulled into
another repository. That's when you can safely use the <span class="command"><strong>hg rollback</strong></span> command, as I detailed in
<a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:rollback" title="Rolling back a transaction">the section called “Rolling back a transaction”</a>.</p><p id="x_11f"><a name="x_11f"></a>After you've pushed a bad change to another repository, you
<span class="emphasis"><em>could</em></span> still use <span class="command"><strong>hg
rollback</strong></span> to make your local copy of the change
disappear, but it won't have the consequences you want. The
change will still be present in the remote repository, so it
will reappear in your local repository the next time you
pull.</p><p id="x_120"><a name="x_120"></a>If a situation like this arises, and you know which
repositories your bad change has propagated into, you can
<span class="emphasis"><em>try</em></span> to get rid of the change from
<span class="emphasis"><em>every</em></span> one of those repositories. This is,
of course, not a satisfactory solution: if you miss even a
single repository while you're expunging, the change is still
<span class="quote">in the wild</span>”, and could propagate further.</p><p id="x_121"><a name="x_121"></a>If you've committed one or more changes
<span class="emphasis"><em>after</em></span> the change that you'd like to see
disappear, your options are further reduced. Mercurial doesn't
provide a way to “<span class="quote">punch a hole</span>” in history, leaving
changesets intact.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394303">Backing out a merge</h3></div></div></div><p id="x_6ba"><a name="x_6ba"></a>Since merges are often complicated, it is not unheard of
for a merge to be mangled badly, but committed erroneously.
Mercurial provides an important safeguard against bad merges
by refusing to commit unresolved files, but human ingenuity
guarantees that it is still possible to mess a merge up and
commit it.</p><p id="x_6bb"><a name="x_6bb"></a>Given a bad merge that has been committed, usually the
best way to approach it is to simply try to repair the damage
by hand. A complete disaster that cannot be easily fixed up
by hand ought to be very rare, but the <span class="command"><strong>hg backout</strong></span> command may help in
making the cleanup easier. It offers a <code class="option">--parent</code> option, which lets
you specify which parent to revert to when backing out a
merge.</p><div class="figure"><a name="fig:undo:bad-merge-1"></a><p class="title"><b>Figure 9.5. A bad merge</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-1.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_6bc"><a name="x_6bc"></a>Suppose we have a revision graph like that in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-1" title="Figure 9.5. A bad merge">Figure 9.5, “A bad merge”</a>. What we'd like is to
<span class="emphasis"><em>redo</em></span> the merge of revisions 2 and
3.</p><p id="x_6bd"><a name="x_6bd"></a>One way to do so would be as follows.</p><div class="orderedlist"><ol type="1"><li><p id="x_6be"><a name="x_6be"></a>Call <span class="command"><strong>hg backout --rev=4
--parent=2</strong></span>. This tells <span class="command"><strong>hg backout</strong></span> to back out revision
4, which is the bad merge, and to when deciding which
revision to prefer, to choose parent 2, one of the parents
of the merge. The effect can be seen in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-2" title="Figure 9.6. Backing out the merge, favoring one parent">Figure 9.6, “Backing out the merge, favoring one parent”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-2"></a><p class="title"><b>Figure 9.6. Backing out the merge, favoring one parent</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-2.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6bf"><a name="x_6bf"></a>Call <span class="command"><strong>hg backout --rev=4
--parent=3</strong></span>. This tells <span class="command"><strong>hg backout</strong></span> to back out revision
4 again, but this time to choose parent 3, the other
parent of the merge. The result is visible in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-3" title="Figure 9.7. Backing out the merge, favoring the other parent">Figure 9.7, “Backing out the merge, favoring the other
parent”</a>, in which the repository
now contains three heads.</p><div class="figure"><a name="fig:undo:bad-merge-3"></a><p class="title"><b>Figure 9.7. Backing out the merge, favoring the other
parent</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-3.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6c0"><a name="x_6c0"></a>Redo the bad merge by merging the two backout heads,
which reduces the number of heads in the repository to
two, as can be seen in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-4" title="Figure 9.8. Merging the backouts">Figure 9.8, “Merging the backouts”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-4"></a><p class="title"><b>Figure 9.8. Merging the backouts</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-4.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6c1"><a name="x_6c1"></a>Merge with the commit that was made after the bad
merge, as shown in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-5" title="Figure 9.9. Merging the backouts">Figure 9.9, “Merging the backouts”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-5"></a><p class="title"><b>Figure 9.9. Merging the backouts</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-5.png" alt="XXX add text"></div></div></div><br class="figure-break"></li></ol></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394612">Protect yourself from “<span class="quote">escaped</span>
changes</h3></div></div></div><p id="x_123"><a name="x_123"></a>If you've committed some changes to your local repository
and they've been pushed or pulled somewhere else, this isn't
necessarily a disaster. You can protect yourself ahead of
time against some classes of bad changeset. This is
particularly easy if your team usually pulls changes from a
central repository.</p><p id="x_124"><a name="x_124"></a>By configuring some hooks on that repository to validate
incoming changesets (see chapter <a class="xref" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks">Chapter 10, <i>Handling repository events with hooks</i></a>),
you can
automatically prevent some kinds of bad changeset from being
pushed to the central repository at all. With such a
configuration in place, some kinds of bad changeset will
naturally tend to “<span class="quote">die out</span>” because they can't
propagate into the central repository. Better yet, this
happens without any need for explicit intervention.</p><p id="x_125"><a name="x_125"></a>For instance, an incoming change hook that
verifies that a changeset will actually compile can prevent
people from inadvertently “<span class="quote">breaking the
build</span>”.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394667">What to do about sensitive changes that escape</h3></div></div></div><p id="x_6c2"><a name="x_6c2"></a>Even a carefully run project can suffer an unfortunate
event such as the committing and uncontrolled propagation of a
file that contains important passwords.</p><p id="x_6c3"><a name="x_6c3"></a>If something like this happens to you, and the information
that gets accidentally propagated is truly sensitive, your
first step should be to mitigate the effect of the leak
without trying to control the leak itself. If you are not 100%
certain that you know exactly who could have seen the changes,
you should immediately change passwords, cancel credit cards,
or find some other way to make sure that the information that
has leaked is no longer useful. In other words, assume that
the change has propagated far and wide, and that there's
nothing more you can do.</p><p id="x_6c4"><a name="x_6c4"></a>You might hope that there would be mechanisms you could
use to either figure out who has seen a change or to erase the
change permanently everywhere, but there are good reasons why
these are not possible.</p><p id="x_6c5"><a name="x_6c5"></a>Mercurial does not provide an audit trail of who has
pulled changes from a repository, because it is usually either
impossible to record such information or trivial to spoof it.
In a multi-user or networked environment, you should thus be
extremely skeptical of yourself if you think that you have
identified every place that a sensitive changeset has
propagated to. Don't forget that people can and will send
bundles by email, have their backup software save data
offsite, carry repositories on USB sticks, and find other
completely innocent ways to confound your attempts to track
down every copy of a problematic change.</p><p id="x_6c6"><a name="x_6c6"></a>Mercurial also does not provide a way to make a file or
changeset completely disappear from history, because there is
no way to enforce its disappearance; someone could easily
modify their copy of Mercurial to ignore such directives. In
addition, even if Mercurial provided such a capability,
someone who simply hadn't pulled a “<span class="quote">make this file
disappear</span>” changeset wouldn't be affected by it, nor
would web crawlers visiting at the wrong time, disk backups,
or other mechanisms. Indeed, no distributed revision control
system can make data reliably vanish. Providing the illusion
of such control could easily give a false sense of security,
and be worse than not providing it at all.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:undo:bisect">Finding the source of a bug</h2></div></div></div><p id="x_126"><a name="x_126"></a>While it's all very well to be able to back out a changeset
that introduced a bug, this requires that you know which
changeset to back out. Mercurial provides an invaluable
command, called <span class="command"><strong>hg bisect</strong></span>, that
helps you to automate this process and accomplish it very
efficiently.</p><p id="x_127"><a name="x_127"></a>The idea behind the <span class="command"><strong>hg
bisect</strong></span> command is that a changeset has introduced
some change of behavior that you can identify with a simple
pass/fail test. You don't know which piece of code introduced the
change, but you know how to test for the presence of the bug.
The <span class="command"><strong>hg bisect</strong></span> command uses your
test to direct its search for the changeset that introduced the
code that caused the bug.</p><p id="x_128"><a name="x_128"></a>Here are a few scenarios to help you understand how you
might apply this command.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_129"><a name="x_129"></a>The most recent version of your software has a
bug that you remember wasn't present a few weeks ago, but
you don't know when it was introduced. Here, your binary
test checks for the presence of that bug.</p></li><li><p id="x_12a"><a name="x_12a"></a>You fixed a bug in a rush, and now it's time to
close the entry in your team's bug database. The bug
database requires a changeset ID when you close an entry,
but you don't remember which changeset you fixed the bug in.
Once again, your binary test checks for the presence of the
bug.</p></li><li><p id="x_12b"><a name="x_12b"></a>Your software works correctly, but runs 15%
slower than the last time you measured it. You want to know
which changeset introduced the performance regression. In
this case, your binary test measures the performance of your
software, to see whether it's “<span class="quote">fast</span>” or
<span class="quote">slow</span>”.</p></li><li><p id="x_12c"><a name="x_12c"></a>The sizes of the components of your project that
you ship exploded recently, and you suspect that something
changed in the way you build your project.</p></li></ul></div><p id="x_12d"><a name="x_12d"></a>From these examples, it should be clear that the <span class="command"><strong>hg bisect</strong></span> command is not useful only
for finding the sources of bugs. You can use it to find any
<span class="quote">emergent property</span>” of a repository (anything that
you can't find from a simple text search of the files in the
tree) for which you can write a binary test.</p><p id="x_12e"><a name="x_12e"></a>We'll introduce a little bit of terminology here, just to
make it clear which parts of the search process are your
responsibility, and which are Mercurial's. A
<span class="emphasis"><em>test</em></span> is something that
<span class="emphasis"><em>you</em></span> run when <span class="command"><strong>hg
bisect</strong></span> chooses a changeset. A
<span class="emphasis"><em>probe</em></span> is what <span class="command"><strong>hg
bisect</strong></span> runs to tell whether a revision is good.
Finally, we'll use the word “<span class="quote">bisect</span>”, as both a
noun and a verb, to stand in for the phrase “<span class="quote">search using
the <span class="command"><strong>hg bisect</strong></span>
command</span>”.</p><p id="x_12f"><a name="x_12f"></a>One simple way to automate the searching process would be
simply to probe every changeset. However, this scales poorly.
If it took ten minutes to test a single changeset, and you had
10,000 changesets in your repository, the exhaustive approach
would take on average 35 <span class="emphasis"><em>days</em></span> to find the
changeset that introduced a bug. Even if you knew that the bug
was introduced by one of the last 500 changesets, and limited
your search to those, you'd still be looking at over 40 hours to
find the changeset that introduced your bug.</p><p id="x_130"><a name="x_130"></a>What the <span class="command"><strong>hg bisect</strong></span> command
does is use its knowledge of the “<span class="quote">shape</span>” of your
project's revision history to perform a search in time
proportional to the <span class="emphasis"><em>logarithm</em></span> of the number
of changesets to check (the kind of search it performs is called
a dichotomic search). With this approach, searching through
10,000 changesets will take less than three hours, even at ten
minutes per test (the search will require about 14 tests).
Limit your search to the last hundred changesets, and it will
take only about an hour (roughly seven tests).</p><p id="x_131"><a name="x_131"></a>The <span class="command"><strong>hg bisect</strong></span> command is
aware of the “<span class="quote">branchy</span>” nature of a Mercurial
project's revision history, so it has no problems dealing with
branches, merges, or multiple heads in a repository. It can
prune entire branches of history with a single probe, which is
how it operates so efficiently.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394992">Using the <span class="command"><strong>hg bisect</strong></span>
command</h3></div></div></div><p id="x_132"><a name="x_132"></a>Here's an example of <span class="command"><strong>hg
bisect</strong></span> in action.</p><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_133"><a name="x_133"></a> In versions 0.9.5 and earlier of Mercurial, <span class="command"><strong>hg bisect</strong></span> was not a core command:
it was distributed with Mercurial as an extension. This
section describes the built-in command, not the old
extension.</p></td></tr></table></div><p id="x_134"><a name="x_134"></a>Now let's create a repository, so that we can try out the
<span class="command"><strong>hg bisect</strong></span> command in
isolation.</p><pre id="id395406" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init mybug</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd mybug</code></strong>
</pre><p id="x_135"><a name="x_135"></a>We'll simulate a project that has a bug in it in a
simple-minded way: create trivial changes in a loop, and
nominate one specific change that will have the
<span class="quote">bug</span>”. This loop creates 35 changesets, each
adding a single file to the repository. We'll represent our
<span class="quote">bug</span>” with a file that contains the text “<span class="quote">i
have a gub</span>”.</p><pre id="id395397" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>buggy_change=22</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>for (( i = 0; i &lt; 35; i++ )); do</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> if [[ $i = $buggy_change ]]; then</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> echo 'i have a gub' &gt; myfile$i</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> hg commit -q -A -m 'buggy changeset'</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> else</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> echo 'nothing to see here, move along' &gt; myfile$i</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> hg commit -q -A -m 'normal changeset'</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> fi</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>done</code></strong>
</pre><p id="x_136"><a name="x_136"></a>The next thing that we'd like to do is figure out how to
use the <span class="command"><strong>hg bisect</strong></span> command.
We can use Mercurial's normal built-in help mechanism for
this.</p><pre id="id395535" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg help bisect</code></strong>
hg bisect [-gbsr] [-c CMD] [REV]
subdivision search of changesets
This command helps to find changesets which introduce problems.
To use, mark the earliest changeset you know exhibits the problem
as bad, then mark the latest changeset which is free from the
problem as good. Bisect will update your working directory to a
revision for testing (unless the --noupdate option is specified).
Once you have performed tests, mark the working directory as bad
or good and bisect will either update to another candidate changeset
or announce that it has found the bad revision.
As a shortcut, you can also use the revision argument to mark a
revision as good or bad without checking it out first.
If you supply a command it will be used for automatic bisection. Its exit
status will be used as flag to mark revision as bad or good. In case exit
status is 0 the revision is marked as good, 125 - skipped, 127 (command not
found) - bisection will be aborted; any other status bigger than 0 will
mark revision as bad.
options:
-r --reset reset bisect state
-g --good mark changeset good
-b --bad mark changeset bad
-s --skip skip testing changeset
-c --command use command to check changeset state
-U --noupdate do not update to target
use "hg -v help bisect" to show global options
</pre><p id="x_137"><a name="x_137"></a>The <span class="command"><strong>hg bisect</strong></span> command
works in steps. Each step proceeds as follows.</p><div class="orderedlist"><ol type="1"><li><p id="x_138"><a name="x_138"></a>You run your binary test.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_139"><a name="x_139"></a>If the test succeeded, you tell <span class="command"><strong>hg bisect</strong></span> by running the
<span class="command"><strong>hg bisect --good</strong></span>
command.</p></li><li><p id="x_13a"><a name="x_13a"></a>If it failed, run the <span class="command"><strong>hg bisect --bad</strong></span>
command.</p></li></ul></div></li><li><p id="x_13b"><a name="x_13b"></a>The command uses your information to decide
which changeset to test next.</p></li><li><p id="x_13c"><a name="x_13c"></a>It updates the working directory to that
changeset, and the process begins again.</p></li></ol></div><p id="x_13d"><a name="x_13d"></a>The process ends when <span class="command"><strong>hg
bisect</strong></span> identifies a unique changeset that marks
the point where your test transitioned from
<span class="quote">succeeding</span>” to “<span class="quote">failing</span>”.</p><p id="x_13e"><a name="x_13e"></a>To start the search, we must run the <span class="command"><strong>hg bisect --reset</strong></span> command.</p><pre id="id395968" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --reset</code></strong>
</pre><p id="x_13f"><a name="x_13f"></a>In our case, the binary test we use is simple: we check to
see if any file in the repository contains the string “<span class="quote">i
have a gub</span>”. If it does, this changeset contains the
change that “<span class="quote">caused the bug</span>”. By convention, a
changeset that has the property we're searching for is
<span class="quote">bad</span>”, while one that doesn't is
<span class="quote">good</span>”.</p><p id="x_140"><a name="x_140"></a>Most of the time, the revision to which the working
directory is synced (usually the tip) already exhibits the
problem introduced by the buggy change, so we'll mark it as
<span class="quote">bad</span>”.</p><pre id="id396047" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --bad</code></strong>
</pre><p id="x_141"><a name="x_141"></a>Our next task is to nominate a changeset that we know
<span class="emphasis"><em>doesn't</em></span> have the bug; the <span class="command"><strong>hg bisect</strong></span> command will
<span class="quote">bracket</span>” its search between the first pair of
good and bad changesets. In our case, we know that revision
10 didn't have the bug. (I'll have more words about choosing
the first “<span class="quote">good</span>” changeset later.)</p><pre id="id396032" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --good 10</code></strong>
Testing changeset 22:b8789808fc48 (24 changesets remaining, ~4 tests)
0 files updated, 0 files merged, 12 files removed, 0 files unresolved
</pre><p id="x_142"><a name="x_142"></a>Notice that this command printed some output.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_143"><a name="x_143"></a>It told us how many changesets it must
consider before it can identify the one that introduced
the bug, and how many tests that will require.</p></li><li><p id="x_144"><a name="x_144"></a>It updated the working directory to the next
changeset to test, and told us which changeset it's
testing.</p></li></ul></div><p id="x_145"><a name="x_145"></a>We now run our test in the working directory. We use the
<span class="command"><strong>grep</strong></span> command to see if our
<span class="quote">bad</span>” file is present in the working directory.
If it is, this revision is bad; if not, this revision is good.
</p><pre id="id395911" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>if grep -q 'i have a gub' *</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>then</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> result=bad</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>else</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> result=good</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>fi</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo this revision is $result</code></strong>
this revision is bad
<code class="prompt">$</code> <strong class="userinput"><code>hg bisect --$result</code></strong>
Testing changeset 16:e61fdddff53e (12 changesets remaining, ~3 tests)
0 files updated, 0 files merged, 6 files removed, 0 files unresolved
</pre><p>
</p><p id="x_146"><a name="x_146"></a>This test looks like a perfect candidate for automation,
so let's turn it into a shell function.</p><pre id="id396435" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest() {</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> if grep -q 'i have a gub' *</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> then</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> result=bad</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> else</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> result=good</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> fi</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> echo this revision is $result</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code> hg bisect --$result</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>}</code></strong>
</pre><p id="x_147"><a name="x_147"></a>We can now run an entire test step with a single command,
<code class="literal">mytest</code>.</p><pre id="id396403" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
this revision is good
Testing changeset 19:706df39b003b (6 changesets remaining, ~2 tests)
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_148"><a name="x_148"></a>A few more invocations of our canned test step command,
and we're done.</p><pre id="id396344" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
this revision is good
Testing changeset 20:bf7ea9a054e6 (3 changesets remaining, ~1 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
this revision is good
Testing changeset 21:921391dd45c1 (2 changesets remaining, ~1 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
this revision is good
The first bad revision is:
changeset: 22:b8789808fc48
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:14 2009 +0000
summary: buggy changeset
</pre><p id="x_149"><a name="x_149"></a>Even though we had 40 changesets to search through, the
<span class="command"><strong>hg bisect</strong></span> command let us find
the changeset that introduced our “<span class="quote">bug</span>” with only
five tests. Because the number of tests that the <span class="command"><strong>hg bisect</strong></span> command performs grows
logarithmically with the number of changesets to search, the
advantage that it has over the “<span class="quote">brute force</span>
search approach increases with every changeset you add.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396541">Cleaning up after your search</h3></div></div></div><p id="x_14a"><a name="x_14a"></a>When you're finished using the <span class="command"><strong>hg
bisect</strong></span> command in a repository, you can use the
<span class="command"><strong>hg bisect --reset</strong></span> command to
drop the information it was using to drive your search. The
command doesn't use much space, so it doesn't matter if you
forget to run this command. However, <span class="command"><strong>hg bisect</strong></span> won't let you start a new
search in that repository until you do a <span class="command"><strong>hg bisect --reset</strong></span>.</p><pre id="id396936" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --reset</code></strong>
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id396622">Tips for finding bugs effectively</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396628">Give consistent input</h3></div></div></div><p id="x_14b"><a name="x_14b"></a>The <span class="command"><strong>hg bisect</strong></span> command
requires that you correctly report the result of every test
you perform. If you tell it that a test failed when it really
succeeded, it <span class="emphasis"><em>might</em></span> be able to detect the
inconsistency. If it can identify an inconsistency in your
reports, it will tell you that a particular changeset is both
good and bad. However, it can't do this perfectly; it's about
as likely to report the wrong changeset as the source of the
bug.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396884">Automate as much as possible</h3></div></div></div><p id="x_14c"><a name="x_14c"></a>When I started using the <span class="command"><strong>hg
bisect</strong></span> command, I tried a few times to run my
tests by hand, on the command line. This is an approach that
I, at least, am not suited to. After a few tries, I found
that I was making enough mistakes that I was having to restart
my searches several times before finally getting correct
results.</p><p id="x_14d"><a name="x_14d"></a>My initial problems with driving the <span class="command"><strong>hg bisect</strong></span> command by hand occurred
even with simple searches on small repositories; if the
problem you're looking for is more subtle, or the number of
tests that <span class="command"><strong>hg bisect</strong></span> must
perform increases, the likelihood of operator error ruining
the search is much higher. Once I started automating my
tests, I had much better results.</p><p id="x_14e"><a name="x_14e"></a>The key to automated testing is twofold:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_14f"><a name="x_14f"></a>always test for the same symptom, and</p></li><li><p id="x_150"><a name="x_150"></a>always feed consistent input to the <span class="command"><strong>hg bisect</strong></span> command.</p></li></ul></div><p id="x_151"><a name="x_151"></a>In my tutorial example above, the <span class="command"><strong>grep</strong></span>
command tests for the symptom, and the <code class="literal">if</code>
statement takes the result of this check and ensures that we
always feed the same input to the <span class="command"><strong>hg
bisect</strong></span> command. The <code class="literal">mytest</code>
function marries these together in a reproducible way, so that
every test is uniform and consistent.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396713">Check your results</h3></div></div></div><p id="x_152"><a name="x_152"></a>Because the output of a <span class="command"><strong>hg
bisect</strong></span> search is only as good as the input you
give it, don't take the changeset it reports as the absolute
truth. A simple way to cross-check its report is to manually
run your test at each of the following changesets:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_153"><a name="x_153"></a>The changeset that it reports as the first bad
revision. Your test should still report this as
bad.</p></li><li><p id="x_154"><a name="x_154"></a>The parent of that changeset (either parent,
if it's a merge). Your test should report this changeset
as good.</p></li><li><p id="x_155"><a name="x_155"></a>A child of that changeset. Your test should
report this changeset as bad.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396770">Beware interference between bugs</h3></div></div></div><p id="x_156"><a name="x_156"></a>It's possible that your search for one bug could be
disrupted by the presence of another. For example, let's say
your software crashes at revision 100, and worked correctly at
revision 50. Unknown to you, someone else introduced a
different crashing bug at revision 60, and fixed it at
revision 80. This could distort your results in one of
several ways.</p><p id="x_157"><a name="x_157"></a>It is possible that this other bug completely
<span class="quote">masks</span>” yours, which is to say that it occurs
before your bug has a chance to manifest itself. If you can't
avoid that other bug (for example, it prevents your project
from building), and so can't tell whether your bug is present
in a particular changeset, the <span class="command"><strong>hg
bisect</strong></span> command cannot help you directly. Instead,
you can mark a changeset as untested by running <span class="command"><strong>hg bisect --skip</strong></span>.</p><p id="x_158"><a name="x_158"></a>A different problem could arise if your test for a bug's
presence is not specific enough. If you check for “<span class="quote">my
program crashes</span>”, then both your crashing bug and an
unrelated crashing bug that masks it will look like the same
thing, and mislead <span class="command"><strong>hg
bisect</strong></span>.</p><p id="x_159"><a name="x_159"></a>Another useful situation in which to use <span class="command"><strong>hg bisect --skip</strong></span> is if you can't
test a revision because your project was in a broken and hence
untestable state at that revision, perhaps because someone
checked in a change that prevented the project from
building.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396856">Bracket your search lazily</h3></div></div></div><p id="x_15a"><a name="x_15a"></a>Choosing the first “<span class="quote">good</span>” and
<span class="quote">bad</span>” changesets that will mark the end points of
your search is often easy, but it bears a little discussion
nevertheless. From the perspective of <span class="command"><strong>hg bisect</strong></span>, the “<span class="quote">newest</span>
changeset is conventionally “<span class="quote">bad</span>”, and the older
changeset is “<span class="quote">good</span>”.</p><p id="x_15b"><a name="x_15b"></a>If you're having trouble remembering when a suitable
<span class="quote">good</span>” change was, so that you can tell <span class="command"><strong>hg bisect</strong></span>, you could do worse than
testing changesets at random. Just remember to eliminate
contenders that can't possibly exhibit the bug (perhaps
because the feature with the bug isn't present yet) and those
where another problem masks the bug (as I discussed
above).</p><p id="x_15c"><a name="x_15c"></a>Even if you end up “<span class="quote">early</span>” by thousands of
changesets or months of history, you will only add a handful
of tests to the total number that <span class="command"><strong>hg
bisect</strong></span> must perform, thanks to its logarithmic
behavior.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="managing-releases-and-branchy-development.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="handling-repository-events-with-hooks.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 8. Managing releases and branchy development </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 10. Handling repository events with hooks</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,462 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 1. How did we get here?</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="preface.html" title="Preface"><link rel="next" href="a-tour-of-mercurial-the-basics.html" title="Chapter 2. A tour of Mercurial: the basics"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 1. How did we get here?</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="a-tour-of-mercurial-the-basics.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:intro"><div class="titlepage"><div><div><h2 class="title">Chapter 1. How did we get here?</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="how-did-we-get-here.html#id342215">Why revision control? Why Mercurial?</a></span></dt><dd><dl><dt><span class="sect2"><a href="how-did-we-get-here.html#id342565">Why use revision control?</a></span></dt><dt><span class="sect2"><a href="how-did-we-get-here.html#id342807">The many names of revision control</a></span></dt></dl></dd><dt><span class="sect1"><a href="how-did-we-get-here.html#id342862">About the examples in this book</a></span></dt><dt><span class="sect1"><a href="how-did-we-get-here.html#id342932">Trends in the field</a></span></dt><dt><span class="sect1"><a href="how-did-we-get-here.html#id342975">A few of the advantages of distributed revision
control</a></span></dt><dd><dl><dt><span class="sect2"><a href="how-did-we-get-here.html#id343018">Advantages for open source projects</a></span></dt><dd><dl><dt><span class="sect3"><a href="how-did-we-get-here.html#id343042">The forking non-problem</a></span></dt></dl></dd><dt><span class="sect2"><a href="how-did-we-get-here.html#id343142">Advantages for commercial projects</a></span></dt></dl></dd><dt><span class="sect1"><a href="how-did-we-get-here.html#id343180">Why choose Mercurial?</a></span></dt><dt><span class="sect1"><a href="how-did-we-get-here.html#id343252">Mercurial compared with other tools</a></span></dt><dd><dl><dt><span class="sect2"><a href="how-did-we-get-here.html#id343265">Subversion</a></span></dt><dt><span class="sect2"><a href="how-did-we-get-here.html#id343368">Git</a></span></dt><dt><span class="sect2"><a href="how-did-we-get-here.html#id343423">CVS</a></span></dt><dt><span class="sect2"><a href="how-did-we-get-here.html#id343482">Commercial tools</a></span></dt><dt><span class="sect2"><a href="how-did-we-get-here.html#id343504">Choosing a revision control tool</a></span></dt></dl></dd><dt><span class="sect1"><a href="how-did-we-get-here.html#id343531">Switching from another tool to Mercurial</a></span></dt><dt><span class="sect1"><a href="how-did-we-get-here.html#id343625">A short history of revision control</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id342215">Why revision control? Why Mercurial?</h2></div></div></div><p id="x_6d"><a name="x_6d"></a>Revision control is the process of managing multiple
versions of a piece of information. In its simplest form, this
is something that many people do by hand: every time you modify
a file, save it under a new name that contains a number, each
one higher than the number of the preceding version.</p><p id="x_6e"><a name="x_6e"></a>Manually managing multiple versions of even a single file is
an error-prone task, though, so software tools to help automate
this process have long been available. The earliest automated
revision control tools were intended to help a single user to
manage revisions of a single file. Over the past few decades,
the scope of revision control tools has expanded greatly; they
now manage multiple files, and help multiple people to work
together. The best modern revision control tools have no
problem coping with thousands of people working together on
projects that consist of hundreds of thousands of files.</p><p id="x_6f"><a name="x_6f"></a>The arrival of distributed revision control is relatively
recent, and so far this new field has grown due to people's
willingness to explore ill-charted territory.</p><p id="x_70"><a name="x_70"></a>I am writing a book about distributed revision control
because I believe that it is an important subject that deserves
a field guide. I chose to write about Mercurial because it is
the easiest tool to learn the terrain with, and yet it scales to
the demands of real, challenging environments where many other
revision control tools buckle.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id342565">Why use revision control?</h3></div></div></div><p id="x_71"><a name="x_71"></a>There are a number of reasons why you or your team might
want to use an automated revision control tool for a
project.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_72"><a name="x_72"></a>It will track the history and evolution of
your project, so you don't have to. For every change,
you'll have a log of <span class="emphasis"><em>who</em></span> made it;
<span class="emphasis"><em>why</em></span> they made it;
<span class="emphasis"><em>when</em></span> they made it; and
<span class="emphasis"><em>what</em></span> the change
was.</p></li><li><p id="x_73"><a name="x_73"></a>When you're working with other people,
revision control software makes it easier for you to
collaborate. For example, when people more or less
simultaneously make potentially incompatible changes, the
software will help you to identify and resolve those
conflicts.</p></li><li><p id="x_74"><a name="x_74"></a>It can help you to recover from mistakes. If
you make a change that later turns out to be in error, you
can revert to an earlier version of one or more files. In
fact, a <span class="emphasis"><em>really</em></span> good revision control
tool will even help you to efficiently figure out exactly
when a problem was introduced (see <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:bisect" title="Finding the source of a bug">the section called “Finding the source of a bug”</a> for details).</p></li><li><p id="x_75"><a name="x_75"></a>It will help you to work simultaneously on,
and manage the drift between, multiple versions of your
project.</p></li></ul></div><p id="x_76"><a name="x_76"></a>Most of these reasons are equally
valid—at least in theory—whether you're working
on a project by yourself, or with a hundred other
people.</p><p id="x_77"><a name="x_77"></a>A key question about the practicality of revision control
at these two different scales (“<span class="quote">lone hacker</span>” and
<span class="quote">huge team</span>”) is how its
<span class="emphasis"><em>benefits</em></span> compare to its
<span class="emphasis"><em>costs</em></span>. A revision control tool that's
difficult to understand or use is going to impose a high
cost.</p><p id="x_78"><a name="x_78"></a>A five-hundred-person project is likely to collapse under
its own weight almost immediately without a revision control
tool and process. In this case, the cost of using revision
control might hardly seem worth considering, since
<span class="emphasis"><em>without</em></span> it, failure is almost
guaranteed.</p><p id="x_79"><a name="x_79"></a>On the other hand, a one-person “<span class="quote">quick hack</span>
might seem like a poor place to use a revision control tool,
because surely the cost of using one must be close to the
overall cost of the project. Right?</p><p id="x_7a"><a name="x_7a"></a>Mercurial uniquely supports <span class="emphasis"><em>both</em></span> of
these scales of development. You can learn the basics in just
a few minutes, and due to its low overhead, you can apply
revision control to the smallest of projects with ease. Its
simplicity means you won't have a lot of abstruse concepts or
command sequences competing for mental space with whatever
you're <span class="emphasis"><em>really</em></span> trying to do. At the same
time, Mercurial's high performance and peer-to-peer nature let
you scale painlessly to handle large projects.</p><p id="x_7b"><a name="x_7b"></a>No revision control tool can rescue a poorly run project,
but a good choice of tools can make a huge difference to the
fluidity with which you can work on a project.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id342807">The many names of revision control</h3></div></div></div><p id="x_7c"><a name="x_7c"></a>Revision control is a diverse field, so much so that it is
referred to by many names and acronyms. Here are a few of the
more common variations you'll encounter:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_7d"><a name="x_7d"></a>Revision control (RCS)</p></li><li><p id="x_7e"><a name="x_7e"></a>Software configuration management (SCM), or
configuration management</p></li><li><p id="x_7f"><a name="x_7f"></a>Source code management</p></li><li><p id="x_80"><a name="x_80"></a>Source code control, or source
control</p></li><li><p id="x_81"><a name="x_81"></a>Version control
(VCS)</p></li></ul></div><p id="x_82"><a name="x_82"></a>Some people claim that these terms actually have different
meanings, but in practice they overlap so much that there's no
agreed or even useful way to tease them apart.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id342862">About the examples in this book</h2></div></div></div><p id="x_84"><a name="x_84"></a>This book takes an unusual approach to code samples. Every
example is “<span class="quote">live</span>”—each one is actually the result
of a shell script that executes the Mercurial commands you see.
Every time an image of the book is built from its sources, all
the example scripts are automatically run, and their current
results compared against their expected results.</p><p id="x_85"><a name="x_85"></a>The advantage of this approach is that the examples are
always accurate; they describe <span class="emphasis"><em>exactly</em></span> the
behavior of the version of Mercurial that's mentioned at the
front of the book. If I update the version of Mercurial that
I'm documenting, and the output of some command changes, the
build fails.</p><p id="x_86"><a name="x_86"></a>There is a small disadvantage to this approach, which is
that the dates and times you'll see in examples tend to be
<span class="quote">squashed</span>” together in a way that they wouldn't be
if the same commands were being typed by a human. Where a human
can issue no more than one command every few seconds, with any
resulting timestamps correspondingly spread out, my automated
example scripts run many commands in one second.</p><p id="x_87"><a name="x_87"></a>As an instance of this, several consecutive commits in an
example can show up as having occurred during the same second.
You can see this occur in the <code class="literal">bisect</code> example in <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:bisect" title="Finding the source of a bug">the section called “Finding the source of a bug”</a>, for instance.</p><p id="x_88"><a name="x_88"></a>So when you're reading examples, don't place too much weight
on the dates or times you see in the output of commands. But
<span class="emphasis"><em>do</em></span> be confident that the behavior you're
seeing is consistent and reproducible.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id342932">Trends in the field</h2></div></div></div><p id="x_89"><a name="x_89"></a>There has been an unmistakable trend in the development and
use of revision control tools over the past four decades, as
people have become familiar with the capabilities of their tools
and constrained by their limitations.</p><p id="x_8a"><a name="x_8a"></a>The first generation began by managing single files on
individual computers. Although these tools represented a huge
advance over ad-hoc manual revision control, their locking model
and reliance on a single computer limited them to small,
tightly-knit teams.</p><p id="x_8b"><a name="x_8b"></a>The second generation loosened these constraints by moving
to network-centered architectures, and managing entire projects
at a time. As projects grew larger, they ran into new problems.
With clients needing to talk to servers very frequently, server
scaling became an issue for large projects. An unreliable
network connection could prevent remote users from being able to
talk to the server at all. As open source projects started
making read-only access available anonymously to anyone, people
without commit privileges found that they could not use the
tools to interact with a project in a natural way, as they could
not record their changes.</p><p id="x_8c"><a name="x_8c"></a>The current generation of revision control tools is
peer-to-peer in nature. All of these systems have dropped the
dependency on a single central server, and allow people to
distribute their revision control data to where it's actually
needed. Collaboration over the Internet has moved from
constrained by technology to a matter of choice and consensus.
Modern tools can operate offline indefinitely and autonomously,
with a network connection only needed when syncing changes with
another repository.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id342975">A few of the advantages of distributed revision
control</h2></div></div></div><p id="x_8d"><a name="x_8d"></a>Even though distributed revision control tools have for
several years been as robust and usable as their
previous-generation counterparts, people using older tools have
not yet necessarily woken up to their advantages. There are a
number of ways in which distributed tools shine relative to
centralised ones.</p><p id="x_8e"><a name="x_8e"></a>For an individual developer, distributed tools are almost
always much faster than centralised tools. This is for a simple
reason: a centralised tool needs to talk over the network for
many common operations, because most metadata is stored in a
single copy on the central server. A distributed tool stores
all of its metadata locally. All else being equal, talking over
the network adds overhead to a centralised tool. Don't
underestimate the value of a snappy, responsive tool: you're
going to spend a lot of time interacting with your revision
control software.</p><p id="x_8f"><a name="x_8f"></a>Distributed tools are indifferent to the vagaries of your
server infrastructure, again because they replicate metadata to
so many locations. If you use a centralised system and your
server catches fire, you'd better hope that your backup media
are reliable, and that your last backup was recent and actually
worked. With a distributed tool, you have many backups
available on every contributor's computer.</p><p id="x_90"><a name="x_90"></a>The reliability of your network will affect distributed
tools far less than it will centralised tools. You can't even
use a centralised tool without a network connection, except for
a few highly constrained commands. With a distributed tool, if
your network connection goes down while you're working, you may
not even notice. The only thing you won't be able to do is talk
to repositories on other computers, something that is relatively
rare compared with local operations. If you have a far-flung
team of collaborators, this may be significant.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343018">Advantages for open source projects</h3></div></div></div><p id="x_91"><a name="x_91"></a>If you take a shine to an open source project and decide
that you would like to start hacking on it, and that project
uses a distributed revision control tool, you are at once a
peer with the people who consider themselves the
<span class="quote">core</span>” of that project. If they publish their
repositories, you can immediately copy their project history,
start making changes, and record your work, using the same
tools in the same ways as insiders. By contrast, with a
centralised tool, you must use the software in a “<span class="quote">read
only</span>” mode unless someone grants you permission to
commit changes to their central server. Until then, you won't
be able to record changes, and your local modifications will
be at risk of corruption any time you try to update your
client's view of the repository.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id343042">The forking non-problem</h4></div></div></div><p id="x_92"><a name="x_92"></a>It has been suggested that distributed revision control
tools pose some sort of risk to open source projects because
they make it easy to “<span class="quote">fork</span>” the development of
a project. A fork happens when there are differences in
opinion or attitude between groups of developers that cause
them to decide that they can't work together any longer.
Each side takes a more or less complete copy of the
project's source code, and goes off in its own
direction.</p><p id="x_93"><a name="x_93"></a>Sometimes the camps in a fork decide to reconcile their
differences. With a centralised revision control system, the
<span class="emphasis"><em>technical</em></span> process of reconciliation is
painful, and has to be performed largely by hand. You have
to decide whose revision history is going to
<span class="quote">win</span>”, and graft the other team's changes into
the tree somehow. This usually loses some or all of one
side's revision history.</p><p id="x_94"><a name="x_94"></a>What distributed tools do with respect to forking is
they make forking the <span class="emphasis"><em>only</em></span> way to
develop a project. Every single change that you make is
potentially a fork point. The great strength of this
approach is that a distributed revision control tool has to
be really good at <span class="emphasis"><em>merging</em></span> forks,
because forks are absolutely fundamental: they happen all
the time.</p><p id="x_95"><a name="x_95"></a>If every piece of work that everybody does, all the
time, is framed in terms of forking and merging, then what
the open source world refers to as a “<span class="quote">fork</span>
becomes <span class="emphasis"><em>purely</em></span> a social issue. If
anything, distributed tools <span class="emphasis"><em>lower</em></span> the
likelihood of a fork:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_96"><a name="x_96"></a>They eliminate the social distinction that
centralised tools impose: that between insiders (people
with commit access) and outsiders (people
without).</p></li><li><p id="x_97"><a name="x_97"></a>They make it easier to reconcile after a
social fork, because all that's involved from the
perspective of the revision control software is just
another merge.</p></li></ul></div><p id="x_98"><a name="x_98"></a>Some people resist distributed tools because they want
to retain tight control over their projects, and they
believe that centralised tools give them this control.
However, if you're of this belief, and you publish your CVS
or Subversion repositories publicly, there are plenty of
tools available that can pull out your entire project's
history (albeit slowly) and recreate it somewhere that you
don't control. So while your control in this case is
illusory, you are forgoing the ability to fluidly
collaborate with whatever people feel compelled to mirror
and fork your history.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343142">Advantages for commercial projects</h3></div></div></div><p id="x_99"><a name="x_99"></a>Many commercial projects are undertaken by teams that are
scattered across the globe. Contributors who are far from a
central server will see slower command execution and perhaps
less reliability. Commercial revision control systems attempt
to ameliorate these problems with remote-site replication
add-ons that are typically expensive to buy and cantankerous
to administer. A distributed system doesn't suffer from these
problems in the first place. Better yet, you can easily set
up multiple authoritative servers, say one per site, so that
there's no redundant communication between repositories over
expensive long-haul network links.</p><p id="x_9a"><a name="x_9a"></a>Centralised revision control systems tend to have
relatively low scalability. It's not unusual for an expensive
centralised system to fall over under the combined load of
just a few dozen concurrent users. Once again, the typical
response tends to be an expensive and clunky replication
facility. Since the load on a central server—if you have
one at all—is many times lower with a distributed tool
(because all of the data is replicated everywhere), a single
cheap server can handle the needs of a much larger team, and
replication to balance load becomes a simple matter of
scripting.</p><p id="x_9b"><a name="x_9b"></a>If you have an employee in the field, troubleshooting a
problem at a customer's site, they'll benefit from distributed
revision control. The tool will let them generate custom
builds, try different fixes in isolation from each other, and
search efficiently through history for the sources of bugs and
regressions in the customer's environment, all without needing
to connect to your company's network.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id343180">Why choose Mercurial?</h2></div></div></div><p id="x_9c"><a name="x_9c"></a>Mercurial has a unique set of properties that make it a
particularly good choice as a revision control system.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_9d"><a name="x_9d"></a>It is easy to learn and use.</p></li><li><p id="x_9e"><a name="x_9e"></a>It is lightweight.</p></li><li><p id="x_9f"><a name="x_9f"></a>It scales excellently.</p></li><li><p id="x_a0"><a name="x_a0"></a>It is easy to
customise.</p></li></ul></div><p id="x_a1"><a name="x_a1"></a>If you are at all familiar with revision control systems,
you should be able to get up and running with Mercurial in less
than five minutes. Even if not, it will take no more than a few
minutes longer. Mercurial's command and feature sets are
generally uniform and consistent, so you can keep track of a few
general rules instead of a host of exceptions.</p><p id="x_a2"><a name="x_a2"></a>On a small project, you can start working with Mercurial in
moments. Creating new changes and branches; transferring changes
around (whether locally or over a network); and history and
status operations are all fast. Mercurial attempts to stay
nimble and largely out of your way by combining low cognitive
overhead with blazingly fast operations.</p><p id="x_a3"><a name="x_a3"></a>The usefulness of Mercurial is not limited to small
projects: it is used by projects with hundreds to thousands of
contributors, each containing tens of thousands of files and
hundreds of megabytes of source code.</p><p id="x_a4"><a name="x_a4"></a>If the core functionality of Mercurial is not enough for
you, it's easy to build on. Mercurial is well suited to
scripting tasks, and its clean internals and implementation in
Python make it easy to add features in the form of extensions.
There are a number of popular and useful extensions already
available, ranging from helping to identify bugs to improving
performance.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id343252">Mercurial compared with other tools</h2></div></div></div><p id="x_a5"><a name="x_a5"></a>Before you read on, please understand that this section
necessarily reflects my own experiences, interests, and (dare I
say it) biases. I have used every one of the revision control
tools listed below, in most cases for several years at a
time.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343265">Subversion</h3></div></div></div><p id="x_a6"><a name="x_a6"></a>Subversion is a popular revision control tool, developed
to replace CVS. It has a centralised client/server
architecture.</p><p id="x_a7"><a name="x_a7"></a>Subversion and Mercurial have similarly named commands for
performing the same operations, so if you're familiar with
one, it is easy to learn to use the other. Both tools are
portable to all popular operating systems.</p><p id="x_a8"><a name="x_a8"></a>Prior to version 1.5, Subversion had no useful support for
merges. At the time of writing, its merge tracking capability
is new, and known to be <a class="ulink" href="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword" target="_top">complicated
and buggy</a>.</p><p id="x_a9"><a name="x_a9"></a>Mercurial has a substantial performance advantage over
Subversion on every revision control operation I have
benchmarked. I have measured its advantage as ranging from a
factor of two to a factor of six when compared with Subversion
1.4.3's <span class="emphasis"><em>ra_local</em></span> file store, which is the
fastest access method available. In more realistic
deployments involving a network-based store, Subversion will
be at a substantially larger disadvantage. Because many
Subversion commands must talk to the server and Subversion
does not have useful replication facilities, server capacity
and network bandwidth become bottlenecks for modestly large
projects.</p><p id="x_aa"><a name="x_aa"></a>Additionally, Subversion incurs substantial storage
overhead to avoid network transactions for a few common
operations, such as finding modified files
(<code class="literal">status</code>) and displaying modifications
against the current revision (<code class="literal">diff</code>). As a
result, a Subversion working copy is often the same size as,
or larger than, a Mercurial repository and working directory,
even though the Mercurial repository contains a complete
history of the project.</p><p id="x_ab"><a name="x_ab"></a>Subversion is widely supported by third party tools.
Mercurial currently lags considerably in this area. This gap
is closing, however, and indeed some of Mercurial's GUI tools
now outshine their Subversion equivalents. Like Mercurial,
Subversion has an excellent user manual.</p><p id="x_ac"><a name="x_ac"></a>Because Subversion doesn't store revision history on the
client, it is well suited to managing projects that deal with
lots of large, opaque binary files. If you check in fifty
revisions to an incompressible 10MB file, Subversion's
client-side space usage stays constant The space used by any
distributed SCM will grow rapidly in proportion to the number
of revisions, because the differences between each revision
are large.</p><p id="x_ad"><a name="x_ad"></a>In addition, it's often difficult or, more usually,
impossible to merge different versions of a binary file.
Subversion's ability to let a user lock a file, so that they
temporarily have the exclusive right to commit changes to it,
can be a significant advantage to a project where binary files
are widely used.</p><p id="x_ae"><a name="x_ae"></a>Mercurial can import revision history from a Subversion
repository. It can also export revision history to a
Subversion repository. This makes it easy to “<span class="quote">test the
waters</span>” and use Mercurial and Subversion in parallel
before deciding to switch. History conversion is incremental,
so you can perform an initial conversion, then small
additional conversions afterwards to bring in new
changes.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343368">Git</h3></div></div></div><p id="x_af"><a name="x_af"></a>Git is a distributed revision control tool that was
developed for managing the Linux kernel source tree. Like
Mercurial, its early design was somewhat influenced by
Monotone.</p><p id="x_b0"><a name="x_b0"></a>Git has a very large command set, with version 1.5.0
providing 139 individual commands. It has something of a
reputation for being difficult to learn. Compared to Git,
Mercurial has a strong focus on simplicity.</p><p id="x_b1"><a name="x_b1"></a>In terms of performance, Git is extremely fast. In
several cases, it is faster than Mercurial, at least on Linux,
while Mercurial performs better on other operations. However,
on Windows, the performance and general level of support that
Git provides is, at the time of writing, far behind that of
Mercurial.</p><p id="x_b2"><a name="x_b2"></a>While a Mercurial repository needs no maintenance, a Git
repository requires frequent manual “<span class="quote">repacks</span>” of
its metadata. Without these, performance degrades, while
space usage grows rapidly. A server that contains many Git
repositories that are not rigorously and frequently repacked
will become heavily disk-bound during backups, and there have
been instances of daily backups taking far longer than 24
hours as a result. A freshly packed Git repository is
slightly smaller than a Mercurial repository, but an unpacked
repository is several orders of magnitude larger.</p><p id="x_b3"><a name="x_b3"></a>The core of Git is written in C. Many Git commands are
implemented as shell or Perl scripts, and the quality of these
scripts varies widely. I have encountered several instances
where scripts charged along blindly in the presence of errors
that should have been fatal.</p><p id="x_b4"><a name="x_b4"></a>Mercurial can import revision history from a Git
repository.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343423">CVS</h3></div></div></div><p id="x_b5"><a name="x_b5"></a>CVS is probably the most widely used revision control tool
in the world. Due to its age and internal untidiness, it has
been only lightly maintained for many years.</p><p id="x_b6"><a name="x_b6"></a>It has a centralised client/server architecture. It does
not group related file changes into atomic commits, making it
easy for people to “<span class="quote">break the build</span>”: one person
can successfully commit part of a change and then be blocked
by the need for a merge, causing other people to see only a
portion of the work they intended to do. This also affects
how you work with project history. If you want to see all of
the modifications someone made as part of a task, you will
need to manually inspect the descriptions and timestamps of
the changes made to each file involved (if you even know what
those files were).</p><p id="x_b7"><a name="x_b7"></a>CVS has a muddled notion of tags and branches that I will
not attempt to even describe. It does not support renaming of
files or directories well, making it easy to corrupt a
repository. It has almost no internal consistency checking
capabilities, so it is usually not even possible to tell
whether or how a repository is corrupt. I would not recommend
CVS for any project, existing or new.</p><p id="x_b8"><a name="x_b8"></a>Mercurial can import CVS revision history. However, there
are a few caveats that apply; these are true of every other
revision control tool's CVS importer, too. Due to CVS's lack
of atomic changes and unversioned filesystem hierarchy, it is
not possible to reconstruct CVS history completely accurately;
some guesswork is involved, and renames will usually not show
up. Because a lot of advanced CVS administration has to be
done by hand and is hence error-prone, it's common for CVS
importers to run into multiple problems with corrupted
repositories (completely bogus revision timestamps and files
that have remained locked for over a decade are just two of
the less interesting problems I can recall from personal
experience).</p><p id="x_b9"><a name="x_b9"></a>Mercurial can import revision history from a CVS
repository.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343482">Commercial tools</h3></div></div></div><p id="x_ba"><a name="x_ba"></a>Perforce has a centralised client/server architecture,
with no client-side caching of any data. Unlike modern
revision control tools, Perforce requires that a user run a
command to inform the server about every file they intend to
edit.</p><p id="x_bb"><a name="x_bb"></a>The performance of Perforce is quite good for small teams,
but it falls off rapidly as the number of users grows beyond a
few dozen. Modestly large Perforce installations require the
deployment of proxies to cope with the load their users
generate.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id343504">Choosing a revision control tool</h3></div></div></div><p id="x_bc"><a name="x_bc"></a>With the exception of CVS, all of the tools listed above
have unique strengths that suit them to particular styles of
work. There is no single revision control tool that is best
in all situations.</p><p id="x_bd"><a name="x_bd"></a>As an example, Subversion is a good choice for working
with frequently edited binary files, due to its centralised
nature and support for file locking.</p><p id="x_be"><a name="x_be"></a>I personally find Mercurial's properties of simplicity,
performance, and good merge support to be a compelling
combination that has served me well for several years.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id343531">Switching from another tool to Mercurial</h2></div></div></div><p id="x_bf"><a name="x_bf"></a>Mercurial is bundled with an extension named <code class="literal">convert</code>, which can incrementally
import revision history from several other revision control
tools. By “<span class="quote">incremental</span>”, I mean that you can
convert all of a project's history to date in one go, then rerun
the conversion later to obtain new changes that happened after
the initial conversion.</p><p id="x_c0"><a name="x_c0"></a>The revision control tools supported by <code class="literal">convert</code> are as follows:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_c1"><a name="x_c1"></a>Subversion</p></li><li><p id="x_c2"><a name="x_c2"></a>CVS</p></li><li><p id="x_c3"><a name="x_c3"></a>Git</p></li><li><p id="x_c4"><a name="x_c4"></a>Darcs</p></li></ul></div><p id="x_c5"><a name="x_c5"></a>In addition, <code class="literal">convert</code> can
export changes from Mercurial to Subversion. This makes it
possible to try Subversion and Mercurial in parallel before
committing to a switchover, without risking the loss of any
work.</p><p id="x_c6"><a name="x_c6"></a>The <span class="command"><strong>convert</strong></span> command
is easy to use. Simply point it at the path or URL of the
source repository, optionally give it the name of the
destination repository, and it will start working. After the
initial conversion, just run the same command again to import
new changes.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id343625">A short history of revision control</h2></div></div></div><p id="x_c7"><a name="x_c7"></a>The best known of the old-time revision control tools is
SCCS (Source Code Control System), which Marc Rochkind wrote at
Bell Labs, in the early 1970s. SCCS operated on individual
files, and required every person working on a project to have
access to a shared workspace on a single system. Only one
person could modify a file at any time; arbitration for access
to files was via locks. It was common for people to lock files,
and later forget to unlock them, preventing anyone else from
modifying those files without the help of an
administrator.</p><p id="x_c8"><a name="x_c8"></a>Walter Tichy developed a free alternative to SCCS in the
early 1980s; he called his program RCS (Revision Control System).
Like SCCS, RCS required developers to work in a single shared
workspace, and to lock files to prevent multiple people from
modifying them simultaneously.</p><p id="x_c9"><a name="x_c9"></a>Later in the 1980s, Dick Grune used RCS as a building block
for a set of shell scripts he initially called cmt, but then
renamed to CVS (Concurrent Versions System). The big innovation
of CVS was that it let developers work simultaneously and
somewhat independently in their own personal workspaces. The
personal workspaces prevented developers from stepping on each
other's toes all the time, as was common with SCCS and RCS. Each
developer had a copy of every project file, and could modify
their copies independently. They had to merge their edits prior
to committing changes to the central repository.</p><p id="x_ca"><a name="x_ca"></a>Brian Berliner took Grune's original scripts and rewrote
them in C, releasing in 1989 the code that has since developed
into the modern version of CVS. CVS subsequently acquired the
ability to operate over a network connection, giving it a
client/server architecture. CVS's architecture is centralised;
only the server has a copy of the history of the project. Client
workspaces just contain copies of recent versions of the
project's files, and a little metadata to tell them where the
server is. CVS has been enormously successful; it is probably
the world's most widely used revision control system.</p><p id="x_cb"><a name="x_cb"></a>In the early 1990s, Sun Microsystems developed an early
distributed revision control system, called TeamWare. A
TeamWare workspace contains a complete copy of the project's
history. TeamWare has no notion of a central repository. (CVS
relied upon RCS for its history storage; TeamWare used
SCCS.)</p><p id="x_cc"><a name="x_cc"></a>As the 1990s progressed, awareness grew of a number of
problems with CVS. It records simultaneous changes to multiple
files individually, instead of grouping them together as a
single logically atomic operation. It does not manage its file
hierarchy well; it is easy to make a mess of a repository by
renaming files and directories. Worse, its source code is
difficult to read and maintain, which made the “<span class="quote">pain
level</span>” of fixing these architectural problems
prohibitive.</p><p id="x_cd"><a name="x_cd"></a>In 2001, Jim Blandy and Karl Fogel, two developers who had
worked on CVS, started a project to replace it with a tool that
would have a better architecture and cleaner code. The result,
Subversion, does not stray from CVS's centralised client/server
model, but it adds multi-file atomic commits, better namespace
management, and a number of other features that make it a
generally better tool than CVS. Since its initial release, it
has rapidly grown in popularity.</p><p id="x_ce"><a name="x_ce"></a>More or less simultaneously, Graydon Hoare began working on
an ambitious distributed revision control system that he named
Monotone. While Monotone addresses many of CVS's design flaws
and has a peer-to-peer architecture, it goes beyond earlier (and
subsequent) revision control tools in a number of innovative
ways. It uses cryptographic hashes as identifiers, and has an
integral notion of “<span class="quote">trust</span>” for code from different
sources.</p><p id="x_cf"><a name="x_cf"></a>Mercurial began life in 2005. While a few aspects of its
design are influenced by Monotone, Mercurial focuses on ease of
use, high performance, and scalability to very large
projects.</p></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="a-tour-of-mercurial-the-basics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Preface </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. A tour of Mercurial: the basics</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

61
read/index.html Normal file
View File

@ -0,0 +1,61 @@
<!-- -*- html -*- -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Mercurial: The Definitive Guide</title>
<link rel="stylesheet" href="/support/styles.css" type="text/css"/>
<link rel="alternate" type="application/atom+xml" title="Comments"
href="/feeds/comments/"/>
<link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"/>
<script type="text/javascript" src="/support/jquery.js"></script>
<script type="text/javascript" src="/support/form.js"></script>
<script type="text/javascript" src="/support/hsbook.js"></script>
</head>
<body>
<div class="navheader"><h1 class="booktitle">Mercurial: The Definitive Guide<div class="authors">by Bryan O'Sullivan</div></h1></div>
<div class="book"><ul class="booktoc">
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:preface/"><img src="/support/figs/rss.png"/></a></span>0. <a href="preface.html">Preface</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:intro/"><img src="/support/figs/rss.png"/></a></span>1. <a href="how-did-we-get-here.html">How did we get here?</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:tour-basic/"><img src="/support/figs/rss.png"/></a></span>2. <a href="a-tour-of-mercurial-the-basics.html">A tour of Mercurial: the basics</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:tour-merge/"><img src="/support/figs/rss.png"/></a></span>3. <a href="a-tour-of-mercurial-merging-work.html">A tour of Mercurial: merging work</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:concepts/"><img src="/support/figs/rss.png"/></a></span>4. <a href="behind-the-scenes.html">Behind the scenes</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:daily/"><img src="/support/figs/rss.png"/></a></span>5. <a href="mercurial-in-daily-use.html">Mercurial in daily use</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/cha:collab/"><img src="/support/figs/rss.png"/></a></span>6. <a href="collaborating-with-other-people.html">Collaborating with other people</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:names/"><img src="/support/figs/rss.png"/></a></span>7. <a href="file-names-and-pattern-matching.html">File names and pattern matching</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:branch/"><img src="/support/figs/rss.png"/></a></span>8. <a href="managing-releases-and-branchy-development.html">Managing releases and branchy development</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:undo/"><img src="/support/figs/rss.png"/></a></span>9. <a href="finding-and-fixing-mistakes.html">Finding and fixing mistakes</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:hook/"><img src="/support/figs/rss.png"/></a></span>10. <a href="handling-repository-events-with-hooks.html">Handling repository events with hooks</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:template/"><img src="/support/figs/rss.png"/></a></span>11. <a href="customizing-the-output-of-mercurial.html">Customizing the output of Mercurial</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:mq/"><img src="/support/figs/rss.png"/></a></span>12. <a href="managing-change-with-mercurial-queues.html">Managing change with Mercurial Queues</a></li>
<li class="zebra_a"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:mq-collab/"><img src="/support/figs/rss.png"/></a></span>13. <a href="advanced-uses-of-mercurial-queues.html">Advanced uses of Mercurial Queues</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-07<a href="/feeds/comments/chap:hgext/"><img src="/support/figs/rss.png"/></a></span>14. <a href="adding-functionality-with-extensions.html">Adding functionality with extensions</a></li>
<li class="zebra_a"><span class="chapinfo">2009-04-28<a href="/feeds/comments/svn/"><img src="/support/figs/rss.png"/></a></span>A. <a href="migrating-to-mercurial.html">Migrating to Mercurial</a></li>
<li class="zebra_b"><span class="chapinfo">2009-05-04<a href="/feeds/comments/chap:mqref/"><img src="/support/figs/rss.png"/></a></span>B. <a href="mercurial-queues-reference.html">Mercurial Queues reference</a></li>
<li class="zebra_a"><span class="chapinfo">2009-03-30<a href="/feeds/comments/chap:srcinstall/"><img src="/support/figs/rss.png"/></a></span>C. <a href="installing-mercurial-from-source.html">Installing Mercurial from source</a></li>
<li class="zebra_b"><span class="chapinfo">2009-03-30<a href="/feeds/comments/cha:opl/"><img src="/support/figs/rss.png"/></a></span>D. <a href="open-publication-license.html">Open Publication License</a></li>
</ul></div>
<div class="hgbookfooter"> <p><img src="/support/figs/rss.png"> Want to stay
up to date? Subscribe to comment feeds for any chapter, or
the <a class="feed"
href="/feeds/comments/">entire book</a>.</p> <p>Copyright
2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by
<a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a
href="http://mattahan.deviantart.com/">Mattahan</a>.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -0,0 +1,33 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Appendix C. Installing Mercurial from source</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="mercurial-queues-reference.html" title="Appendix B. Mercurial Queues reference"><link rel="next" href="open-publication-license.html" title="Appendix D. Open Publication License"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix C. Installing Mercurial from source</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="mercurial-queues-reference.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="open-publication-license.html">Next</a></td></tr></table></div><div class="appendix" lang="en" id="chap:srcinstall"><div class="titlepage"><div><div><h2 class="title">Appendix C. Installing Mercurial from source</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="installing-mercurial-from-source.html#sec:srcinstall:unixlike">On a Unix-like system</a></span></dt><dt><span class="sect1"><a href="installing-mercurial-from-source.html#id448555">On Windows</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:srcinstall:unixlike">On a Unix-like system</h2></div></div></div><p id="x_5e0"><a name="x_5e0"></a>If you are using a Unix-like system that has a sufficiently
recent version of Python (2.3 or newer) available, it is easy to
install Mercurial from source.</p><div class="orderedlist"><ol type="1"><li><p id="x_5e1"><a name="x_5e1"></a>Download a recent source tarball from <a class="ulink" href="http://www.selenic.com/mercurial/download" target="_top">http://www.selenic.com/mercurial/download</a>.</p></li><li><p id="x_5e2"><a name="x_5e2"></a>Unpack the tarball:</p><pre id="id448490" class="programlisting">gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</pre></li><li><p id="x_5e3"><a name="x_5e3"></a>Go into the source directory and run the
installer script. This will build Mercurial and install it
in your home directory.</p><pre id="id448506" class="programlisting">cd mercurial-MYVERSION
python setup.py install --force --home=$HOME</pre></li></ol></div><p id="x_5e4"><a name="x_5e4"></a>Once the install finishes, Mercurial will be in the
<code class="literal">bin</code> subdirectory of your home directory.
Don't forget to make sure that this directory is present in your
shell's search path.</p><p id="x_5e5"><a name="x_5e5"></a>You will probably need to set the <code class="envar">PYTHONPATH</code>
environment variable so that the Mercurial executable can find
the rest of the Mercurial packages. For example, on my laptop,
I have set it to <code class="literal">/home/bos/lib/python</code>. The
exact path that you will need to use depends on how Python was
built for your system, but should be easy to figure out. If
you're uncertain, look through the output of the installer
script above, and see where the contents of the
<code class="literal">mercurial</code> directory were installed to.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id448555">On Windows</h2></div></div></div><p id="x_5e6"><a name="x_5e6"></a>Building and installing Mercurial on Windows requires a
variety of tools, a fair amount of technical knowledge, and
considerable patience. I very much <span class="emphasis"><em>do not
recommend</em></span> this route if you are a “<span class="quote">casual
user</span>”. Unless you intend to hack on Mercurial, I
strongly suggest that you use a binary package instead.</p><p id="x_5e7"><a name="x_5e7"></a>If you are intent on building Mercurial from source on
Windows, follow the “<span class="quote">hard way</span>” directions on the
Mercurial wiki at <a class="ulink" href="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall" target="_top">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</a>,
and expect the process to involve a lot of fiddly work.</p></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="mercurial-queues-reference.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="open-publication-license.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Appendix B. Mercurial Queues reference </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix D. Open Publication License</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,517 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 8. Managing releases and branchy development</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="file-names-and-pattern-matching.html" title="Chapter 7. File names and pattern matching"><link rel="next" href="finding-and-fixing-mistakes.html" title="Chapter 9. Finding and fixing mistakes"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 8. Managing releases and branchy development</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="file-names-and-pattern-matching.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="finding-and-fixing-mistakes.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:branch"><div class="titlepage"><div><div><h2 class="title">Chapter 8. Managing releases and branchy development</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id383990">Giving a persistent name to a revision</a></span></dt><dd><dl><dt><span class="sect2"><a href="managing-releases-and-branchy-development.html#id384894">Handling tag conflicts during a merge</a></span></dt><dt><span class="sect2"><a href="managing-releases-and-branchy-development.html#id385011">Tags and cloning</a></span></dt><dt><span class="sect2"><a href="managing-releases-and-branchy-development.html#id385111">When permanent tags are too much</a></span></dt></dl></dd><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id385202">The flow of changes—big picture vs. little</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id385287">Managing big-picture branches in repositories</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id385475">Don't repeat yourself: merging across branches</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id386031">Naming branches within one repository</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id386726">Dealing with multiple named branches in a
repository</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id387231">Branch names and merging</a></span></dt><dt><span class="sect1"><a href="managing-releases-and-branchy-development.html#id387616">Branch naming is generally useful</a></span></dt></dl></div><p id="x_369"><a name="x_369"></a>Mercurial provides several mechanisms for you to manage a
project that is making progress on multiple fronts at once. To
understand these mechanisms, let's first take a brief look at a
fairly normal software project structure.</p><p id="x_36a"><a name="x_36a"></a>Many software projects issue periodic “<span class="quote">major</span>
releases that contain substantial new features. In parallel, they
may issue “<span class="quote">minor</span>” releases. These are usually
identical to the major releases off which they're based, but with
a few bugs fixed.</p><p id="x_36b"><a name="x_36b"></a>In this chapter, we'll start by talking about how to keep
records of project milestones such as releases. We'll then
continue on to talk about the flow of work between different
phases of a project, and how Mercurial can help you to isolate and
manage this work.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id383990">Giving a persistent name to a revision</h2></div></div></div><p id="x_36c"><a name="x_36c"></a>Once you decide that you'd like to call a particular
revision a “<span class="quote">release</span>”, it's a good idea to record
the identity of that revision. This will let you reproduce that
release at a later date, for whatever purpose you might need at
the time (reproducing a bug, porting to a new platform, etc).
</p><pre id="id384355" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init mytag</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd mytag</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo hello &gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'Initial commit'</code></strong>
adding myfile
</pre><p>
</p><p id="x_36d"><a name="x_36d"></a>Mercurial lets you give a permanent name to any revision
using the <span class="command"><strong>hg tag</strong></span> command. Not
surprisingly, these names are called “<span class="quote">tags</span>”.</p><pre id="id384242" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tag v1.0</code></strong>
</pre><p id="x_36e"><a name="x_36e"></a>A tag is nothing more than a “<span class="quote">symbolic name</span>
for a revision. Tags exist purely for your convenience, so that
you have a handy permanent way to refer to a revision; Mercurial
doesn't interpret the tag names you use in any way. Neither
does Mercurial place any restrictions on the name of a tag,
beyond a few that are necessary to ensure that a tag can be
parsed unambiguously. A tag name cannot contain any of the
following characters:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_36f"><a name="x_36f"></a>Colon (ASCII 58,
<span class="quote"><code class="literal">:</code></span>”)</p></li><li><p id="x_370"><a name="x_370"></a>Carriage return (ASCII 13,
<span class="quote"><code class="literal">\r</code></span>”)</p></li><li><p id="x_371"><a name="x_371"></a>Newline (ASCII 10,
<span class="quote"><code class="literal">\n</code></span>”)</p></li></ul></div><p id="x_372"><a name="x_372"></a>You can use the <span class="command"><strong>hg tags</strong></span>
command to display the tags present in your repository. In the
output, each tagged revision is identified first by its name,
then by revision number, and finally by the unique hash of the
revision.</p><pre id="id384189" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tags</code></strong>
tip 1:8046fdcc425d
v1.0 0:a80eb2d666b7
</pre><p id="x_373"><a name="x_373"></a>Notice that <code class="literal">tip</code> is listed in the output
of <span class="command"><strong>hg tags</strong></span>. The
<code class="literal">tip</code> tag is a special “<span class="quote">floating</span>
tag, which always identifies the newest revision in the
repository.</p><p id="x_374"><a name="x_374"></a>In the output of the <span class="command"><strong>hg
tags</strong></span> command, tags are listed in reverse order, by
revision number. This usually means that recent tags are listed
before older tags. It also means that <code class="literal">tip</code> is
always going to be the first tag listed in the output of
<span class="command"><strong>hg tags</strong></span>.</p><p id="x_375"><a name="x_375"></a>When you run <span class="command"><strong>hg log</strong></span>, if it
displays a revision that has tags associated with it, it will
print those tags.</p><pre id="id384742" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log</code></strong>
changeset: 1:8046fdcc425d
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:45 2009 +0000
summary: Added tag v1.0 for changeset a80eb2d666b7
changeset: 0:a80eb2d666b7
tag: v1.0
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:45 2009 +0000
summary: Initial commit
</pre><p id="x_376"><a name="x_376"></a>Any time you need to provide a revision ID to a Mercurial
command, the command will accept a tag name in its place.
Internally, Mercurial will translate your tag name into the
corresponding revision ID, then use that.</p><pre id="id384652" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo goodbye &gt; myfile2</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'Second commit'</code></strong>
adding myfile2
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r v1.0</code></strong>
changeset: 0:a80eb2d666b7
tag: v1.0
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:45 2009 +0000
summary: Initial commit
</pre><p id="x_377"><a name="x_377"></a>There's no limit on the number of tags you can have in a
repository, or on the number of tags that a single revision can
have. As a practical matter, it's not a great idea to have
<span class="quote">too many</span>” (a number which will vary from project
to project), simply because tags are supposed to help you to
find revisions. If you have lots of tags, the ease of using
them to identify revisions diminishes rapidly.</p><p id="x_378"><a name="x_378"></a>For example, if your project has milestones as frequent as
every few days, it's perfectly reasonable to tag each one of
those. But if you have a continuous build system that makes
sure every revision can be built cleanly, you'd be introducing a
lot of noise if you were to tag every clean build. Instead, you
could tag failed builds (on the assumption that they're rare!),
or simply not use tags to track buildability.</p><p id="x_379"><a name="x_379"></a>If you want to remove a tag that you no longer want, use
<span class="command"><strong>hg tag --remove</strong></span>.</p><pre id="id384619" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tag --remove v1.0</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tags</code></strong>
tip 3:788019dad621
</pre><p id="x_37a"><a name="x_37a"></a>You can also modify a tag at any time, so that it identifies
a different revision, by simply issuing a new <span class="command"><strong>hg tag</strong></span> command. You'll have to use the
<code class="option">-f</code> option to tell Mercurial
that you <span class="emphasis"><em>really</em></span> want to update the
tag.</p><pre id="id385034" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tag -r 1 v1.1</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tags</code></strong>
tip 4:7027bc5755bd
v1.1 1:8046fdcc425d
<code class="prompt">$</code> <strong class="userinput"><code>hg tag -r 2 v1.1</code></strong>
abort: tag 'v1.1' already exists (use -f to force)
<code class="prompt">$</code> <strong class="userinput"><code>hg tag -f -r 2 v1.1</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tags</code></strong>
tip 5:cdbd327f8987
v1.1 2:97a73dafd9c0
</pre><p id="x_37b"><a name="x_37b"></a>There will still be a permanent record of the previous
identity of the tag, but Mercurial will no longer use it.
There's thus no penalty to tagging the wrong revision; all you
have to do is turn around and tag the correct revision once you
discover your error.</p><p id="x_37c"><a name="x_37c"></a>Mercurial stores tags in a normal revision-controlled file
in your repository. If you've created any tags, you'll find
them in a file in the root of your repository named <code class="filename">.hgtags</code>. When you run the <span class="command"><strong>hg tag</strong></span> command, Mercurial modifies
this file, then automatically commits the change to it. This
means that every time you run <span class="command"><strong>hg
tag</strong></span>, you'll see a corresponding changeset in the
output of <span class="command"><strong>hg log</strong></span>.</p><pre id="id385228" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 5:cdbd327f8987
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:46 2009 +0000
summary: Added tag v1.1 for changeset 97a73dafd9c0
</pre><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id384894">Handling tag conflicts during a merge</h3></div></div></div><p id="x_37d"><a name="x_37d"></a>You won't often need to care about the <code class="filename">.hgtags</code> file, but it sometimes
makes its presence known during a merge. The format of the
file is simple: it consists of a series of lines. Each line
starts with a changeset hash, followed by a space, followed by
the name of a tag.</p><p id="x_37e"><a name="x_37e"></a>If you're resolving a conflict in the <code class="filename">.hgtags</code> file during a merge,
there's one twist to modifying the <code class="filename">.hgtags</code> file: when Mercurial is
parsing the tags in a repository, it
<span class="emphasis"><em>never</em></span> reads the working copy of the
<code class="filename">.hgtags</code> file. Instead, it
reads the <span class="emphasis"><em>most recently committed</em></span>
revision of the file.</p><p id="x_37f"><a name="x_37f"></a>An unfortunate consequence of this design is that you
can't actually verify that your merged <code class="filename">.hgtags</code> file is correct until
<span class="emphasis"><em>after</em></span> you've committed a change. So if
you find yourself resolving a conflict on <code class="filename">.hgtags</code> during a merge, be sure to
run <span class="command"><strong>hg tags</strong></span> after you commit.
If it finds an error in the <code class="filename">.hgtags</code> file, it will report the
location of the error, which you can then fix and commit. You
should then run <span class="command"><strong>hg tags</strong></span>
again, just to be sure that your fix is correct.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id385011">Tags and cloning</h3></div></div></div><p id="x_380"><a name="x_380"></a>You may have noticed that the <span class="command"><strong>hg
clone</strong></span> command has a <code class="option">-r</code> option that lets you clone
an exact copy of the repository as of a particular changeset.
The new clone will not contain any project history that comes
after the revision you specified. This has an interaction
with tags that can surprise the unwary.</p><p id="x_381"><a name="x_381"></a>Recall that a tag is stored as a revision to
the <code class="filename">.hgtags</code> file. When you
create a tag, the changeset in which its recorded refers to an
older changeset. When you run <span class="command"><strong>hg clone
-r foo</strong></span> to clone a repository as of tag
<code class="literal">foo</code>, the new clone <span class="emphasis"><em>will not
contain any revision newer than the one the tag refers to,
including the revision where the tag was created</em></span>.
The result is that you'll get exactly the right subset of the
project's history in the new repository, but
<span class="emphasis"><em>not</em></span> the tag you might have
expected.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id385111">When permanent tags are too much</h3></div></div></div><p id="x_382"><a name="x_382"></a>Since Mercurial's tags are revision controlled and carried
around with a project's history, everyone you work with will
see the tags you create. But giving names to revisions has
uses beyond simply noting that revision
<code class="literal">4237e45506ee</code> is really
<code class="literal">v2.0.2</code>. If you're trying to track down a
subtle bug, you might want a tag to remind you of something
like “<span class="quote">Anne saw the symptoms with this
revision</span>”.</p><p id="x_383"><a name="x_383"></a>For cases like this, what you might want to use are
<span class="emphasis"><em>local</em></span> tags. You can create a local tag
with the <code class="option">-l</code> option to the
<span class="command"><strong>hg tag</strong></span> command. This will
store the tag in a file called <code class="filename">.hg/localtags</code>. Unlike <code class="filename">.hgtags</code>, <code class="filename">.hg/localtags</code> is not revision
controlled. Any tags you create using <code class="option">-l</code> remain strictly local to the
repository you're currently working in.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id385202">The flow of changes—big picture vs. little</h2></div></div></div><p id="x_384"><a name="x_384"></a>To return to the outline I sketched at the
beginning of the chapter, let's think about a project that has
multiple concurrent pieces of work under development at
once.</p><p id="x_385"><a name="x_385"></a>There might be a push for a new “<span class="quote">main</span>” release;
a new minor bugfix release to the last main release; and an
unexpected “<span class="quote">hot fix</span>” to an old release that is now
in maintenance mode.</p><p id="x_386"><a name="x_386"></a>The usual way people refer to these different concurrent
directions of development is as “<span class="quote">branches</span>”.
However, we've already seen numerous times that Mercurial treats
<span class="emphasis"><em>all of history</em></span> as a series of branches and
merges. Really, what we have here is two ideas that are
peripherally related, but which happen to share a name.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_387"><a name="x_387"></a><span class="quote">Big picture</span>” branches represent
the sweep of a project's evolution; people give them names,
and talk about them in conversation.</p></li><li><p id="x_388"><a name="x_388"></a><span class="quote">Little picture</span>” branches are
artefacts of the day-to-day activity of developing and
merging changes. They expose the narrative of how the code
was developed.</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id385287">Managing big-picture branches in repositories</h2></div></div></div><p id="x_389"><a name="x_389"></a>The easiest way to isolate a “<span class="quote">big picture</span>
branch in Mercurial is in a dedicated repository. If you have
an existing shared repository—let's call it
<code class="literal">myproject</code>—that reaches a
<span class="quote">1.0</span>” milestone, you can start to prepare for
future maintenance releases on top of version 1.0 by tagging the
revision from which you prepared the 1.0 release.</p><pre id="id385665" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd myproject</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tag v1.0</code></strong>
</pre><p id="x_38a"><a name="x_38a"></a>You can then clone a new shared
<code class="literal">myproject-1.0.1</code> repository as of that
tag.</p><pre id="id385745" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone myproject myproject-1.0.1</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_38b"><a name="x_38b"></a>Afterwards, if someone needs to work on a bug fix that ought
to go into an upcoming 1.0.1 minor release, they clone the
<code class="literal">myproject-1.0.1</code> repository, make their
changes, and push them back.</p><pre id="id385828" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg clone myproject-1.0.1 my-1.0.1-bugfix</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd my-1.0.1-bugfix</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'I fixed a bug using only echo!' &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Important fix for 1.0.1'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg push</code></strong>
pushing to /tmp/branch-repo1HDNuO/myproject-1.0.1
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
</pre><p id="x_38c"><a name="x_38c"></a>Meanwhile, development for
the next major release can continue, isolated and unabated, in
the <code class="literal">myproject</code> repository.</p><pre id="id385558" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone myproject my-feature</code></strong>
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd my-feature</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'This sure is an exciting new feature!' &gt; mynewfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'New feature'</code></strong>
adding mynewfile
<code class="prompt">$</code> <strong class="userinput"><code>hg push</code></strong>
pushing to /tmp/branch-repo1HDNuO/myproject
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id385475">Don't repeat yourself: merging across branches</h2></div></div></div><p id="x_38d"><a name="x_38d"></a>In many cases, if you have a bug to fix on a maintenance
branch, the chances are good that the bug exists on your
project's main branch (and possibly other maintenance branches,
too). It's a rare developer who wants to fix the same bug
multiple times, so let's look at a few ways that Mercurial can
help you to manage these bugfixes without duplicating your
work.</p><p id="x_38e"><a name="x_38e"></a>In the simplest instance, all you need to do is pull changes
from your maintenance branch into your local clone of the target
branch.</p><pre id="id385508" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone myproject myproject-merge</code></strong>
updating working directory
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>cd myproject-merge</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg pull ../myproject-1.0.1</code></strong>
pulling from ../myproject-1.0.1
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
</pre><p id="x_38f"><a name="x_38f"></a>You'll then need to merge the heads of the two branches, and
push back to the main branch.</p><pre id="id385922" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Merge bugfix from 1.0.1 branch'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg push</code></strong>
pushing to /tmp/branch-repo1HDNuO/myproject
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id386031">Naming branches within one repository</h2></div></div></div><p id="x_390"><a name="x_390"></a>In most instances, isolating branches in repositories is the
right approach. Its simplicity makes it easy to understand; and
so it's hard to make mistakes. There's a one-to-one
relationship between branches you're working in and directories
on your system. This lets you use normal (non-Mercurial-aware)
tools to work on files within a branch/repository.</p><p id="x_391"><a name="x_391"></a>If you're more in the “<span class="quote">power user</span>” category
(<span class="emphasis"><em>and</em></span> your collaborators are too), there is
an alternative way of handling branches that you can consider.
I've already mentioned the human-level distinction between
<span class="quote">small picture</span>” and “<span class="quote">big picture</span>
branches. While Mercurial works with multiple “<span class="quote">small
picture</span>” branches in a repository all the time (for
example after you pull changes in, but before you merge them),
it can <span class="emphasis"><em>also</em></span> work with multiple “<span class="quote">big
picture</span>” branches.</p><p id="x_392"><a name="x_392"></a>The key to working this way is that Mercurial lets you
assign a persistent <span class="emphasis"><em>name</em></span> to a branch.
There always exists a branch named <code class="literal">default</code>.
Even before you start naming branches yourself, you can find
traces of the <code class="literal">default</code> branch if you look for
them.</p><p id="x_393"><a name="x_393"></a>As an example, when you run the <span class="command"><strong>hg
commit</strong></span> command, and it pops up your editor so that
you can enter a commit message, look for a line that contains
the text “<span class="quote"><code class="literal">HG: branch default</code></span>” at
the bottom. This is telling you that your commit will occur on
the branch named <code class="literal">default</code>.</p><p id="x_394"><a name="x_394"></a>To start working with named branches, use the <span class="command"><strong>hg branches</strong></span> command. This command
lists the named branches already present in your repository,
telling you which changeset is the tip of each.</p><pre id="id386525" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 0:692c56a8362e
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:16 2009 +0000
summary: Initial commit
<code class="prompt">$</code> <strong class="userinput"><code>hg branches</code></strong>
default 0:692c56a8362e
</pre><p id="x_395"><a name="x_395"></a>Since you haven't created any named branches yet, the only
one that exists is <code class="literal">default</code>.</p><p id="x_396"><a name="x_396"></a>To find out what the “<span class="quote">current</span>” branch is, run
the <span class="command"><strong>hg branch</strong></span> command, giving
it no arguments. This tells you what branch the parent of the
current changeset is on.</p><pre id="id386475" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg branch</code></strong>
default
</pre><p id="x_397"><a name="x_397"></a>To create a new branch, run the <span class="command"><strong>hg
branch</strong></span> command again. This time, give it one
argument: the name of the branch you want to create.</p><pre id="id386501" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg branch foo</code></strong>
marked working directory as branch foo
<code class="prompt">$</code> <strong class="userinput"><code>hg branch</code></strong>
foo
</pre><p id="x_398"><a name="x_398"></a>After you've created a branch, you might wonder what effect
the <span class="command"><strong>hg branch</strong></span> command has had.
What do the <span class="command"><strong>hg status</strong></span> and
<span class="command"><strong>hg tip</strong></span> commands report?</p><pre id="id386417" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 0:692c56a8362e
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:16 2009 +0000
summary: Initial commit
</pre><p id="x_399"><a name="x_399"></a>Nothing has changed in the
working directory, and there's been no new history created. As
this suggests, running the <span class="command"><strong>hg
branch</strong></span> command has no permanent effect; it only
tells Mercurial what branch name to use the
<span class="emphasis"><em>next</em></span> time you commit a changeset.</p><p id="x_39a"><a name="x_39a"></a>When you commit a change, Mercurial records the name of the
branch on which you committed. Once you've switched from the
<code class="literal">default</code> branch to another and committed,
you'll see the name of the new branch show up in the output of
<span class="command"><strong>hg log</strong></span>, <span class="command"><strong>hg tip</strong></span>, and other commands that
display the same kind of output.</p><pre id="id386918" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo 'hello again' &gt;&gt; myfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Second commit'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 1:554c1c20014c
branch: foo
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Second commit
</pre><p id="x_39b"><a name="x_39b"></a>The <span class="command"><strong>hg log</strong></span>-like commands
will print the branch name of every changeset that's not on the
<code class="literal">default</code> branch. As a result, if you never
use named branches, you'll never see this information.</p><p id="x_39c"><a name="x_39c"></a>Once you've named a branch and committed a change with that
name, every subsequent commit that descends from that change
will inherit the same branch name. You can change the name of a
branch at any time, using the <span class="command"><strong>hg
branch</strong></span> command.</p><pre id="id386816" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg branch</code></strong>
foo
<code class="prompt">$</code> <strong class="userinput"><code>hg branch bar</code></strong>
marked working directory as branch bar
<code class="prompt">$</code> <strong class="userinput"><code>echo new file &gt; newfile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'Third commit'</code></strong>
adding newfile
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 2:b9e802e02f12
branch: bar
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Third commit
</pre><p id="x_39d"><a name="x_39d"></a>In practice, this is something you won't do very often, as
branch names tend to have fairly long lifetimes. (This isn't a
rule, just an observation.)</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id386726">Dealing with multiple named branches in a
repository</h2></div></div></div><p id="x_39e"><a name="x_39e"></a>If you have more than one named branch in a repository,
Mercurial will remember the branch that your working directory
is on when you start a command like <span class="command"><strong>hg
update</strong></span> or <span class="command"><strong>hg pull
-u</strong></span>. It will update the working directory to the tip
of this branch, no matter what the “<span class="quote">repo-wide</span>” tip
is. To update to a revision that's on a different named branch,
you may need to use the <code class="option">-C</code>
option to <span class="command"><strong>hg update</strong></span>.</p><p id="x_39f"><a name="x_39f"></a>This behavior is a little subtle, so let's see it in
action. First, let's remind ourselves what branch we're
currently on, and what branches are in our repository.</p><pre id="id387049" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 2:b9e802e02f12
branch: bar
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Third commit
<code class="prompt">$</code> <strong class="userinput"><code>hg branches</code></strong>
bar 2:b9e802e02f12
foo 1:554c1c20014c (inactive)
default 0:692c56a8362e (inactive)
</pre><p id="x_3a0"><a name="x_3a0"></a>We're on the <code class="literal">bar</code> branch, but there also
exists an older <span class="command"><strong>hg foo</strong></span>
branch.</p><p id="x_3a1"><a name="x_3a1"></a>We can <span class="command"><strong>hg update</strong></span> back and
forth between the tips of the <code class="literal">foo</code> and
<code class="literal">bar</code> branches without needing to use the
<code class="option">-C</code> option, because this
only involves going backwards and forwards linearly through our
change history.</p><pre id="id387392" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg update foo</code></strong>
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 1:554c1c20014c
branch: foo
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Second commit
<code class="prompt">$</code> <strong class="userinput"><code>hg update bar</code></strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
changeset: 2:b9e802e02f12
branch: bar
tag: tip
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Third commit
</pre><p id="x_3a2"><a name="x_3a2"></a>If we go back to the <code class="literal">foo</code> branch and then
run <span class="command"><strong>hg update</strong></span>, it will keep us
on <code class="literal">foo</code>, not move us to the tip of
<code class="literal">bar</code>.</p><pre id="id387295" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg update foo</code></strong>
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg update</code></strong>
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_3a3"><a name="x_3a3"></a>Committing a new change on the <code class="literal">foo</code> branch
introduces a new head.</p><pre id="id387632" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo something &gt; somefile</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'New file'</code></strong>
adding somefile
created new head
<code class="prompt">$</code> <strong class="userinput"><code>hg heads</code></strong>
changeset: 3:04da8e502cbb
branch: foo
tag: tip
parent: 1:554c1c20014c
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:18 2009 +0000
summary: New file
changeset: 2:b9e802e02f12
branch: bar
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:17 2009 +0000
summary: Third commit
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id387231">Branch names and merging</h2></div></div></div><p id="x_3a4"><a name="x_3a4"></a>As you've probably noticed, merges in Mercurial are not
symmetrical. Let's say our repository has two heads, 17 and 23.
If I <span class="command"><strong>hg update</strong></span> to 17 and then
<span class="command"><strong>hg merge</strong></span> with 23, Mercurial
records 17 as the first parent of the merge, and 23 as the
second. Whereas if I <span class="command"><strong>hg update</strong></span>
to 23 and then <span class="command"><strong>hg merge</strong></span> with
17, it records 23 as the first parent, and 17 as the
second.</p><p id="x_3a5"><a name="x_3a5"></a>This affects Mercurial's choice of branch name when you
merge. After a merge, Mercurial will retain the branch name of
the first parent when you commit the result of the merge. If
your first parent's branch name is <code class="literal">foo</code>, and
you merge with <code class="literal">bar</code>, the branch name will
still be <code class="literal">foo</code> after you merge.</p><p id="x_3a6"><a name="x_3a6"></a>It's not unusual for a repository to contain multiple heads,
each with the same branch name. Let's say I'm working on the
<code class="literal">foo</code> branch, and so are you. We commit
different changes; I pull your changes; I now have two heads,
each claiming to be on the <code class="literal">foo</code> branch. The
result of a merge will be a single head on the
<code class="literal">foo</code> branch, as you might hope.</p><p id="x_3a7"><a name="x_3a7"></a>But if I'm working on the <code class="literal">bar</code> branch, and
I merge work from the <code class="literal">foo</code> branch, the result
will remain on the <code class="literal">bar</code> branch.</p><pre id="id387860" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg branch</code></strong>
bar
<code class="prompt">$</code> <strong class="userinput"><code>hg merge foo</code></strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Merge'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
changeset: 4:c760b46b1a7b
branch: bar
tag: tip
parent: 2:b9e802e02f12
parent: 3:04da8e502cbb
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:18 2009 +0000
summary: Merge
</pre><p id="x_3a8"><a name="x_3a8"></a>To give a more concrete example, if I'm working on the
<code class="literal">bleeding-edge</code> branch, and I want to bring in
the latest fixes from the <code class="literal">stable</code> branch,
Mercurial will choose the “<span class="quote">right</span>
(<code class="literal">bleeding-edge</code>) branch name when I pull and
merge from <code class="literal">stable</code>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id387616">Branch naming is generally useful</h2></div></div></div><p id="x_3a9"><a name="x_3a9"></a>You shouldn't think of named branches as applicable only to
situations where you have multiple long-lived branches
cohabiting in a single repository. They're very useful even in
the one-branch-per-repository case.</p><p id="x_3aa"><a name="x_3aa"></a>In the simplest case, giving a name to each branch gives you
a permanent record of which branch a changeset originated on.
This gives you more context when you're trying to follow the
history of a long-lived branchy project.</p><p id="x_3ab"><a name="x_3ab"></a>If you're working with shared repositories, you can set up a
<code class="literal">pretxnchangegroup</code> hook on each
that will block incoming changes that have the
<span class="quote">wrong</span>” branch name. This provides a simple, but
effective, defence against people accidentally pushing changes
from a “<span class="quote">bleeding edge</span>” branch to a
<span class="quote">stable</span>” branch. Such a hook might look like this
inside the shared repo's <code class="filename">
/.hgrc</code>.</p><pre id="id387701" class="programlisting">[hooks]
pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</pre></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="file-names-and-pattern-matching.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="finding-and-fixing-mistakes.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 7. File names and pattern matching </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 9. Finding and fixing mistakes</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,671 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 5. Mercurial in daily use</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="behind-the-scenes.html" title="Chapter 4. Behind the scenes"><link rel="next" href="collaborating-with-other-people.html" title="Chapter 6. Collaborating with other people"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 5. Mercurial in daily use</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="behind-the-scenes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="collaborating-with-other-people.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:daily"><div class="titlepage"><div><div><h2 class="title">Chapter 5. Mercurial in daily use</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id360398">Telling Mercurial which files to track</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id360891">Explicit versus implicit file naming</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id361216">Mercurial tracks files, not directories</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id361518">How to stop tracking a file</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id361912">Removing a file does not affect its history</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id361971">Missing files</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id362350">Aside: why tell Mercurial explicitly to remove a
file?</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id362374">Useful shorthand—adding and removing files in one
step</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-in-daily-use.html#chap:daily.copy">Copying files</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id362673">The results of copying during a merge</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#sec:daily:why-copy">Why should changes follow copies?</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id363437">How to make changes not follow a
copy</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id363575">Behavior of the hg copy
command</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id364064">Renaming files</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id364249">Renaming files and merging changes</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id364290">Divergent renames and merging</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id364713">Convergent renames and merging</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id364870">Other name-related corner cases</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id365158">Recovering from mistakes</a></span></dt><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id365252">Dealing with tricky merges</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id366109">File resolution states</a></span></dt><dt><span class="sect2"><a href="mercurial-in-daily-use.html#id366263">Resolving a file merge</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id366325">More useful diffs</a></span></dt><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id366788">Which files to manage, and which to avoid</a></span></dt><dt><span class="sect1"><a href="mercurial-in-daily-use.html#id360710">Backups and mirroring</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id360398">Telling Mercurial which files to track</h2></div></div></div><p id="x_1a3"><a name="x_1a3"></a>Mercurial does not work with files in your repository unless
you tell it to manage them. The <span class="command"><strong>hg
status</strong></span> command will tell you which files Mercurial
doesn't know about; it uses a
<span class="quote"><code class="literal">?</code></span>” to display such
files.</p><p id="x_1a4"><a name="x_1a4"></a>To tell Mercurial to track a file, use the <span class="command"><strong>hg add</strong></span> command. Once you have added a
file, the entry in the output of <span class="command"><strong>hg
status</strong></span> for that file changes from
<span class="quote"><code class="literal">?</code></span>” to
<span class="quote"><code class="literal">A</code></span>”.</p><pre id="id361125" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init add-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd add-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo a &gt; myfile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
? myfile.txt
<code class="prompt">$</code> <strong class="userinput"><code>hg add myfile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
A myfile.txt
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Added one file'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
</pre><p id="x_1a5"><a name="x_1a5"></a>After you run a <span class="command"><strong>hg commit</strong></span>,
the files that you added before the commit will no longer be
listed in the output of <span class="command"><strong>hg
status</strong></span>. The reason for this is that by default, <span class="command"><strong>hg status</strong></span> only tells you about
<span class="quote">interesting</span>” files—those that you have (for
example) modified, removed, or renamed. If you have a repository
that contains thousands of files, you will rarely want to know
about files that Mercurial is tracking, but that have not
changed. (You can still get this information; we'll return to
this later.)</p><p id="x_1a6"><a name="x_1a6"></a>Once you add a file, Mercurial doesn't do anything with it
immediately. Instead, it will take a snapshot of the file's
state the next time you perform a commit. It will then continue
to track the changes you make to the file every time you commit,
until you remove the file.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id360891">Explicit versus implicit file naming</h3></div></div></div><p id="x_1a7"><a name="x_1a7"></a>A useful behavior that Mercurial has is that if you pass
the name of a directory to a command, every Mercurial command
will treat this as “<span class="quote">I want to operate on every file in
this directory and its subdirectories</span>”.</p><pre id="id361402" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mkdir b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b/somefile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo c &gt; b/source.cpp</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>mkdir b/d</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo d &gt; b/d/test.h</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add b</code></strong>
adding b/d/test.h
adding b/somefile.txt
adding b/source.cpp
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Added all files in subdirectory'</code></strong>
</pre><p id="x_1a8"><a name="x_1a8"></a>Notice in this example that Mercurial printed
the names of the files it added, whereas it didn't do so when
we added the file named <code class="filename">myfile.txt</code> in the
earlier example.</p><p id="x_1a9"><a name="x_1a9"></a>What's going on is that in the former case, we explicitly
named the file to add on the command line. The assumption
that Mercurial makes in such cases is that we know what we
are doing, and it doesn't print any output.</p><p id="x_1aa"><a name="x_1aa"></a>However, when we <span class="emphasis"><em>imply</em></span> the names of
files by giving the name of a directory, Mercurial takes the
extra step of printing the name of each file that it does
something with. This makes it more clear what is happening,
and reduces the likelihood of a silent and nasty surprise.
This behavior is common to most Mercurial commands.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id361216">Mercurial tracks files, not directories</h3></div></div></div><p id="x_1ab"><a name="x_1ab"></a>Mercurial does not track directory information. Instead,
it tracks the path to a file. Before creating a file, it
first creates any missing directory components of the path.
After it deletes a file, it then deletes any empty directories
that were in the deleted file's path. This sounds like a
trivial distinction, but it has one minor practical
consequence: it is not possible to represent a completely
empty directory in Mercurial.</p><p id="x_1ac"><a name="x_1ac"></a>Empty directories are rarely useful, and there are
unintrusive workarounds that you can use to achieve an
appropriate effect. The developers of Mercurial thus felt
that the complexity that would be required to manage empty
directories was not worth the limited benefit this feature
would bring.</p><p id="x_1ad"><a name="x_1ad"></a>If you need an empty directory in your repository, there
are a few ways to achieve this. One is to create a directory,
then <span class="command"><strong>hg add</strong></span> a
<span class="quote">hidden</span>” file to that directory. On Unix-like
systems, any file name that begins with a period
(“<span class="quote"><code class="literal">.</code></span>”) is treated as hidden by
most commands and GUI tools. This approach is illustrated
below.</p><pre id="id361678" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init hidden-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd hidden-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>mkdir empty</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>touch empty/.hidden</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add empty/.hidden</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Manage an empty-looking directory'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls empty</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone hidden-example tmp</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>ls tmp</code></strong>
empty
<code class="prompt">$</code> <strong class="userinput"><code>ls tmp/empty</code></strong>
</pre><p id="x_1ae"><a name="x_1ae"></a>Another way to tackle a need for an empty directory is to
simply create one in your automated build scripts before they
will need it.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id361518">How to stop tracking a file</h2></div></div></div><p id="x_1af"><a name="x_1af"></a>Once you decide that a file no longer belongs in
your repository, use the <span class="command"><strong>hg
remove</strong></span> command. This deletes the file, and tells
Mercurial to stop tracking it (which will occur at the next
commit). A removed file is represented in the output of
<span class="command"><strong>hg status</strong></span> with a
<span class="quote"><code class="literal">R</code></span>”.</p><pre id="id361614" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init remove-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd remove-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo a &gt; a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>mkdir b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b/b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add a b</code></strong>
adding b/b
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Small example for file removal'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg remove a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
R a
<code class="prompt">$</code> <strong class="userinput"><code>hg remove b</code></strong>
removing b/b
</pre><p id="x_1b0"><a name="x_1b0"></a>After you <span class="command"><strong>hg remove</strong></span> a file,
Mercurial will no longer track changes to that file, even if you
recreate a file with the same name in your working directory.
If you do recreate a file with the same name and want Mercurial
to track the new file, simply <span class="command"><strong>hg
add</strong></span> it. Mercurial will know that the newly added
file is not related to the old file of the same name.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id361912">Removing a file does not affect its history</h3></div></div></div><p id="x_1b1"><a name="x_1b1"></a>It is important to understand that removing a file has
only two effects.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_1b2"><a name="x_1b2"></a>It removes the current version of the file
from the working directory.</p></li><li><p id="x_1b3"><a name="x_1b3"></a>It stops Mercurial from tracking changes to
the file, from the time of the next commit.</p></li></ul></div><p id="x_1b4"><a name="x_1b4"></a>Removing a file <span class="emphasis"><em>does not</em></span> in any way
alter the <span class="emphasis"><em>history</em></span> of the file.</p><p id="x_1b5"><a name="x_1b5"></a>If you update the working directory to a
changeset that was committed when it was still tracking a file
that you later removed, the file will reappear in the working
directory, with the contents it had when you committed that
changeset. If you then update the working directory to a
later changeset, in which the file had been removed, Mercurial
will once again remove the file from the working
directory.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id361971">Missing files</h3></div></div></div><p id="x_1b6"><a name="x_1b6"></a>Mercurial considers a file that you have deleted, but not
used <span class="command"><strong>hg remove</strong></span> to delete, to
be <span class="emphasis"><em>missing</em></span>. A missing file is
represented with “<span class="quote"><code class="literal">!</code></span>” in the
output of <span class="command"><strong>hg status</strong></span>.
Mercurial commands will not generally do anything with missing
files.</p><pre id="id362389" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init missing-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd missing-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo a &gt; a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'File about to be missing'</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>rm a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
! a
</pre><p id="x_1b7"><a name="x_1b7"></a>If your repository contains a file that <span class="command"><strong>hg status</strong></span> reports as missing, and
you want the file to stay gone, you can run <span class="command"><strong>hg remove <code class="option">--after</code></strong></span> at any
time later on, to tell Mercurial that you really did mean to
remove the file.</p><pre id="id362602" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg remove --after a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
R a
</pre><p id="x_1b8"><a name="x_1b8"></a>On the other hand, if you deleted the missing file by
accident, give <span class="command"><strong>hg revert</strong></span> the
name of the file to recover. It will reappear, in unmodified
form.</p><pre id="id362278" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg revert a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cat a</code></strong>
a
<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id362350">Aside: why tell Mercurial explicitly to remove a
file?</h3></div></div></div><p id="x_1b9"><a name="x_1b9"></a>You might wonder why Mercurial requires you to explicitly
tell it that you are deleting a file. Early during the
development of Mercurial, it let you delete a file however you
pleased; Mercurial would notice the absence of the file
automatically when you next ran a <span class="command"><strong>hg
commit</strong></span>, and stop tracking the file. In practice,
this made it too easy to accidentally remove a file without
noticing.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id362374">Useful shorthand—adding and removing files in one
step</h3></div></div></div><p id="x_1ba"><a name="x_1ba"></a>Mercurial offers a combination command, <span class="command"><strong>hg addremove</strong></span>, that adds untracked
files and marks missing files as removed.</p><pre id="id362827" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init addremove-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd addremove-example</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo a &gt; a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg addremove</code></strong>
adding a
adding b
</pre><p id="x_1bb"><a name="x_1bb"></a>The <span class="command"><strong>hg commit</strong></span> command
also provides a <code class="option">-A</code>
option that performs this same add-and-remove, immediately
followed by a commit.</p><pre id="id362800" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo c &gt; c</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -A -m 'Commit with addremove'</code></strong>
adding c
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="chap:daily.copy">Copying files</h2></div></div></div><p id="x_1bc"><a name="x_1bc"></a>Mercurial provides a <span class="command"><strong>hg
copy</strong></span> command that lets you make a new copy of a
file. When you copy a file using this command, Mercurial makes
a record of the fact that the new file is a copy of the original
file. It treats these copied files specially when you merge
your work with someone else's.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id362673">The results of copying during a merge</h3></div></div></div><p id="x_1bd"><a name="x_1bd"></a>What happens during a merge is that changes
<span class="quote">follow</span>” a copy. To best illustrate what this
means, let's create an example. We'll start with the usual
tiny repository that contains a single file.</p><pre id="id362752" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init my-copy</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd my-copy</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo line &gt; file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg add file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Added a file'</code></strong>
</pre><p id="x_1be"><a name="x_1be"></a>We need to do some work in
parallel, so that we'll have something to merge. So let's
clone our repository.</p><pre id="id363244" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone my-copy your-copy</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_1bf"><a name="x_1bf"></a>Back in our initial repository, let's use the <span class="command"><strong>hg copy</strong></span> command to make a copy of
the first file we created.</p><pre id="id363206" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd my-copy</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg copy file new-file</code></strong>
</pre><p id="x_1c0"><a name="x_1c0"></a>If we look at the output of the <span class="command"><strong>hg
status</strong></span> command afterwards, the copied file looks
just like a normal added file.</p><pre id="id363145" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
A new-file
</pre><p id="x_1c1"><a name="x_1c1"></a>But if we pass the <code class="option">-C</code> option to <span class="command"><strong>hg status</strong></span>, it prints another line of
output: this is the file that our newly-added file was copied
<span class="emphasis"><em>from</em></span>.</p><pre id="id363483" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status -C</code></strong>
A new-file
file
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Copied file'</code></strong>
</pre><p id="x_1c2"><a name="x_1c2"></a>Now, back in the repository we cloned, let's make a change
in parallel. We'll add a line of content to the original file
that we created.</p><pre id="id363089" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../your-copy</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo 'new contents' &gt;&gt; file</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Changed file'</code></strong>
</pre><p id="x_1c3"><a name="x_1c3"></a>Now we have a modified <code class="filename">file</code> in this
repository. When we pull the changes from the first
repository, and merge the two heads, Mercurial will propagate
the changes that we made locally to <code class="filename">file</code>
into its copy, <code class="filename">new-file</code>.</p><pre id="id363538" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg pull ../my-copy</code></strong>
pulling from ../my-copy
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
<code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
merging file and new-file to new-file
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
<code class="prompt">$</code> <strong class="userinput"><code>cat new-file</code></strong>
line
new contents
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:daily:why-copy">Why should changes follow copies?</h3></div></div></div><p id="x_1c4"><a name="x_1c4"></a>This behavior—of changes to a file
propagating out to copies of the file—might seem
esoteric, but in most cases it's highly desirable.</p><p id="x_1c5"><a name="x_1c5"></a>First of all, remember that this propagation
<span class="emphasis"><em>only</em></span> happens when you merge. So if you
<span class="command"><strong>hg copy</strong></span> a file, and
subsequently modify the original file during the normal course
of your work, nothing will happen.</p><p id="x_1c6"><a name="x_1c6"></a>The second thing to know is that modifications will only
propagate across a copy as long as the changeset that you're
merging changes from <span class="emphasis"><em>hasn't yet seen</em></span>
the copy.</p><p id="x_1c7"><a name="x_1c7"></a>The reason that Mercurial does this is as follows. Let's
say I make an important bug fix in a source file, and commit
my changes. Meanwhile, you've decided to <span class="command"><strong>hg copy</strong></span> the file in your repository,
without knowing about the bug or having seen the fix, and you
have started hacking on your copy of the file.</p><p id="x_1c8"><a name="x_1c8"></a>If you pulled and merged my changes, and Mercurial
<span class="emphasis"><em>didn't</em></span> propagate changes across copies,
your new source file would now contain the bug, and unless you
knew to propagate the bug fix by hand, the bug would
<span class="emphasis"><em>remain</em></span> in your copy of the file.</p><p id="x_1c9"><a name="x_1c9"></a>By automatically propagating the change that fixed the bug
from the original file to the copy, Mercurial prevents this
class of problem. To my knowledge, Mercurial is the
<span class="emphasis"><em>only</em></span> revision control system that
propagates changes across copies like this.</p><p id="x_1ca"><a name="x_1ca"></a>Once your change history has a record that the copy and
subsequent merge occurred, there's usually no further need to
propagate changes from the original file to the copied file,
and that's why Mercurial only propagates changes across copies
at the first merge, and not afterwards.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id363437">How to make changes <span class="emphasis"><em>not</em></span> follow a
copy</h3></div></div></div><p id="x_1cb"><a name="x_1cb"></a>If, for some reason, you decide that this business of
automatically propagating changes across copies is not for
you, simply use your system's normal file copy command (on
Unix-like systems, that's <span class="command"><strong>cp</strong></span>) to make a
copy of a file, then <span class="command"><strong>hg add</strong></span>
the new copy by hand. Before you do so, though, please do
reread <a class="xref" href="mercurial-in-daily-use.html#sec:daily:why-copy" title="Why should changes follow copies?">the section called “Why should changes follow copies?”</a>, and make
an informed
decision that this behavior is not appropriate to your
specific case.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id363575">Behavior of the <span class="command"><strong>hg copy</strong></span>
command</h3></div></div></div><p id="x_1cc"><a name="x_1cc"></a>When you use the <span class="command"><strong>hg copy</strong></span>
command, Mercurial makes a copy of each source file as it
currently stands in the working directory. This means that if
you make some modifications to a file, then <span class="command"><strong>hg copy</strong></span> it without first having
committed those changes, the new copy will also contain the
modifications you have made up until that point. (I find this
behavior a little counterintuitive, which is why I mention it
here.)</p><p id="x_1cd"><a name="x_1cd"></a>The <span class="command"><strong>hg copy</strong></span>
command acts similarly to the Unix <span class="command"><strong>cp</strong></span>
command (you can use the <span class="command"><strong>hg
cp</strong></span> alias if you prefer). We must supply two or
more arguments, of which the last is treated as the
<span class="emphasis"><em>destination</em></span>, and all others are
<span class="emphasis"><em>sources</em></span>.</p><p id="x_685"><a name="x_685"></a>If you pass <span class="command"><strong>hg copy</strong></span> a
single file as the source, and the destination does not exist,
it creates a new file with that name.</p><pre id="id364014" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mkdir k</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg copy a k</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls k</code></strong>
a
</pre><p id="x_1ce"><a name="x_1ce"></a>If the destination is a directory, Mercurial copies its
sources into that directory.</p><pre id="id363994" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mkdir d</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg copy a b d</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>ls d</code></strong>
a b
</pre><p id="x_1cf"><a name="x_1cf"></a>Copying a directory is
recursive, and preserves the directory structure of the
source.</p><pre id="id363868" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg copy z e</code></strong>
copying z/a/c to e/a/c
</pre><p id="x_1d0"><a name="x_1d0"></a>If the source and destination are both directories, the
source tree is recreated in the destination directory.</p><pre id="id363817" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg copy z d</code></strong>
copying z/a/c to d/z/a/c
</pre><p id="x_1d1"><a name="x_1d1"></a>As with the <span class="command"><strong>hg remove</strong></span>
command, if you copy a file manually and then want Mercurial
to know that you've copied the file, simply use the <code class="option">--after</code> option to <span class="command"><strong>hg copy</strong></span>.</p><pre id="id364027" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cp a n</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg copy --after a n</code></strong>
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id364064">Renaming files</h2></div></div></div><p id="x_1d2"><a name="x_1d2"></a>It's rather more common to need to rename a file than to
make a copy of it. The reason I discussed the <span class="command"><strong>hg copy</strong></span> command before talking about
renaming files is that Mercurial treats a rename in essentially
the same way as a copy. Therefore, knowing what Mercurial does
when you copy a file tells you what to expect when you rename a
file.</p><p id="x_1d3"><a name="x_1d3"></a>When you use the <span class="command"><strong>hg rename</strong></span>
command, Mercurial makes a copy of each source file, then
deletes it and marks the file as removed.</p><pre id="id364447" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rename a b</code></strong>
</pre><p id="x_1d4"><a name="x_1d4"></a>The <span class="command"><strong>hg status</strong></span> command shows
the newly copied file as added, and the copied-from file as
removed.</p><pre id="id364426" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
A b
R a
</pre><p id="x_1d5"><a name="x_1d5"></a>As with the results of a <span class="command"><strong>hg
copy</strong></span>, we must use the <code class="option">-C</code> option to <span class="command"><strong>hg status</strong></span> to see that the added file
is really being tracked by Mercurial as a copy of the original,
now removed, file.</p><pre id="id364367" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status -C</code></strong>
A b
a
R a
</pre><p id="x_1d6"><a name="x_1d6"></a>As with <span class="command"><strong>hg remove</strong></span> and
<span class="command"><strong>hg copy</strong></span>, you can tell Mercurial
about a rename after the fact using the <code class="option">--after</code> option. In most other
respects, the behavior of the <span class="command"><strong>hg
rename</strong></span> command, and the options it accepts, are
similar to the <span class="command"><strong>hg copy</strong></span>
command.</p><p id="x_686"><a name="x_686"></a>If you're familiar with the Unix command line, you'll be
glad to know that <span class="command"><strong>hg rename</strong></span>
command can be invoked as <span class="command"><strong>hg
mv</strong></span>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id364249">Renaming files and merging changes</h3></div></div></div><p id="x_1d7"><a name="x_1d7"></a>Since Mercurial's rename is implemented as
copy-and-remove, the same propagation of changes happens when
you merge after a rename as after a copy.</p><p id="x_1d8"><a name="x_1d8"></a>If I modify a file, and you rename it to a new name, and
then we merge our respective changes, my modifications to the
file under its original name will be propagated into the file
under its new name. (This is something you might expect to
<span class="quote">simply work,</span>” but not all revision control
systems actually do this.)</p><p id="x_1d9"><a name="x_1d9"></a>Whereas having changes follow a copy is a feature where
you can perhaps nod and say “<span class="quote">yes, that might be
useful,</span>” it should be clear that having them follow a
rename is definitely important. Without this facility, it
would simply be too easy for changes to become orphaned when
files are renamed.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id364290">Divergent renames and merging</h3></div></div></div><p id="x_1da"><a name="x_1da"></a>The case of diverging names occurs when two developers
start with a file—let's call it
<code class="filename">foo</code>—in their respective
repositories.</p><pre id="id364337" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg clone orig anne</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg clone orig bob</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_1db"><a name="x_1db"></a>Anne renames the file to <code class="filename">bar</code>.</p><pre id="id364844" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd anne</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg rename foo bar</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -m 'Rename foo to bar'</code></strong>
</pre><p id="x_1dc"><a name="x_1dc"></a>Meanwhile, Bob renames it to
<code class="filename">quux</code>. (Remember that <span class="command"><strong>hg mv</strong></span> is an alias for <span class="command"><strong>hg rename</strong></span>.)</p><pre id="id364729" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../bob</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg mv foo quux</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -m 'Rename foo to quux'</code></strong>
</pre><p id="x_1dd"><a name="x_1dd"></a>I like to think of this as a conflict because each
developer has expressed different intentions about what the
file ought to be named.</p><p id="x_1de"><a name="x_1de"></a>What do you think should happen when they merge their
work? Mercurial's actual behavior is that it always preserves
<span class="emphasis"><em>both</em></span> names when it merges changesets that
contain divergent renames.</p><pre id="id365077" class="screen"># See http://www.selenic.com/mercurial/bts/issue455
<code class="prompt">$</code> <strong class="userinput"><code>cd ../orig</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg pull -u ../anne</code></strong>
pulling from ../anne
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg pull ../bob</code></strong>
pulling from ../bob
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
<code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
warning: detected divergent renames of foo to:
bar
quux
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
<code class="prompt">$</code> <strong class="userinput"><code>ls</code></strong>
bar quux
</pre><p id="x_1df"><a name="x_1df"></a>Notice that while Mercurial warns about the divergent
renames, it leaves it up to you to do something about the
divergence after the merge.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id364713">Convergent renames and merging</h3></div></div></div><p id="x_1e0"><a name="x_1e0"></a>Another kind of rename conflict occurs when two people
choose to rename different <span class="emphasis"><em>source</em></span> files
to the same <span class="emphasis"><em>destination</em></span>. In this case,
Mercurial runs its normal merge machinery, and lets you guide
it to a suitable resolution.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id364870">Other name-related corner cases</h3></div></div></div><p id="x_1e1"><a name="x_1e1"></a>Mercurial has a longstanding bug in which it fails to
handle a merge where one side has a file with a given name,
while another has a directory with the same name. This is
documented as <a class="ulink" href="http://www.selenic.com/mercurial/bts/issue29" target="_top">issue
29</a>.</p><pre id="id365033" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init issue29</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd issue29</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo a &gt; a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -Ama</code></strong>
adding a
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -Amb</code></strong>
adding b
<code class="prompt">$</code> <strong class="userinput"><code>hg up 0</code></strong>
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>mkdir b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo b &gt; b/b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -Amc</code></strong>
adding b/b
created new head
<code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
abort: Is a directory: /tmp/issue29ozeAHx/issue29/b
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id365158">Recovering from mistakes</h2></div></div></div><p id="x_1e2"><a name="x_1e2"></a>Mercurial has some useful commands that will help you to
recover from some common mistakes.</p><p id="x_1e3"><a name="x_1e3"></a>The <span class="command"><strong>hg revert</strong></span> command lets
you undo changes that you have made to your working directory.
For example, if you <span class="command"><strong>hg add</strong></span> a
file by accident, just run <span class="command"><strong>hg
revert</strong></span> with the name of the file you added, and
while the file won't be touched in any way, it won't be tracked
for adding by Mercurial any longer, either. You can also use
<span class="command"><strong>hg revert</strong></span> to get rid of
erroneous changes to a file.</p><p id="x_1e4"><a name="x_1e4"></a>It is helpful to remember that the <span class="command"><strong>hg revert</strong></span> command is useful for
changes that you have not yet committed. Once you've committed
a change, if you decide it was a mistake, you can still do
something about it, though your options may be more
limited.</p><p id="x_1e5"><a name="x_1e5"></a>For more information about the <span class="command"><strong>hg revert</strong></span> command, and details about
how to deal with changes you have already committed, see <a class="xref" href="finding-and-fixing-mistakes.html" title="Chapter 9. Finding and fixing mistakes">Chapter 9, <i>Finding and fixing mistakes</i></a>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id365252">Dealing with tricky merges</h2></div></div></div><p id="x_687"><a name="x_687"></a>In a complicated or large project, it's not unusual for a
merge of two changesets to result in some headaches. Suppose
there's a big source file that's been extensively edited by each
side of a merge: this is almost inevitably going to result in
conflicts, some of which can take a few tries to sort
out.</p><p id="x_688"><a name="x_688"></a>Let's develop a simple case of this and see how to deal with
it. We'll start off with a repository containing one file, and
clone it twice.</p><pre id="id365683" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init conflict</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>cd conflict</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo first &gt; myfile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -A -m first</code></strong>
adding myfile.txt
<code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg clone conflict left</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg clone conflict right</code></strong>
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre><p id="x_689"><a name="x_689"></a>In one clone, we'll modify the file in one way.</p><pre id="id365663" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd left</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo left &gt;&gt; myfile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -m left</code></strong>
</pre><p id="x_68a"><a name="x_68a"></a>In another, we'll modify the file differently.</p><pre id="id365607" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../right</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>echo right &gt;&gt; myfile.txt</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg ci -m right</code></strong>
</pre><p id="x_68b"><a name="x_68b"></a>Next, we'll pull each set of changes into our original
repo.</p><pre id="id366073" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ../conflict</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg pull -u ../left</code></strong>
pulling from ../left
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<code class="prompt">$</code> <strong class="userinput"><code>hg pull -u ../right</code></strong>
pulling from ../right
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
not updating, since new heads added
(run 'hg heads' to see heads, 'hg merge' to merge)
</pre><p id="x_68c"><a name="x_68c"></a>We expect our repository to now contain two heads.</p><pre id="id366011" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg heads</code></strong>
changeset: 2:adc157afe092
tag: tip
parent: 0:b704237e4749
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:25 2009 +0000
summary: right
changeset: 1:64abc51bea49
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:25 2009 +0000
summary: left
</pre><p id="x_68d"><a name="x_68d"></a>Normally, if we run <span class="command"><strong>hg
merge</strong></span> at this point, it will drop us into a GUI that
will let us manually resolve the conflicting edits to
<code class="filename">myfile.txt</code>. However, to simplify things
for presentation here, we'd like the merge to fail immediately
instead. Here's one way we can do so.</p><pre id="id366060" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>export HGMERGE=merge</code></strong>
</pre><p id="x_68e"><a name="x_68e"></a>We've told Mercurial's merge machinery to run the command
<span class="command"><strong>false</strong></span> (which, as we desire, fails
immediately) if it detects a merge that it can't sort out
automatically.</p><p id="x_68f"><a name="x_68f"></a>If we now fire up <span class="command"><strong>hg
merge</strong></span>, it should grind to a halt and report a
failure.</p><pre id="id365931" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
merging myfile.txt
merge: warning: conflicts during merge
merging myfile.txt failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
</pre><p id="x_690"><a name="x_690"></a>Even if we don't notice that the merge failed, Mercurial
will prevent us from accidentally committing the result of a
failed merge.</p><pre id="id366386" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Attempt to commit a failed merge'</code></strong>
abort: unresolved merge conflicts (see hg resolve)
</pre><p id="x_691"><a name="x_691"></a>When <span class="command"><strong>hg commit</strong></span> fails in
this case, it suggests that we use the unfamiliar <span class="command"><strong>hg resolve</strong></span> command. As usual,
<span class="command"><strong>hg help resolve</strong></span> will print a
helpful synopsis.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id366109">File resolution states</h3></div></div></div><p id="x_692"><a name="x_692"></a>When a merge occurs, most files will usually remain
unmodified. For each file where Mercurial has to do
something, it tracks the state of the file.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_693"><a name="x_693"></a>A <span class="emphasis"><em>resolved</em></span> file has been
successfully merged, either automatically by Mercurial or
manually with human intervention.</p></li><li><p id="x_694"><a name="x_694"></a>An <span class="emphasis"><em>unresolved</em></span> file was not merged
successfully, and needs more attention.</p></li></ul></div><p id="x_695"><a name="x_695"></a>If Mercurial sees <span class="emphasis"><em>any</em></span> file in the
unresolved state after a merge, it considers the merge to have
failed. Fortunately, we do not need to restart the entire
merge from scratch.</p><p id="x_696"><a name="x_696"></a>The <code class="option">--list</code> or
<code class="option">-l</code> option to <span class="command"><strong>hg resolve</strong></span> prints out the state of
each merged file.</p><pre id="id366549" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg resolve -l</code></strong>
U myfile.txt
</pre><p id="x_697"><a name="x_697"></a>In the output from <span class="command"><strong>hg
resolve</strong></span>, a resolved file is marked with
<code class="literal">R</code>, while an unresolved file is marked with
<code class="literal">U</code>. If any files are listed with
<code class="literal">U</code>, we know that an attempt to commit the
results of the merge will fail.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id366263">Resolving a file merge</h3></div></div></div><p id="x_698"><a name="x_698"></a>We have several options to move a file from the unresolved
into the resolved state. By far the most common is to rerun
<span class="command"><strong>hg resolve</strong></span>. If we pass the
names of individual files or directories, it will retry the
merges of any unresolved files present in those locations. We
can also pass the <code class="option">--all</code>
or <code class="option">-a</code> option, which
will retry the merges of <span class="emphasis"><em>all</em></span> unresolved
files.</p><p id="x_699"><a name="x_699"></a>Mercurial also lets us modify the resolution state of a
file directly. We can manually mark a file as resolved using
the <code class="option">--mark</code> option, or
as unresolved using the <code class="option">--unmark</code> option. This allows
us to clean up a particularly messy merge by hand, and to keep
track of our progress with each file as we go.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id366325">More useful diffs</h2></div></div></div><p id="x_6c7"><a name="x_6c7"></a>The default output of the <span class="command"><strong>hg
diff</strong></span> command is backwards compatible with the
regular <span class="command"><strong>diff</strong></span> command, but this has some
drawbacks.</p><p id="x_6c8"><a name="x_6c8"></a>Consider the case where we use <span class="command"><strong>hg
rename</strong></span> to rename a file.</p><pre id="id366520" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rename a b</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg diff</code></strong>
diff -r 4b300eaa7199 a
--- a/a Tue May 05 06:55:21 2009 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-a
diff -r 4b300eaa7199 b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/b Tue May 05 06:55:21 2009 +0000
@@ -0,0 +1,1 @@
+a
</pre><p id="x_6c9"><a name="x_6c9"></a>The output of <span class="command"><strong>hg diff</strong></span> above
obscures the fact that we simply renamed a file. The <span class="command"><strong>hg diff</strong></span> command accepts an option,
<code class="option">--git</code> or <code class="option">-g</code>, to use a newer
diff format that displays such information in a more readable
form.</p><pre id="id366842" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg diff -g</code></strong>
diff --git a/a b/b
rename from a
rename to b
</pre><p id="x_6ca"><a name="x_6ca"></a>This option also helps with a case that can otherwise be
confusing: a file that appears to be modified according to
<span class="command"><strong>hg status</strong></span>, but for which
<span class="command"><strong>hg diff</strong></span> prints nothing. This
situation can arise if we change the file's execute
permissions.</p><pre id="id366568" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>chmod +x a</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg st</code></strong>
M a
<code class="prompt">$</code> <strong class="userinput"><code>hg diff</code></strong>
</pre><p id="x_6cb"><a name="x_6cb"></a>The normal <span class="command"><strong>diff</strong></span> command pays no attention
to file permissions, which is why <span class="command"><strong>hg
diff</strong></span> prints nothing by default. If we supply it
with the <code class="option">-g</code> option, it tells us what really
happened.</p><pre id="id366782" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg diff -g</code></strong>
diff --git a/a b/a
old mode 100644
new mode 100755
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id366788">Which files to manage, and which to avoid</h2></div></div></div><p id="x_6cc"><a name="x_6cc"></a>Revision control systems are generally best at managing text
files that are written by humans, such as source code, where the
files do not change much from one revision to the next. Some
centralized revision control systems can also deal tolerably
well with binary files, such as bitmap images.</p><p id="x_6cd"><a name="x_6cd"></a>For instance, a game development team will typically manage
both its source code and all of its binary assets (e.g. geometry
data, textures, map layouts) in a revision control
system.</p><p id="x_6ce"><a name="x_6ce"></a>Because it is usually impossible to merge two conflicting
modifications to a binary file, centralized systems often
provide a file locking mechanism that allow a user to say
<span class="quote">I am the only person who can edit this
file</span>”.</p><p id="x_6cf"><a name="x_6cf"></a>Compared to a centralized system, a distributed revision
control system changes some of the factors that guide decisions
over which files to manage and how.</p><p id="x_6d0"><a name="x_6d0"></a>For instance, a distributed revision control system cannot,
by its nature, offer a file locking facility. There is thus no
built-in mechanism to prevent two people from making conflicting
changes to a binary file. If you have a team where several
people may be editing binary files frequently, it may not be a
good idea to use Mercurial—or any other distributed
revision control system—to manage those files.</p><p id="x_6d1"><a name="x_6d1"></a>When storing modifications to a file, Mercurial usually
saves only the differences between the previous and current
versions of the file. For most text files, this is extremely
efficient. However, some files (particularly binary files) are
laid out in such a way that even a small change to a file's
logical content results in many or most of the bytes inside the
file changing. For instance, compressed files are particularly
susceptible to this. If the differences between each successive
version of a file are always large, Mercurial will not be able
to store the file's revision history very efficiently. This can
affect both local storage needs and the amount of time it takes
to clone a repository.</p><p id="x_6d2"><a name="x_6d2"></a>To get an idea of how this could affect you in practice,
suppose you want to use Mercurial to manage an OpenOffice
document. OpenOffice stores documents on disk as compressed zip
files. Edit even a single letter of your document in OpenOffice,
and almost every byte in the entire file will change when you
save it. Now suppose that file is 2MB in size. Because most of
the file changes every time you save, Mercurial will have to
store all 2MB of the file every time you commit, even though
from your perspective, perhaps only a few words are changing
each time. A single frequently-edited file that is not friendly
to Mercurial's storage assumptions can easily have an outsized
effect on the size of the repository.</p><p id="x_6d3"><a name="x_6d3"></a>Even worse, if both you and someone else edit the OpenOffice
document you're working on, there is no useful way to merge your
work. In fact, there isn't even a good way to tell what the
differences are between your respective changes.</p><p id="x_6d4"><a name="x_6d4"></a>There are thus a few clear recommendations about specific
kinds of files to be very careful with.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_6d5"><a name="x_6d5"></a>Files that are very large and incompressible, e.g. ISO
CD-ROM images, will by virtue of sheer size make clones over
a network very slow.</p></li><li><p id="x_6d6"><a name="x_6d6"></a>Files that change a lot from one revision to the next
may be expensive to store if you edit them frequently, and
conflicts due to concurrent edits may be difficult to
resolve.</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id360710">Backups and mirroring</h2></div></div></div><p id="x_6d7"><a name="x_6d7"></a>Since Mercurial maintains a complete copy of history in each
clone, everyone who uses Mercurial to collaborate on a project
can potentially act as a source of backups in the event of a
catastrophe. If a central repository becomes unavailable, you
can construct a replacement simply by cloning a copy of the
repository from one contributor, and pulling any changes they
may not have seen from others.</p><p id="x_6d8"><a name="x_6d8"></a>It is simple to use Mercurial to perform off-site backups
and remote mirrors. Set up a periodic job (e.g. via the
<span class="command"><strong>cron</strong></span> command) on a remote server to pull
changes from your master repositories every hour. This will
only be tricky in the unlikely case that the number of master
repositories you maintain changes frequently, in which case
you'll need to do a little scripting to refresh the list of
repositories to back up.</p><p id="x_6d9"><a name="x_6d9"></a>If you perform traditional backups of your master
repositories to tape or disk, and you want to back up a
repository named <code class="filename">myrepo</code>, use <span class="command"><strong>hg
clone -U myrepo myrepo.bak</strong></span> to create a
clone of <code class="filename">myrepo</code> before you start your
backups. The <code class="option">-U</code> option doesn't check out a
working directory after the clone completes, since that would be
superfluous and make the backup take longer.</p><p id="x_6da"><a name="x_6da"></a>If you then back up <code class="filename">myrepo.bak</code> instead
of <code class="filename">myrepo</code>, you will be guaranteed to have a
consistent snapshot of your repository that won't be pushed to
by an insomniac developer in mid-backup.</p></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="behind-the-scenes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="collaborating-with-other-people.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 4. Behind the scenes </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 6. Collaborating with other people</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,263 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Appendix B. Mercurial Queues reference</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="migrating-to-mercurial.html" title="Appendix A. Migrating to Mercurial"><link rel="next" href="installing-mercurial-from-source.html" title="Appendix C. Installing Mercurial from source"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix B. Mercurial Queues reference</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="migrating-to-mercurial.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="installing-mercurial-from-source.html">Next</a></td></tr></table></div><div class="appendix" lang="en" id="chap:mqref"><div class="titlepage"><div><div><h2 class="title">Appendix B. Mercurial Queues reference</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="mercurial-queues-reference.html#sec:mqref:cmdref">MQ command reference</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444629">qapplied—print
applied patches</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444662">qcommit—commit
changes in the queue repository</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444757">qdelete—delete a patch
from the series
file</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444842">qdiff—print a
diff of the topmost applied patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444880">qfold—move
applied patches into repository history</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id444909">qfold—merge
(fold) several patches into one</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445054">qheader—display the
header/description of a patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445085">qimport—import
a third-party patch into the queue</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445169">qinit—prepare
a repository to work with MQ</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445302">qnew—create a
new patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445412">qnext—print
the name of the next patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445458">qpop—pop
patches off the stack</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445656">qprev—print
the name of the previous patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#sec:mqref:cmd:qpush">qpush—push
patches onto the stack</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id445928">qrefresh—update the
topmost applied patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446108">qrename—rename
a patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446162">qseries—print
the entire patch series</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446201">qtop—print the
name of the current patch</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446230">qunapplied—print patches
not yet applied</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446269">hg strip—remove a
revision and descendants</a></span></dt></dl></dd><dt><span class="sect1"><a href="mercurial-queues-reference.html#id446370">MQ file reference</a></span></dt><dd><dl><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446375">The series
file</a></span></dt><dt><span class="sect2"><a href="mercurial-queues-reference.html#id446487">The status
file</a></span></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:mqref:cmdref">MQ command reference</h2></div></div></div><p id="x_5e8"><a name="x_5e8"></a>For an overview of the commands provided by MQ, use the
command <span class="command"><strong>hg help mq</strong></span>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444629"><span class="command"><strong>qapplied</strong></span>—print
applied patches</h3></div></div></div><p id="x_5e9"><a name="x_5e9"></a>The <span class="command"><strong>qapplied</strong></span> command
prints the current stack of applied patches. Patches are
printed in oldest-to-newest order, so the last patch in the
list is the “<span class="quote">top</span>” patch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444662"><span class="command"><strong>qcommit</strong></span>—commit
changes in the queue repository</h3></div></div></div><p id="x_5ea"><a name="x_5ea"></a>The <span class="command"><strong>qcommit</strong></span> command
commits any outstanding changes in the <code class="filename">.hg/patches</code>
repository. This command only works if the <code class="filename">.hg/patches</code>
directory is a repository, i.e. you created the directory
using <span class="command"><strong>hg qinit <code class="option">-c</code></strong></span> or
ran <span class="command"><strong>hg init</strong></span> in the directory
after running <span class="command"><strong>qinit</strong></span>.</p><p id="x_5eb"><a name="x_5eb"></a>This command is shorthand for <span class="command"><strong>hg
commit --cwd .hg/patches</strong></span>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444757"><span class="command"><strong>qdelete</strong></span>—delete a patch
from the <code class="filename">series</code>
file</h3></div></div></div><p id="x_5ec"><a name="x_5ec"></a>The <span class="command"><strong>qdelete</strong></span> command
removes the entry for a patch from the <code class="filename">series</code> file in the <code class="filename">.hg/patches</code>
directory. It does not pop the patch if the patch is already
applied. By default, it does not delete the patch file; use
the <code class="option">-f</code> option
to do that.</p><p id="x_5ed"><a name="x_5ed"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5ee"><a name="x_5ee"></a><code class="option">-f</code>: Delete the
patch file.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444842"><span class="command"><strong>qdiff</strong></span>—print a
diff of the topmost applied patch</h3></div></div></div><p id="x_5ef"><a name="x_5ef"></a>The <span class="command"><strong>qdiff</strong></span> command
prints a diff of the topmost applied patch. It is equivalent
to <span class="command"><strong>hg diff -r-2:-1</strong></span>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444880"><span class="command"><strong>qfold</strong></span>—move
applied patches into repository history</h3></div></div></div><p id="x_72d"><a name="x_72d"></a>The <span class="command"><strong>hg qfinish</strong></span> command converts the
specified applied patches into permanent changes by moving
them out of MQ's control so that they will be treated as
normal repository history.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id444909"><span class="command"><strong>qfold</strong></span>—merge
(“<span class="quote">fold</span>”) several patches into one</h3></div></div></div><p id="x_5f0"><a name="x_5f0"></a>The <span class="command"><strong>qfold</strong></span> command
merges multiple patches into the topmost applied patch, so
that the topmost applied patch makes the union of all of the
changes in the patches in question.</p><p id="x_5f1"><a name="x_5f1"></a>The patches to fold must not be applied; <span class="command"><strong>qfold</strong></span> will exit with an error if
any is. The order in which patches are folded is significant;
<span class="command"><strong>hg qfold a b</strong></span> means
<span class="quote">apply the current topmost patch, followed by
<code class="literal">a</code>, followed by
<code class="literal">b</code></span>”.</p><p id="x_5f2"><a name="x_5f2"></a>The comments from the folded patches are appended to the
comments of the destination patch, with each block of comments
separated by three asterisk
(“<span class="quote"><code class="literal">*</code></span>”) characters. Use the
<code class="option">-e</code> option to
edit the commit message for the combined patch/changeset after
the folding has completed.</p><p id="x_5f3"><a name="x_5f3"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5f4"><a name="x_5f4"></a><code class="option">-e</code>: Edit the
commit message and patch description for the newly folded
patch.</p></li><li><p id="x_5f5"><a name="x_5f5"></a><code class="option">-l</code>: Use the
contents of the given file as the new commit message and
patch description for the folded patch.</p></li><li><p id="x_5f6"><a name="x_5f6"></a><code class="option">-m</code>: Use the
given text as the new commit message and patch description
for the folded patch.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445054"><span class="command"><strong>qheader</strong></span>—display the
header/description of a patch</h3></div></div></div><p id="x_5f7"><a name="x_5f7"></a>The <span class="command"><strong>qheader</strong></span> command
prints the header, or description, of a patch. By default, it
prints the header of the topmost applied patch. Given an
argument, it prints the header of the named patch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445085"><span class="command"><strong>qimport</strong></span>—import
a third-party patch into the queue</h3></div></div></div><p id="x_5f8"><a name="x_5f8"></a>The <span class="command"><strong>qimport</strong></span> command
adds an entry for an external patch to the <code class="filename">series</code> file, and copies the patch
into the <code class="filename">.hg/patches</code> directory. It adds
the entry immediately after the topmost applied patch, but
does not push the patch.</p><p id="x_5f9"><a name="x_5f9"></a>If the <code class="filename">.hg/patches</code> directory is a
repository, <span class="command"><strong>qimport</strong></span>
automatically does an <span class="command"><strong>hg add</strong></span>
of the imported patch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445169"><span class="command"><strong>qinit</strong></span>—prepare
a repository to work with MQ</h3></div></div></div><p id="x_5fa"><a name="x_5fa"></a>The <span class="command"><strong>qinit</strong></span> command
prepares a repository to work with MQ. It creates a directory
called <code class="filename">.hg/patches</code>.</p><p id="x_5fb"><a name="x_5fb"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5fc"><a name="x_5fc"></a><code class="option">-c</code>: Create
<code class="filename">.hg/patches</code> as a repository
in its own right. Also creates a <code class="filename">.hgignore</code> file that will
ignore the <code class="filename">status</code>
file.</p></li></ul></div><p id="x_5fd"><a name="x_5fd"></a>When the <code class="filename">.hg/patches</code> directory is a
repository, the <span class="command"><strong>qimport</strong></span>
and <span class="command"><strong>qnew</strong></span> commands
automatically <span class="command"><strong>hg add</strong></span> new
patches.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445302"><span class="command"><strong>qnew</strong></span>—create a
new patch</h3></div></div></div><p id="x_5fe"><a name="x_5fe"></a>The <span class="command"><strong>qnew</strong></span> command
creates a new patch. It takes one mandatory argument, the
name to use for the patch file. The newly created patch is
created empty by default. It is added to the <code class="filename">series</code> file after the current
topmost applied patch, and is immediately pushed on top of
that patch.</p><p id="x_5ff"><a name="x_5ff"></a>If <span class="command"><strong>qnew</strong></span> finds modified
files in the working directory, it will refuse to create a new
patch unless the <code class="option">-f</code> option is used
(see below). This behavior allows you to <span class="command"><strong>qrefresh</strong></span> your topmost applied
patch before you apply a new patch on top of it.</p><p id="x_600"><a name="x_600"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_601"><a name="x_601"></a><code class="option">-f</code>: Create a new
patch if the contents of the working directory are
modified. Any outstanding modifications are added to the
newly created patch, so after this command completes, the
working directory will no longer be modified.</p></li><li><p id="x_602"><a name="x_602"></a><code class="option">-m</code>: Use the given
text as the commit message. This text will be stored at
the beginning of the patch file, before the patch
data.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445412"><span class="command"><strong>qnext</strong></span>—print
the name of the next patch</h3></div></div></div><p id="x_603"><a name="x_603"></a>The <span class="command"><strong>qnext</strong></span> command
prints the name name of the next patch in the <code class="filename">series</code> file after the topmost
applied patch. This patch will become the topmost applied
patch if you run <span class="command"><strong>qpush</strong></span>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445458"><span class="command"><strong>qpop</strong></span>—pop
patches off the stack</h3></div></div></div><p id="x_604"><a name="x_604"></a>The <span class="command"><strong>qpop</strong></span> command
removes applied patches from the top of the stack of applied
patches. By default, it removes only one patch.</p><p id="x_605"><a name="x_605"></a>This command removes the changesets that represent the
popped patches from the repository, and updates the working
directory to undo the effects of the patches.</p><p id="x_606"><a name="x_606"></a>This command takes an optional argument, which it uses as
the name or index of the patch to pop to. If given a name, it
will pop patches until the named patch is the topmost applied
patch. If given a number, <span class="command"><strong>qpop</strong></span> treats the number as an
index into the entries in the series file, counting from zero
(empty lines and lines containing only comments do not count).
It pops patches until the patch identified by the given index
is the topmost applied patch.</p><p id="x_607"><a name="x_607"></a>The <span class="command"><strong>qpop</strong></span> command does
not read or write patches or the <code class="filename">series</code> file. It is thus safe to
<span class="command"><strong>qpop</strong></span> a patch that you have
removed from the <code class="filename">series</code>
file, or a patch that you have renamed or deleted entirely.
In the latter two cases, use the name of the patch as it was
when you applied it.</p><p id="x_608"><a name="x_608"></a>By default, the <span class="command"><strong>qpop</strong></span>
command will not pop any patches if the working directory has
been modified. You can override this behavior using the
<code class="option">-f</code> option,
which reverts all modifications in the working
directory.</p><p id="x_609"><a name="x_609"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_60a"><a name="x_60a"></a><code class="option">-a</code>: Pop all
applied patches. This returns the repository to its state
before you applied any patches.</p></li><li><p id="x_60b"><a name="x_60b"></a><code class="option">-f</code>: Forcibly
revert any modifications to the working directory when
popping.</p></li><li><p id="x_60c"><a name="x_60c"></a><code class="option">-n</code>: Pop a patch
from the named queue.</p></li></ul></div><p id="x_60d"><a name="x_60d"></a>The <span class="command"><strong>qpop</strong></span> command
removes one line from the end of the <code class="filename">status</code> file for each patch that it
pops.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445656"><span class="command"><strong>qprev</strong></span>—print
the name of the previous patch</h3></div></div></div><p id="x_60e"><a name="x_60e"></a>The <span class="command"><strong>qprev</strong></span> command
prints the name of the patch in the <code class="filename">series</code> file that comes before the
topmost applied patch. This will become the topmost applied
patch if you run <span class="command"><strong>qpop</strong></span>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:mqref:cmd:qpush"><span class="command"><strong>qpush</strong></span>—push
patches onto the stack</h3></div></div></div><p id="x_60f"><a name="x_60f"></a>The <span class="command"><strong>qpush</strong></span> command adds
patches onto the applied stack. By default, it adds only one
patch.</p><p id="x_610"><a name="x_610"></a>This command creates a new changeset to represent each
applied patch, and updates the working directory to apply the
effects of the patches.</p><p id="x_611"><a name="x_611"></a>The default data used when creating a changeset are as
follows:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_612"><a name="x_612"></a>The commit date and time zone are the current
date and time zone. Because these data are used to
compute the identity of a changeset, this means that if
you <span class="command"><strong>qpop</strong></span> a patch and
<span class="command"><strong>qpush</strong></span> it again, the
changeset that you push will have a different identity
than the changeset you popped.</p></li><li><p id="x_613"><a name="x_613"></a>The author is the same as the default used by
the <span class="command"><strong>hg commit</strong></span>
command.</p></li><li><p id="x_614"><a name="x_614"></a>The commit message is any text from the patch
file that comes before the first diff header. If there is
no such text, a default commit message is used that
identifies the name of the patch.</p></li></ul></div><p id="x_615"><a name="x_615"></a>If a patch contains a Mercurial patch header,
the information in the patch header overrides these
defaults.</p><p id="x_616"><a name="x_616"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_617"><a name="x_617"></a><code class="option">-a</code>: Push all
unapplied patches from the <code class="filename">series</code> file until there are
none left to push.</p></li><li><p id="x_618"><a name="x_618"></a><code class="option">-l</code>: Add the name
of the patch to the end of the commit message.</p></li><li><p id="x_619"><a name="x_619"></a><code class="option">-m</code>: If a patch
fails to apply cleanly, use the entry for the patch in
another saved queue to compute the parameters for a
three-way merge, and perform a three-way merge using the
normal Mercurial merge machinery. Use the resolution of
the merge as the new patch content.</p></li><li><p id="x_61a"><a name="x_61a"></a><code class="option">-n</code>: Use the
named queue if merging while pushing.</p></li></ul></div><p id="x_61b"><a name="x_61b"></a>The <span class="command"><strong>qpush</strong></span> command
reads, but does not modify, the <code class="filename">series</code> file. It appends one line
to the <span class="command"><strong>hg status</strong></span> file for
each patch that it pushes.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id445928"><span class="command"><strong>qrefresh</strong></span>—update the
topmost applied patch</h3></div></div></div><p id="x_61c"><a name="x_61c"></a>The <span class="command"><strong>qrefresh</strong></span> command
updates the topmost applied patch. It modifies the patch,
removes the old changeset that represented the patch, and
creates a new changeset to represent the modified
patch.</p><p id="x_61d"><a name="x_61d"></a>The <span class="command"><strong>qrefresh</strong></span> command
looks for the following modifications:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_61e"><a name="x_61e"></a>Changes to the commit message, i.e. the text
before the first diff header in the patch file, are
reflected in the new changeset that represents the
patch.</p></li><li><p id="x_61f"><a name="x_61f"></a>Modifications to tracked files in the working
directory are added to the patch.</p></li><li><p id="x_620"><a name="x_620"></a>Changes to the files tracked using <span class="command"><strong>hg add</strong></span>, <span class="command"><strong>hg copy</strong></span>, <span class="command"><strong>hg remove</strong></span>, or <span class="command"><strong>hg rename</strong></span>. Added files and copy
and rename destinations are added to the patch, while
removed files and rename sources are removed.</p></li></ul></div><p id="x_621"><a name="x_621"></a>Even if <span class="command"><strong>qrefresh</strong></span>
detects no changes, it still recreates the changeset that
represents the patch. This causes the identity of the
changeset to differ from the previous changeset that
identified the patch.</p><p id="x_622"><a name="x_622"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_623"><a name="x_623"></a><code class="option">-e</code>: Modify
the commit and patch description, using the preferred text
editor.</p></li><li><p id="x_624"><a name="x_624"></a><code class="option">-m</code>: Modify
the commit message and patch description, using the given
text.</p></li><li><p id="x_625"><a name="x_625"></a><code class="option">-l</code>: Modify
the commit message and patch description, using text from
the given file.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446108"><span class="command"><strong>qrename</strong></span>—rename
a patch</h3></div></div></div><p id="x_626"><a name="x_626"></a>The <span class="command"><strong>qrename</strong></span> command
renames a patch, and changes the entry for the patch in the
<code class="filename">series</code> file.</p><p id="x_627"><a name="x_627"></a>With a single argument, <span class="command"><strong>qrename</strong></span> renames the topmost
applied patch. With two arguments, it renames its first
argument to its second.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446162"><span class="command"><strong>qseries</strong></span>—print
the entire patch series</h3></div></div></div><p id="x_62a"><a name="x_62a"></a>The <span class="command"><strong>qseries</strong></span> command
prints the entire patch series from the <code class="filename">series</code> file. It prints only patch
names, not empty lines or comments. It prints in order from
first to be applied to last.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446201"><span class="command"><strong>qtop</strong></span>—print the
name of the current patch</h3></div></div></div><p id="x_62b"><a name="x_62b"></a>The <span class="command"><strong>qtop</strong></span> prints the
name of the topmost currently applied patch.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446230"><span class="command"><strong>qunapplied</strong></span>—print patches
not yet applied</h3></div></div></div><p id="x_62c"><a name="x_62c"></a>The <span class="command"><strong>qunapplied</strong></span> command
prints the names of patches from the <code class="filename">series</code> file that are not yet
applied. It prints them in order from the next patch that
will be pushed to the last.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446269"><span class="command"><strong>hg strip</strong></span>—remove a
revision and descendants</h3></div></div></div><p id="x_62d"><a name="x_62d"></a>The <span class="command"><strong>hg strip</strong></span> command
removes a revision, and all of its descendants, from the
repository. It undoes the effects of the removed revisions
from the repository, and updates the working directory to the
first parent of the removed revision.</p><p id="x_62e"><a name="x_62e"></a>The <span class="command"><strong>hg strip</strong></span> command
saves a backup of the removed changesets in a bundle, so that
they can be reapplied if removed in error.</p><p id="x_62f"><a name="x_62f"></a>Options:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_630"><a name="x_630"></a><code class="option">-b</code>: Save
unrelated changesets that are intermixed with the stripped
changesets in the backup bundle.</p></li><li><p id="x_631"><a name="x_631"></a><code class="option">-f</code>: If a
branch has multiple heads, remove all heads.</p></li><li><p id="x_632"><a name="x_632"></a><code class="option">-n</code>: Do
not save a backup bundle.</p></li></ul></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id446370">MQ file reference</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446375">The <code class="filename">series</code>
file</h3></div></div></div><p id="x_633"><a name="x_633"></a>The <code class="filename">series</code> file
contains a list of the names of all patches that MQ can apply.
It is represented as a list of names, with one name saved per
line. Leading and trailing white space in each line are
ignored.</p><p id="x_634"><a name="x_634"></a>Lines may contain comments. A comment begins with the
<span class="quote"><code class="literal">#</code></span>” character, and extends to
the end of the line. Empty lines, and lines that contain only
comments, are ignored.</p><p id="x_635"><a name="x_635"></a>You will often need to edit the <code class="filename">series</code> file by hand, hence the
support for comments and empty lines noted above. For
example, you can comment out a patch temporarily, and <span class="command"><strong>qpush</strong></span> will skip over that patch
when applying patches. You can also change the order in which
patches are applied by reordering their entries in the
<code class="filename">series</code> file.</p><p id="x_636"><a name="x_636"></a>Placing the <code class="filename">series</code>
file under revision control is also supported; it is a good
idea to place all of the patches that it refers to under
revision control, as well. If you create a patch directory
using the <code class="option">-c</code>
option to <span class="command"><strong>qinit</strong></span>, this will
be done for you automatically.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id446487">The <code class="filename">status</code>
file</h3></div></div></div><p id="x_637"><a name="x_637"></a>The <code class="filename">status</code> file
contains the names and changeset hashes of all patches that MQ
currently has applied. Unlike the <code class="filename">series</code> file, this file is not
intended for editing. You should not place this file under
revision control, or modify it in any way. It is used by MQ
strictly for internal book-keeping.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="migrating-to-mercurial.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="installing-mercurial-from-source.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Appendix A. Migrating to Mercurial </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix C. Installing Mercurial from source</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,221 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Appendix A. Migrating to Mercurial</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="adding-functionality-with-extensions.html" title="Chapter 14. Adding functionality with extensions"><link rel="next" href="mercurial-queues-reference.html" title="Appendix B. Mercurial Queues reference"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix A. Migrating to Mercurial</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="adding-functionality-with-extensions.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="mercurial-queues-reference.html">Next</a></td></tr></table></div><div class="appendix" lang="en" id="svn"><div class="titlepage"><div><div><h2 class="title">Appendix A. Migrating to Mercurial</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="migrating-to-mercurial.html#id441179">Importing history from another system</a></span></dt><dd><dl><dt><span class="sect2"><a href="migrating-to-mercurial.html#id441710">Converting multiple branches</a></span></dt><dt><span class="sect2"><a href="migrating-to-mercurial.html#id441801">Mapping user names</a></span></dt><dt><span class="sect2"><a href="migrating-to-mercurial.html#svn.filemap">Tidying up the tree</a></span></dt><dt><span class="sect2"><a href="migrating-to-mercurial.html#id441972">Improving Subversion conversion performance</a></span></dt></dl></dd><dt><span class="sect1"><a href="migrating-to-mercurial.html#id442205">Migrating from Subversion</a></span></dt><dd><dl><dt><span class="sect2"><a href="migrating-to-mercurial.html#id442221">Philosophical differences</a></span></dt><dd><dl><dt><span class="sect3"><a href="migrating-to-mercurial.html#id442247">Scope of commands</a></span></dt><dt><span class="sect3"><a href="migrating-to-mercurial.html#id442299">Multi-user operation and safety</a></span></dt><dt><span class="sect3"><a href="migrating-to-mercurial.html#id442339">Published vs local changes</a></span></dt></dl></dd><dt><span class="sect2"><a href="migrating-to-mercurial.html#id442397">Quick reference</a></span></dt></dl></dd><dt><span class="sect1"><a href="migrating-to-mercurial.html#id442924">Useful tips for newcomers</a></span></dt></dl></div><p id="x_6e1"><a name="x_6e1"></a>A common way to test the waters with a new revision control
tool is to experiment with switching an existing project, rather
than starting a new project from scratch.</p><p id="x_6e2"><a name="x_6e2"></a>In this appendix, we discuss how to import a project's history
into Mercurial, and what to look out for if you are used to a
different revision control system.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id441179">Importing history from another system</h2></div></div></div><p id="x_6e3"><a name="x_6e3"></a>Mercurial ships with an extension named
<code class="literal">convert</code>, which can import project history
from most popular revision control systems. At the time this
book was written, it could import history from the following
systems:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_6e4"><a name="x_6e4"></a>Subversion</p></li><li><p id="x_6e5"><a name="x_6e5"></a>CVS</p></li><li><p id="x_6e6"><a name="x_6e6"></a>git</p></li><li><p id="x_6e7"><a name="x_6e7"></a>Darcs</p></li><li><p id="x_6e8"><a name="x_6e8"></a>Bazaar</p></li><li><p id="x_6e9"><a name="x_6e9"></a>Monotone</p></li><li><p id="x_6ea"><a name="x_6ea"></a>GNU Arch</p></li><li><p id="x_6eb"><a name="x_6eb"></a>Mercurial</p></li></ul></div><p id="x_6ec"><a name="x_6ec"></a>(To see why Mercurial itself is supported as a source, see
<a class="xref" href="migrating-to-mercurial.html#svn.filemap" title="Tidying up the tree">the section called “Tidying up the tree”</a>.)</p><p id="x_6ed"><a name="x_6ed"></a>You can enable the extension in the usual way, by editing
your <code class="filename">~/.hgrc</code> file.</p><pre id="id441625" class="programlisting">[extensions]
convert =</pre><p id="x_6ee"><a name="x_6ee"></a>This will make a <span class="command"><strong>hg convert</strong></span> command
available. The command is easy to use. For instance, this
command will import the Subversion history for the Nose unit
testing framework into Mercurial.</p><pre id="id441645" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg convert http://python-nose.googlecode.com/svn/trunk</code></strong></pre><p id="x_6ef"><a name="x_6ef"></a>The <code class="literal">convert</code> extension operates
incrementally. In other words, after you have run <span class="command"><strong>hg
convert</strong></span> once, running it again will import any new
revisions committed after the first run began. Incremental
conversion will only work if you run <span class="command"><strong>hg
convert</strong></span> in the same Mercurial repository that you
originally used, because the <code class="literal">convert</code>
extension saves some private metadata in a
non-revision-controlled file named
<code class="filename">.hg/shamap</code> inside the target
repository.</p><p id="x_707"><a name="x_707"></a>When you want to start making changes using Mercurial, it's
best to clone the tree in which you are doing your conversions,
and leave the original tree for future incremental conversions.
This is the safest way to let you pull and merge future commits
from the source revision control system into your newly active
Mercurial project.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id441710">Converting multiple branches</h3></div></div></div><p id="x_708"><a name="x_708"></a>The <span class="command"><strong>hg convert</strong></span> command given above
converts only the history of the <code class="literal">trunk</code>
branch of the Subversion repository. If we instead use the
URL <code class="literal">http://python-nose.googlecode.com/svn</code>,
Mercurial will automatically detect the
<code class="literal">trunk</code>, <code class="literal">tags</code> and
<code class="literal">branches</code> layout that Subversion projects
usually use, and it will import each as a separate Mercurial
branch.</p><p id="x_709"><a name="x_709"></a>By default, each Subversion branch imported into Mercurial
is given a branch name. After the conversion completes, you
can get a list of the active branch names in the Mercurial
repository using <span class="command"><strong>hg branches -a</strong></span>. If you
would prefer to import the Subversion branches without names,
pass the <code class="option">--config
convert.hg.usebranchnames=false</code> option to
<span class="command"><strong>hg convert</strong></span>.</p><p id="x_70a"><a name="x_70a"></a>Once you have converted your tree, if you want to follow
the usual Mercurial practice of working in a tree that
contains a single branch, you can clone that single branch
using <span class="command"><strong>hg clone -r mybranchname</strong></span>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id441801">Mapping user names</h3></div></div></div><p id="x_6f0"><a name="x_6f0"></a>Some revision control tools save only short usernames with
commits, and these can be difficult to interpret. The norm
with Mercurial is to save a committer's name and email
address, which is much more useful for talking to them after
the fact.</p><p id="x_6f1"><a name="x_6f1"></a>If you are converting a tree from a revision control
system that uses short names, you can map those names to
longer equivalents by passing a <code class="option">--authors</code>
option to <span class="command"><strong>hg convert</strong></span>. This option accepts
a file name that should contain entries of the following
form.</p><pre id="id441835" class="programlisting">arist = Aristotle &lt;aristotle@phil.example.gr&gt;
soc = Socrates &lt;socrates@phil.example.gr&gt;</pre><p id="x_6f2"><a name="x_6f2"></a>Whenever <code class="literal">convert</code> encounters a commit
with the username <code class="literal">arist</code> in the source
repository, it will use the name <code class="literal">Aristotle
&lt;aristotle@phil.example.gr&gt;</code> in the converted
Mercurial revision. If no match is found for a name, it is
used verbatim.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="svn.filemap">Tidying up the tree</h3></div></div></div><p id="x_6f3"><a name="x_6f3"></a>Not all projects have pristine history. There may be a
directory that should never have been checked in, a file that
is too big, or a whole hierarchy that needs to be
refactored.</p><p id="x_6f4"><a name="x_6f4"></a>The <code class="literal">convert</code> extension supports the idea
of a “<span class="quote">file map</span>” that can reorganize the files and
directories in a project as it imports the project's history.
This is useful not only when importing history from other
revision control systems, but also to prune or refactor a
Mercurial tree.</p><p id="x_6f5"><a name="x_6f5"></a>To specify a file map, use the <code class="option">--filemap</code>
option and supply a file name. A file map contains lines of the
following forms.</p><pre id="id441918" class="programlisting"># This is a comment.
# Empty lines are ignored.
include path/to/file
exclude path/to/file
rename from/some/path to/some/other/place
</pre><p id="x_6f6"><a name="x_6f6"></a>The <code class="literal">include</code> directive causes a file, or
all files under a directory, to be included in the destination
repository. This also excludes all other files and dirs not
explicitely included. The <code class="literal">exclude</code>
directive causes files or directories to be omitted, and
others not explicitly mentioned to be included.</p><p id="x_6f7"><a name="x_6f7"></a>To move a file or directory from one location to another,
use the <code class="literal">rename</code> directive. If you need to
move a file or directory from a subdirectory into the root of
the repository, use <code class="literal">.</code> as the second
argument to the <code class="literal">rename</code> directive.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id441972">Improving Subversion conversion performance</h3></div></div></div><p id="x_70b"><a name="x_70b"></a>You will often need several attempts before you hit the
perfect combination of user map, file map, and other
conversion parameters. Converting a Subversion repository
over an access protocol like <code class="literal">ssh</code> or
<code class="literal">http</code> can proceed thousands of times more
slowly than Mercurial is capable of actually operating, due to
network delays. This can make tuning that perfect conversion
recipe very painful.</p><p id="x_70c"><a name="x_70c"></a>The <a class="ulink" href="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt" target="_top"><span class="command"><strong>svnsync</strong></span></a>
command can greatly speed up the conversion of a Subversion
repository. It is a read-only mirroring program for
Subversion repositories. The idea is that you create a local
mirror of your Subversion tree, then convert the mirror into a
Mercurial repository.</p><p id="x_70d"><a name="x_70d"></a>Suppose we want to convert the Subversion repository for
the popular Memcached project into a Mercurial tree. First,
we create a local Subversion repository.</p><pre id="id442028" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>svnadmin create memcached-mirror</code></strong></pre><p id="x_70e"><a name="x_70e"></a>Next, we set up a Subversion hook that
<span class="command"><strong>svnsync</strong></span> needs.</p><pre id="id442056" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo '#!/bin/sh' &gt; memcached-mirror/hooks/pre-revprop-change</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>chmod +x memcached-mirror/hooks/pre-revprop-change</code></strong></pre><p id="x_70f"><a name="x_70f"></a>We then initialize <span class="command"><strong>svnsync</strong></span> in this
repository.</p><pre id="id442096" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>svnsync --init file://`pwd`/memcached-mirror \
http://code.sixapart.com/svn/memcached</code></strong></pre><p id="x_710"><a name="x_710"></a>Our next step is to begin the <span class="command"><strong>svnsync</strong></span>
mirroring process.</p><pre id="id442124" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>svnsync sync file://`pwd`/memcached-mirror</code></strong></pre><p id="x_711"><a name="x_711"></a>Finally, we import the history of our local Subversion
mirror into Mercurial.</p><pre id="id442146" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg convert memcached-mirror</code></strong></pre><p id="x_712"><a name="x_712"></a>We can use this process incrementally if the Subversion
repository is still in use. We run <span class="command"><strong>svnsync</strong></span>
to pull new changes into our mirror, then <span class="command"><strong>hg
convert</strong></span> to import them into our Mercurial
tree.</p><p id="x_713"><a name="x_713"></a>There are two advantages to doing a two-stage import with
<span class="command"><strong>svnsync</strong></span>. The first is that it uses more
efficient Subversion network syncing code than <span class="command"><strong>hg
convert</strong></span>, so it transfers less data over the
network. The second is that the import from a local
Subversion tree is so fast that you can tweak your conversion
setup repeatedly without having to sit through a painfully
slow network-based conversion process each time.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id442205">Migrating from Subversion</h2></div></div></div><p id="x_6f8"><a name="x_6f8"></a>Subversion is currently the most popular open source
revision control system. Although there are many differences
between Mercurial and Subversion, making the transition from
Subversion to Mercurial is not particularly difficult. The two
have similar command sets and generally uniform
interfaces.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id442221">Philosophical differences</h3></div></div></div><p id="x_6f9"><a name="x_6f9"></a>The fundamental difference between Subversion and
Mercurial is of course that Subversion is centralized, while
Mercurial is distributed. Since Mercurial stores all of a
project's history on your local drive, it only needs to
perform a network access when you want to explicitly
communicate with another repository. In contrast, Subversion
stores very little information locally, and the client must
thus contact its server for many common operations.</p><p id="x_6fa"><a name="x_6fa"></a>Subversion more or less gets away without a well-defined
notion of a branch: which portion of a server's namespace
qualifies as a branch is a matter of convention, with the
software providing no enforcement. Mercurial treats a
repository as the unit of branch management.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id442247">Scope of commands</h4></div></div></div><p id="x_6fb"><a name="x_6fb"></a>Since Subversion doesn't know what parts of its
namespace are really branches, it treats most commands as
requests to operate at and below whatever directory you are
currently visiting. For instance, if you run <span class="command"><strong>svn
log</strong></span>, you'll get the history of whatever part of
the tree you're looking at, not the tree as a whole.</p><p id="x_6fc"><a name="x_6fc"></a>Mercurial's commands behave differently, by defaulting
to operating over an entire repository. Run <span class="command"><strong>hg
log</strong></span> and it will tell you the history of the
entire tree, no matter what part of the working directory
you're visiting at the time. If you want the history of
just a particular file or directory, simply supply it by
name, e.g. <span class="command"><strong>hg log src</strong></span>.</p><p id="x_6fd"><a name="x_6fd"></a>From my own experience, this difference in default
behaviors is probably the most likely to trip you up if you
have to switch back and forth frequently between the two
tools.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id442299">Multi-user operation and safety</h4></div></div></div><p id="x_6fe"><a name="x_6fe"></a>With Subversion, it is normal (though slightly frowned
upon) for multiple people to collaborate in a single branch.
If Alice and Bob are working together, and Alice commits
some changes to their shared branch, Bob must update his
client's view of the branch before he can commit. Since at
this time he has no permanent record of the changes he has
made, he can corrupt or lose his modifications during and
after his update.</p><p id="x_6ff"><a name="x_6ff"></a>Mercurial encourages a commit-then-merge model instead.
Bob commits his changes locally before pulling changes from,
or pushing them to, the server that he shares with Alice.
If Alice pushed her changes before Bob tries to push his, he
will not be able to push his changes until he pulls hers,
merges with them, and commits the result of the merge. If
he makes a mistake during the merge, he still has the option
of reverting to the commit that recorded his changes.</p><p id="x_700"><a name="x_700"></a>It is worth emphasizing that these are the common ways
of working with these tools. Subversion supports a safer
work-in-your-own-branch model, but it is cumbersome enough
in practice to not be widely used. Mercurial can support
the less safe mode of allowing changes to be pulled in and
merged on top of uncommitted edits, but this is considered
highly unusual.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id442339">Published vs local changes</h4></div></div></div><p id="x_701"><a name="x_701"></a>A Subversion <span class="command"><strong>svn commit</strong></span> command
immediately publishes changes to a server, where they can be
seen by everyone who has read access.</p><p id="x_702"><a name="x_702"></a>With Mercurial, commits are always local, and must be
published via a <span class="command"><strong>hg push</strong></span> command
afterwards.</p><p id="x_703"><a name="x_703"></a>Each approach has its advantages and disadvantages. The
Subversion model means that changes are published, and hence
reviewable and usable, immediately. On the other hand, this
means that a user must have commit access to a repository in
order to use the software in a normal way, and commit access
is not lightly given out by most open source
projects.</p><p id="x_704"><a name="x_704"></a>The Mercurial approach allows anyone who can clone a
repository to commit changes without the need for someone
else's permission, and they can then publish their changes
and continue to participate however they see fit. The
distinction between committing and pushing does open up the
possibility of someone committing changes to their laptop
and walking away for a few days having forgotten to push
them, which in rare cases might leave collaborators
temporarily stuck.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id442397">Quick reference</h3></div></div></div><div class="table"><a name="id442402"></a><p class="title"><b>Table A.1. Subversion commands and Mercurial equivalents</b></p><div class="table-contents"><table summary="Subversion commands and Mercurial equivalents" border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Subversion</th><th>Mercurial</th><th>Notes</th></tr></thead><tbody><tr><td><span class="command"><strong>svn add</strong></span></td><td><span class="command"><strong>hg add</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn blame</strong></span></td><td><span class="command"><strong>hg annotate</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn cat</strong></span></td><td><span class="command"><strong>hg cat</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn checkout</strong></span></td><td><span class="command"><strong>hg clone</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn cleanup</strong></span></td><td>n/a</td><td>No cleanup needed</td></tr><tr><td><span class="command"><strong>svn commit</strong></span></td><td><span class="command"><strong>hg commit</strong></span>; <span class="command"><strong>hg
push</strong></span></td><td><span class="command"><strong>hg push</strong></span> publishes after
commit</td></tr><tr><td><span class="command"><strong>svn copy</strong></span></td><td><span class="command"><strong>hg clone</strong></span></td><td>To create a new branch</td></tr><tr><td><span class="command"><strong>svn copy</strong></span></td><td><span class="command"><strong>hg copy</strong></span></td><td>To copy files or directories</td></tr><tr><td><span class="command"><strong>svn delete</strong></span> (<span class="command"><strong>svn
remove</strong></span>)</td><td><span class="command"><strong>hg remove</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn diff</strong></span></td><td><span class="command"><strong>hg diff</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn export</strong></span></td><td><span class="command"><strong>hg archive</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn help</strong></span></td><td><span class="command"><strong>hg help</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn import</strong></span></td><td><span class="command"><strong>hg addremove</strong></span>; <span class="command"><strong>hg
commit</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn info</strong></span></td><td><span class="command"><strong>hg parents</strong></span></td><td>Shows what revision is checked out</td></tr><tr><td><span class="command"><strong>svn info</strong></span></td><td><span class="command"><strong>hg showconfig
paths.parent</strong></span></td><td>Shows what URL is checked out</td></tr><tr><td><span class="command"><strong>svn list</strong></span></td><td><span class="command"><strong>hg manifest</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn log</strong></span></td><td><span class="command"><strong>hg log</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn merge</strong></span></td><td><span class="command"><strong>hg merge</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn mkdir</strong></span></td><td>n/a</td><td>Mercurial does not track directories</td></tr><tr><td><span class="command"><strong>svn move</strong></span> (<span class="command"><strong>svn
rename</strong></span>)</td><td><span class="command"><strong>hg rename</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn resolved</strong></span></td><td><span class="command"><strong>hg resolve -m</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn revert</strong></span></td><td><span class="command"><strong>hg revert</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn status</strong></span></td><td><span class="command"><strong>hg status</strong></span></td><td> </td></tr><tr><td><span class="command"><strong>svn update</strong></span></td><td><span class="command"><strong>hg pull -u</strong></span></td><td> </td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id442924">Useful tips for newcomers</h2></div></div></div><p id="x_705"><a name="x_705"></a>Under some revision control systems, printing a diff for a
single committed revision can be painful. For instance, with
Subversion, to see what changed in revision 104654, you must
type <span class="command"><strong>svn diff -r104653:104654</strong></span>. Mercurial
eliminates the need to type the revision ID twice in this common
case. For a plain diff, <span class="command"><strong>hg export 104654</strong></span>. For
a log message followed by a diff, <span class="command"><strong>hg log -r104654
-p</strong></span>.</p><p id="x_706"><a name="x_706"></a>When you run <span class="command"><strong>hg status</strong></span> without any
arguments, it prints the status of the entire tree, with paths
relative to the root of the repository. This makes it tricky to
copy a file name from the output of <span class="command"><strong>hg status</strong></span>
into the command line. If you supply a file or directory name
to <span class="command"><strong>hg status</strong></span>, it will print paths relative to
your current location instead. So to get tree-wide status from
<span class="command"><strong>hg status</strong></span>, with paths that are relative to
your current directory and not the root of the repository, feed
the output of <span class="command"><strong>hg root</strong></span> into <span class="command"><strong>hg
status</strong></span>. You can easily do this as follows on a
Unix-like system:</p><pre id="id443005" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status `hg root`</code></strong></pre></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="adding-functionality-with-extensions.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="mercurial-queues-reference.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 14. Adding functionality with extensions </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix B. Mercurial Queues reference</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

View File

@ -0,0 +1,89 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Appendix D. Open Publication License</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="installing-mercurial-from-source.html" title="Appendix C. Installing Mercurial from source"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix D. Open Publication License</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="installing-mercurial-from-source.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table></div><div class="appendix" lang="en" id="cha:opl"><div class="titlepage"><div><div><h2 class="title">Appendix D. Open Publication License</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="open-publication-license.html#id448273">Requirements on both unmodified and modified
versions</a></span></dt><dt><span class="sect1"><a href="open-publication-license.html#id448880">Copyright</a></span></dt><dt><span class="sect1"><a href="open-publication-license.html#id448894">Scope of license</a></span></dt><dt><span class="sect1"><a href="open-publication-license.html#id448948">Requirements on modified works</a></span></dt><dt><span class="sect1"><a href="open-publication-license.html#id449019">Good-practice recommendations</a></span></dt><dt><span class="sect1"><a href="open-publication-license.html#sec:opl:options">License options</a></span></dt></dl></div><p id="x_638"><a name="x_638"></a>Version 1.0, 8 June 1999</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id448273">Requirements on both unmodified and modified
versions</h2></div></div></div><p id="x_639"><a name="x_639"></a>The Open Publication works may be reproduced and distributed
in whole or in part, in any medium physical or electronic,
provided that the terms of this license are adhered to, and that
this license or an incorporation of it by reference (with any
options elected by the author(s) and/or publisher) is displayed
in the reproduction.</p><p id="x_63a"><a name="x_63a"></a>Proper form for an incorporation by reference is as
follows:</p><div class="blockquote"><blockquote class="blockquote"><p id="x_63b"><a name="x_63b"></a> Copyright (c) <span class="emphasis"><em>year</em></span> by
<span class="emphasis"><em>author's name or designee</em></span>. This material
may be distributed only subject to the terms and conditions
set forth in the Open Publication License,
v<span class="emphasis"><em>x.y</em></span> or later (the latest version is
presently available at <a class="ulink" href="http://www.opencontent.org/openpub/" target="_top">http://www.opencontent.org/openpub/</a>).</p></blockquote></div><p id="x_63c"><a name="x_63c"></a>The reference must be immediately followed with any options
elected by the author(s) and/or publisher of the document (see
<a class="xref" href="open-publication-license.html#sec:opl:options" title="License options">the section called “License options”</a>).</p><p id="x_63d"><a name="x_63d"></a>Commercial redistribution of Open Publication-licensed
material is permitted.</p><p id="x_63e"><a name="x_63e"></a>Any publication in standard (paper) book form shall require
the citation of the original publisher and author. The publisher
and author's names shall appear on all outer surfaces of the
book. On all outer surfaces of the book the original publisher's
name shall be as large as the title of the work and cited as
possessive with respect to the title.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id448880">Copyright</h2></div></div></div><p id="x_63f"><a name="x_63f"></a>The copyright to each Open Publication is owned by its
author(s) or designee.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id448894">Scope of license</h2></div></div></div><p id="x_640"><a name="x_640"></a>The following license terms apply to all Open Publication
works, unless otherwise explicitly stated in the
document.</p><p id="x_641"><a name="x_641"></a>Mere aggregation of Open Publication works or a portion of
an Open Publication work with other works or programs on the
same media shall not cause this license to apply to those other
works. The aggregate work shall contain a notice specifying the
inclusion of the Open Publication material and appropriate
copyright notice.</p><p id="x_642"><a name="x_642"></a><span class="bold"><strong>Severability</strong></span>. If any part
of this license is found to be unenforceable in any
jurisdiction, the remaining portions of the license remain in
force.</p><p id="x_643"><a name="x_643"></a><span class="bold"><strong>No warranty</strong></span>. Open
Publication works are licensed and provided “<span class="quote">as is</span>
without warranty of any kind, express or implied, including, but
not limited to, the implied warranties of merchantability and
fitness for a particular purpose or a warranty of
non-infringement.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id448948">Requirements on modified works</h2></div></div></div><p id="x_644"><a name="x_644"></a>All modified versions of documents covered by this license,
including translations, anthologies, compilations and partial
documents, must meet the following requirements:</p><div class="orderedlist"><ol type="1"><li><p id="x_645"><a name="x_645"></a>The modified version must be labeled as
such.</p></li><li><p id="x_646"><a name="x_646"></a>The person making the modifications must be
identified and the modifications dated.</p></li><li><p id="x_647"><a name="x_647"></a>Acknowledgement of the original author and
publisher if applicable must be retained according to normal
academic citation practices.</p></li><li><p id="x_648"><a name="x_648"></a>The location of the original unmodified document
must be identified.</p></li><li><p id="x_649"><a name="x_649"></a>The original author's (or authors') name(s) may
not be used to assert or imply endorsement of the resulting
document without the original author's (or authors')
permission.</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id449019">Good-practice recommendations</h2></div></div></div><p id="x_64a"><a name="x_64a"></a>In addition to the requirements of this license, it is
requested from and strongly recommended of redistributors
that:</p><div class="orderedlist"><ol type="1"><li><p id="x_64b"><a name="x_64b"></a>If you are distributing Open Publication works
on hardcopy or CD-ROM, you provide email notification to the
authors of your intent to redistribute at least thirty days
before your manuscript or media freeze, to give the authors
time to provide updated documents. This notification should
describe modifications, if any, made to the document.</p></li><li><p id="x_64c"><a name="x_64c"></a>All substantive modifications (including
deletions) be either clearly marked up in the document or
else described in an attachment to the document.</p></li><li><p id="x_64d"><a name="x_64d"></a>Finally, while it is not mandatory under this
license, it is considered good form to offer a free copy of
any hardcopy and CD-ROM expression of an Open
Publication-licensed work to its author(s).</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:opl:options">License options</h2></div></div></div><p id="x_64e"><a name="x_64e"></a>The author(s) and/or publisher of an Open
Publication-licensed document may elect certain options by
appending language to the reference to or copy of the license.
These options are considered part of the license instance and
must be included with the license (or its incorporation by
reference) in derived works.</p><div class="orderedlist"><ol type="1"><li><p id="x_64f"><a name="x_64f"></a>To prohibit distribution of substantively
modified versions without the explicit permission of the
author(s). “<span class="quote">Substantive modification</span>” is
defined as a change to the semantic content of the document,
and excludes mere changes in format or typographical
corrections.</p></li><li><p id="x_650"><a name="x_650"></a> To accomplish this, add the phrase
<span class="quote">Distribution of substantively modified versions of
this document is prohibited without the explicit
permission of the copyright holder.</span>” to the license
reference or copy.</p></li><li><p id="x_651"><a name="x_651"></a>To prohibit any publication of this work or
derivative works in whole or in part in standard (paper)
book form for commercial purposes is prohibited unless prior
permission is obtained from the copyright holder.</p></li><li><p id="x_652"><a name="x_652"></a>To accomplish this, add the phrase
<span class="quote">Distribution of the work or derivative of the work in
any standard (paper) book form is prohibited unless prior
permission is obtained from the copyright holder.</span>
to the license reference or copy.</p></li></ol></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="installing-mercurial-from-source.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">Appendix C. Installing Mercurial from source </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>

112
read/preface.html Normal file
View File

@ -0,0 +1,112 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Preface</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="index.html" title="Mercurial: The Definitive Guide"><link rel="next" href="how-did-we-get-here.html" title="Chapter 1. How did we get here?"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Preface</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="how-did-we-get-here.html">Next</a></td></tr></table></div><div class="preface" lang="en" id="chap:preface"><div class="titlepage"><div><div><h2 class="title">Preface</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="preface.html#id321829">Technical storytelling</a></span></dt><dt><span class="sect1"><a href="preface.html#id330285">Thank you for supporting Mercurial</a></span></dt><dt><span class="sect1"><a href="preface.html#id296114">Acknowledgments</a></span></dt><dt><span class="sect1"><a href="preface.html#id298254">Conventions Used in This Book</a></span></dt><dt><span class="sect1"><a href="preface.html#id341884">Using Code Examples</a></span></dt><dt><span class="sect1"><a href="preface.html#id297605">Safari® Books Online</a></span></dt><dt><span class="sect1"><a href="preface.html#id297646">How to Contact Us</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id321829">Technical storytelling</h2></div></div></div><p id="x_72e"><a name="x_72e"></a>A few years ago, when I wanted to explain why I believed
that distributed revision control is important, the field was
then so new that there was almost no published literature to
refer people to.</p><p id="x_72f"><a name="x_72f"></a>Although at that time I spent some time working on the
internals of Mercurial itself, I switched to writing this book
because that seemed like the most effective way to help the
software to reach a wide audience, along with the idea that
revision control ought to be distributed in nature. I publish
the book online under a liberal license for the same
reason: to get the word out.</p><p id="x_730"><a name="x_730"></a>There's a familiar rhythm to a good software book that
closely resembles telling a story: What is this thing? Why does
it matter? How will it help me? How do I use it? In this
book, I try to answer those questions for distributed revision
control in general, and for Mercurial in particular.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id330285">Thank you for supporting Mercurial</h2></div></div></div><p id="x_731"><a name="x_731"></a>By purchasing a copy of this book, you are supporting the
continued development and freedom of Mercurial in particular,
and of open source and free software in general. O'Reilly Media
and I are donating my royalties on the sales of this book to the
Software Freedom Conservancy (<a class="ulink" href="http://www.softwarefreedom.org/" target="_top">http://www.softwarefreedom.org/</a>)
which provides clerical and legal support to Mercurial and a
number of other prominent and worthy open source software
projects.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id296114">Acknowledgments</h2></div></div></div><p id="x_732"><a name="x_732"></a>This book would not exist were it not for the efforts of
Matt Mackall, the author and project lead of Mercurial. He is
ably assisted by hundreds of volunteer contributors across the
world.</p><p id="x_733"><a name="x_733"></a>My children, Cian and Ruairi, always stood ready to help me
to unwind with wonderful, madcap little-boy games. I'd also
like to thank my ex-wife, Shannon, for her support.</p><p id="x_734"><a name="x_734"></a>My colleagues and friends provided help and support in
innumerable ways. This list of people is necessarily very
incomplete: Stephen Hahn, Karyn Ritter, Bonnie Corwin, James
Vasile, Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh,
Jeremy Fitzhardinge, Rachel Chalmers.</p><p id="x_735"><a name="x_735"></a>I developed this book in the open, posting drafts of
chapters to the book web site as I completed them. Readers then
submitted feedback using a web application that I developed. By
the time I finished writing the book, more than 100 people had
submitted comments, an amazing number considering that the
comment system was live for only about two months towards the
end of the writing process.</p><p id="x_736"><a name="x_736"></a>I would particularly like to recognize the following people,
who between them contributed over a third of the total number of
comments. I would like to thank them for their care and effort
in providing so much detailed feedback.</p><p id="x_737"><a name="x_737"></a>Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe,
Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der
Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon
Parise.</p><p id="x_738"><a name="x_738"></a>I also want to acknowledge the help of the many people who
caught errors and provided helpful suggestions throughout the
book.</p><p id="x_739"><a name="x_739"></a>Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan
Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric
Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan
Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted
Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned
Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph
Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris,
Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen,
David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry
Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger,
Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav
Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli,
Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser,
Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry,
Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák,
Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord
Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan
Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers,
Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan
Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz
Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam,
Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot,
Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez,
Ahmed Chaudhary.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id298254">Conventions Used in This Book</h2></div></div></div><p id="x_73a"><a name="x_73a"></a>The following typographical conventions are used in this
book:</p><div class="variablelist"><dl><dt><span class="term">Italic</span></dt><dd><p id="x_73b"><a name="x_73b"></a>Indicates new terms, URLs, email addresses, filenames,
and file extensions.</p></dd><dt><span class="term"><code class="literal">Constant width</code></span></dt><dd><p id="x_73c"><a name="x_73c"></a>Used for program listings, as well as within
paragraphs to refer to program elements such as variable
or function names, databases, data types, environment
variables, statements, and keywords.</p></dd><dt><span class="term"><strong class="userinput"><code>Constant width bold</code></strong></span></dt><dd><p id="x_73d"><a name="x_73d"></a>Shows commands or other text that should be typed
literally by the user.</p></dd><dt><span class="term"><em class="replaceable"><code>Constant width italic</code></em></span></dt><dd><p id="x_73e"><a name="x_73e"></a>Shows text that should be replaced with user-supplied
values or by values determined by context.</p></dd></dl></div><div class="tip"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p id="x_73f"><a name="x_73f"></a>This icon signifies a tip, suggestion, or general
note.</p></td></tr></table></div><div class="caution"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="/support/figs/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p id="x_740"><a name="x_740"></a>This icon indicates a warning or caution.</p></td></tr></table></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id341884">Using Code Examples</h2></div></div></div><p id="x_741"><a name="x_741"></a>This book is here to help you get your job done. In general,
you may use the code in this book in your programs and
documentation. You do not need to contact us for permission
unless youre reproducing a significant portion of the code. For
example, writing a program that uses several chunks of code from
this book does not require permission. Selling or distributing a
CD-ROM of examples from OReilly books does require permission.
Answering a question by citing this book and quoting example
code does not require permission. Incorporating a significant
amount of example code from this book into your products
documentation does require permission.</p><p id="x_742"><a name="x_742"></a>We appreciate, but do not require, attribution. An
attribution usually includes the title, author, publisher, and
ISBN. For example: “<span class="emphasis"><em>Book Title</em></span> by Some
Author. Copyright 2008 OReilly Media, Inc.,
978-0-596-xxxx-x.”</p><p id="x_743"><a name="x_743"></a>If you feel your use of code examples falls outside fair use
or the permission given above, feel free to contact us at
<code class="email">&lt;<a class="email" href="mailto:permissions@oreilly.com">permissions@oreilly.com</a>&gt;</code>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id297605">Safari® Books Online</h2></div></div></div><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_744"><a name="x_744"></a>When you see a Safari® Books Online icon on the cover of
your favorite technology book, that means the book is
available online through the OReilly Network Safari
Bookshelf.</p></td></tr></table></div><p id="x_745"><a name="x_745"></a>Safari offers a solution thats better than e-books. Its a
virtual library that lets you easily search thousands of top
tech books, cut and paste code samples, download chapters, and
find quick answers when you need the most accurate, current
information. Try it for free at <a class="ulink" href="http://my.safaribooksonline.com/?portal=oreilly" target="_top">http://my.safaribooksonline.com</a>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id297646">How to Contact Us</h2></div></div></div><p id="x_746"><a name="x_746"></a>Please address comments and questions concerning this book
to the publisher:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>OReilly Media, Inc.</td></tr><tr><td>1005 Gravenstein Highway North</td></tr><tr><td>Sebastopol, CA 95472</td></tr><tr><td>800-998-9938 (in the United States or Canada)</td></tr><tr><td>707-829-0515 (international or local)</td></tr><tr><td>707 829-0104 (fax)</td></tr></table><p id="x_747"><a name="x_747"></a>We have a web page for this book, where we list errata,
examples, and any additional information. You can access this
page at:</p><table class="simplelist" border="0" summary="Simple list"><tr><td><a class="ulink" href="http://www.oreilly.com/catalog/&lt;catalog%20%20%20%20page&gt;" target="_top">http://www.oreilly.com/catalog/&lt;catalog page&gt;</a></td></tr></table><p class="remark"><i><span class="remark">Dont forget to update the &lt;url&gt; attribute,
too.</span></i></p><p id="x_748"><a name="x_748"></a>To comment or ask technical questions about this book, send
email to:</p><table class="simplelist" border="0" summary="Simple list"><tr><td><code class="email">&lt;<a class="email" href="mailto:bookquestions@oreilly.com">bookquestions@oreilly.com</a>&gt;</code></td></tr></table><p id="x_749"><a name="x_749"></a>For more information about our books, conferences, Resource
Centers, and the OReilly Network, see our web site at:</p><table class="simplelist" border="0" summary="Simple list"><tr><td><a class="ulink" href="http://www.oreilly.com" target="_top">http://www.oreilly.com</a></td></tr></table></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="how-did-we-get-here.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Mercurial: The Definitive Guide </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 1. How did we get here?</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>