bos@559: <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
bos@559: 
bos@686: <appendix id="svn">
bos@687:   <?dbhtml filename="migrating-to-mercurial.html"?>
bos@686: <title>Migrating to Mercurial</title>
bos@686: 
bos@691:   <para id="x_6e1">A common way to test the waters with a new revision control
bos@686:     tool is to experiment with switching an existing project, rather
bos@686:     than starting a new project from scratch.</para>
bos@686: 
bos@691:   <para id="x_6e2">In this appendix, we discuss how to import a project's history
bos@686:     into Mercurial, and what to look out for if you are used to a
bos@686:     different revision control system.</para>
bos@686: 
bos@686:   <sect1>
bos@686:     <title>Importing history from another system</title>
bos@686: 
bos@691:     <para id="x_6e3">Mercurial ships with an extension named
bos@686:       <literal>convert</literal>, which can import project history
bos@686:       from most popular revision control systems.  At the time this
bos@686:       book was written, it could import history from the following
bos@686:       systems:</para>
bos@686:     <itemizedlist>
bos@686:       <listitem>
bos@691: 	<para id="x_6e4">Subversion</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6e5">CVS</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6e6">git</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6e7">Darcs</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6e8">Bazaar</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6e9">Monotone</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6ea">GNU Arch</para>
bos@691:       </listitem>
bos@691:       <listitem>
bos@691: 	<para id="x_6eb">Mercurial</para>
bos@686:       </listitem>
bos@686:     </itemizedlist>
bos@686: 
bos@691:     <para id="x_6ec">(To see why Mercurial itself is supported as a source, see
bos@686:       <xref linkend="svn.filemap"/>.)</para>
bos@686: 
bos@691:     <para id="x_6ed">You can enable the extension in the usual way, by editing
bos@686:       your <filename>~/.hgrc</filename> file.</para>
bos@686: 
bos@686:     <programlisting>[extensions]
bos@686: convert =</programlisting>
bos@686: 
bos@691:     <para id="x_6ee">This will make a <command>hg convert</command> command
bos@686:       available.  The command is easy to use.  For instance, this
bos@686:       command will import the Subversion history for the Nose unit
bos@686:       testing framework into Mercurial.</para>
bos@686: 
bos@686:     <screen><prompt>$</prompt> <userinput>hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen>
bos@686: 
bos@691:     <para id="x_6ef">The <literal>convert</literal> extension operates
bos@686:       incrementally.  In other words, after you have run <command>hg
bos@686: 	convert</command> once, running it again will import any new
bos@686:       revisions committed after the first run began.  Incremental
bos@686:       conversion will only work if you run <command>hg
bos@686: 	convert</command> in the same Mercurial repository that you
bos@686:       originally used, because the <literal>convert</literal>
bos@686:       extension saves some private metadata in a
bos@686:       non-revision-controlled file named
bos@686:       <filename>.hg/shamap</filename> inside the target
bos@686:       repository.</para>
bos@686: 
bos@693:     <para>When you want to start making changes using Mercurial, it's
bos@693:       best to clone the tree in which you are doing your conversions,
bos@693:       and leave the original tree for future incremental conversions.
bos@693:       This is the safest way to let you pull and merge future commits
bos@693:       from the source revision control system into your newly active
bos@693:       Mercurial project.</para>
bos@693: 
bos@693:     <sect2>
bos@693:       <title>Converting multiple branches</title>
bos@693: 
bos@693:       <para>The <command>hg convert</command> command given above
bos@693: 	converts only the history of the <literal>trunk</literal>
bos@693: 	branch of the Subversion repository.  If we instead use the
bos@693: 	URL <literal>http://python-nose.googlecode.com/svn</literal>,
bos@693: 	Mercurial will automatically detect the
bos@693: 	<literal>trunk</literal>, <literal>tags</literal> and
bos@693: 	<literal>branches</literal> layout that Subversion projects
bos@693: 	usually use, and it will import each as a separate Mercurial
bos@693: 	branch.</para>
bos@693: 
bos@693:       <para>By default, each Subversion branch imported into Mercurial
bos@693: 	is given a branch name.  After the conversion completes, you
bos@693: 	can get a list of the active branch names in the Mercurial
bos@693: 	repository using <command>hg branches -a</command>. If you
bos@693: 	would prefer to import the Subversion branches without names,
bos@693: 	pass the <option>--config
bos@693: 	  convert.hg.usebranchnames=false</option> option to
bos@693: 	<command>hg convert</command>.</para>
bos@693: 
bos@693:       <para>Once you have converted your tree, if you want to follow
bos@693: 	the usual Mercurial practice of working in a tree that
bos@693: 	contains a single branch, you can clone that single branch
bos@693: 	using <command>hg clone -r mybranchname</command>.</para>
bos@693:     </sect2>
bos@693: 
bos@686:     <sect2>
bos@686:       <title>Mapping user names</title>
bos@686: 
bos@691:       <para id="x_6f0">Some revision control tools save only short usernames with
bos@686: 	commits, and these can be difficult to interpret.  The norm
bos@686: 	with Mercurial is to save a committer's name and email
bos@686: 	address, which is much more useful for talking to them after
bos@686: 	the fact.</para>
bos@686: 
bos@691:       <para id="x_6f1">If you are converting a tree from a revision control
bos@686: 	system that uses short names, you can map those names to
bos@686: 	longer equivalents by passing a <option>--authors</option>
bos@686: 	option to <command>hg convert</command>.  This option accepts
bos@686: 	a file name that should contain entries of the following
bos@686: 	form.</para>
bos@686: 
bos@686:       <programlisting>arist = Aristotle &lt;aristotle@phil.example.gr&gt;
bos@686: soc = Socrates &lt;socrates@phil.example.gr&gt;</programlisting>
bos@686: 
bos@691:       <para id="x_6f2">Whenever <literal>convert</literal> encounters a commit
bos@686: 	with the username <literal>arist</literal> in the source
bos@686: 	repository, it will use the name <literal>Aristotle
bos@686: 	  &lt;aristotle@phil.example.gr&gt;</literal> in the converted
bos@686: 	Mercurial revision.  If no match is found for a name, it is
bos@686: 	used verbatim.</para>
bos@686:     </sect2>
bos@686: 
bos@686:     <sect2 id="svn.filemap">
bos@686:       <title>Tidying up the tree</title>
bos@686: 
bos@691:       <para id="x_6f3">Not all projects have pristine history.  There may be a
bos@686: 	directory that should never have been checked in, a file that
bos@686: 	is too big, or a whole hierarchy that needs to be
bos@686: 	refactored.</para>
bos@686: 
bos@691:       <para id="x_6f4">The <literal>convert</literal> extension supports the idea
bos@686: 	of a <quote>file map</quote> that can reorganize the files and
bos@686: 	directories in a project as it imports the project's history.
bos@686: 	This is useful not only when importing history from other
bos@686: 	revision control systems, but also to prune or refactor a
bos@686: 	Mercurial tree.</para>
bos@686: 
bos@691:       <para id="x_6f5">To specify a file map, use the <option>--filemap</option>
bos@686: 	option and supply a file name.  A file map contains lines of the
bos@686: 	following forms.</para>
bos@686: 
bos@686:       <programlisting># This is a comment.
bos@686: # Empty lines are ignored.	
bos@686: 
bos@686: include path/to/file
bos@686: 
bos@686: exclude path/to/file
bos@686: 
bos@686: rename from/some/path to/some/other/place
bos@686: </programlisting>
bos@686: 
bos@691:       <para id="x_6f6">The <literal>include</literal> directive causes a file, or
bos@686: 	all files under a directory, to be included in the destination
bos@686: 	repository.  This also excludes all other files and dirs not
bos@686: 	explicitely included.  The <literal>exclude</literal>
bos@686: 	directive causes files or directories to be omitted, and
bos@686: 	others not explicitly mentioned to be included.</para>
bos@686: 
bos@691:       <para id="x_6f7">To move a file or directory from one location to another,
bos@686: 	use the <literal>rename</literal> directive.  If you need to
bos@686: 	move a file or directory from a subdirectory into the root of
bos@686: 	the repository, use <literal>.</literal> as the second
bos@686: 	argument to the <literal>rename</literal> directive.</para>
bos@686:     </sect2>
bos@693: 
bos@693:     <sect2>
bos@693:       <title>Improving Subversion conversion performance</title>
bos@693: 
bos@693:       <para>You will often need several attempts before you hit the
bos@693: 	perfect combination of user map, file map, and other
bos@693: 	conversion parameters.  Converting a Subversion repository
bos@693: 	over an access protocol like <literal>ssh</literal> or
bos@693: 	<literal>http</literal> can proceed thousands of times more
bos@693: 	slowly than Mercurial is capable of actually operating, due to
bos@693: 	network delays.  This can make tuning that perfect conversion
bos@693: 	recipe very painful.</para>
bos@693: 
bos@693:       <para>The <ulink
bos@693: 	  url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command>svnsync</command></ulink> 
bos@693: 	command can greatly speed up the conversion of a Subversion
bos@693: 	repository.  It is a read-only mirroring program for
bos@693: 	Subversion repositories.  The idea is that you create a local
bos@693: 	mirror of your Subversion tree, then convert the mirror into a
bos@693: 	Mercurial repository.</para>
bos@693: 
bos@693:       <para>Suppose we want to convert the Subversion repository for
bos@693: 	the popular Memcached project into a Mercurial tree.  First,
bos@693: 	we create a local Subversion repository.</para>
bos@693: 
bos@693:       <screen><prompt>$</prompt> <userinput>svnadmin create memcached-mirror</userinput></screen>
bos@693: 
bos@693:       <para>Next, we set up a Subversion hook that
bos@693: 	<command>svnsync</command> needs.</para>
bos@693: 
bos@693:       <screen><prompt>$</prompt> <userinput>echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change</userinput>
bos@693: <prompt>$</prompt> <userinput>chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen>
bos@693: 
bos@693:       <para>We then initialize <command>svnsync</command> in this
bos@693: 	repository.</para>
bos@693: 
bos@693:       <screen><prompt>$</prompt> <userinput>svnsync --init file://`pwd`/memcached-mirror \
bos@693:   http://code.sixapart.com/svn/memcached</userinput></screen>
bos@693: 
bos@693:       <para>Our next step is to begin the <command>svnsync</command>
bos@693: 	mirroring process.</para>
bos@693: 
bos@693:       <screen><prompt>$</prompt> <userinput>svnsync sync file://`pwd`/memcached-mirror</userinput></screen>
bos@693: 
bos@693:       <para>Finally, we import the history of our local Subversion
bos@693: 	mirror into Mercurial.</para>
bos@693: 
bos@693:       <screen><prompt>$</prompt> <userinput>hg convert memcached-mirror</userinput></screen>
bos@693:       
bos@693:       <para>We can use this process incrementally if the Subversion
bos@693: 	repository is still in use.  We run <command>svnsync</command>
bos@693: 	to pull new changes into our mirror, then <command>hg
bos@693: 	  convert</command> to import them into our Mercurial
bos@693: 	tree.</para>
bos@693: 
bos@693:       <para>There are two advantages to doing a two-stage import with
bos@693: 	<command>svnsync</command>.  The first is that it uses more
bos@693: 	efficient Subversion network syncing code than <command>hg
bos@693: 	  convert</command>, so it transfers less data over the
bos@693: 	network.  The second is that the import from a local
bos@693: 	Subversion tree is so fast that you can tweak your conversion
bos@693: 	setup repeatedly without having to sit through a painfully
bos@693: 	slow network-based conversion process each time.</para>
bos@693:     </sect2>
bos@686:   </sect1>
bos@686: 
bos@686:   <sect1>
bos@686:     <title>Migrating from Subversion</title>
bos@686: 
bos@691:     <para id="x_6f8">Subversion is currently the most popular open source
bos@686:       revision control system. Although there are many differences
bos@686:       between Mercurial and Subversion, making the transition from
bos@686:       Subversion to Mercurial is not particularly difficult.  The two
bos@686:       have similar command sets and generally uniform
bos@686:       interfaces.</para>
bos@686: 
bos@686:     <sect2>
bos@686:       <title>Philosophical differences</title>
bos@686: 
bos@691:       <para id="x_6f9">The fundamental difference between Subversion and
bos@686: 	Mercurial is of course that Subversion is centralized, while
bos@686: 	Mercurial is distributed.  Since Mercurial stores all of a
bos@686: 	project's history on your local drive, it only needs to
bos@686: 	perform a network access when you want to explicitly
bos@686: 	communicate with another repository. In contrast, Subversion
bos@686: 	stores very little information locally, and the client must
bos@686: 	thus contact its server for many common operations.</para>
bos@686: 
bos@691:       <para id="x_6fa">Subversion more or less gets away without a well-defined
bos@686: 	notion of a branch: which portion of a server's namespace
bos@686: 	qualifies as a branch is a matter of convention, with the
bos@686: 	software providing no enforcement.  Mercurial treats a
bos@686: 	repository as the unit of branch management.</para>
bos@686: 
bos@686:       <sect3>
bos@686: 	<title>Scope of commands</title>
bos@686: 
bos@691: 	<para id="x_6fb">Since Subversion doesn't know what parts of its
bos@686: 	  namespace are really branches, it treats most commands as
bos@686: 	  requests to operate at and below whatever directory you are
bos@686: 	  currently visiting.  For instance, if you run <command>svn
bos@686: 	    log</command>, you'll get the history of whatever part of
bos@686: 	  the tree you're looking at, not the tree as a whole.</para>
bos@686: 
bos@691: 	<para id="x_6fc">Mercurial's commands behave differently, by defaulting
bos@686: 	  to operating over an entire repository.  Run <command>hg
bos@686: 	    log</command> and it will tell you the history of the
bos@686: 	  entire tree, no matter what part of the working directory
bos@686: 	  you're visiting at the time.  If you want the history of
bos@686: 	  just a particular file or directory, simply supply it by
bos@686: 	  name, e.g. <command>hg log src</command>.</para>
bos@686: 
bos@691: 	<para id="x_6fd">From my own experience, this difference in default
bos@686: 	  behaviors is probably the most likely to trip you up if you
bos@686: 	  have to switch back and forth frequently between the two
bos@686: 	  tools.</para>
bos@686:       </sect3>
bos@686: 
bos@686:       <sect3>
bos@686: 	<title>Multi-user operation and safety</title>
bos@686: 
bos@691: 	<para id="x_6fe">With Subversion, it is normal (though slightly frowned
bos@686: 	  upon) for multiple people to collaborate in a single branch.
bos@686: 	  If Alice and Bob are working together, and Alice commits
bos@686: 	  some changes to their shared branch, Bob must update his
bos@686: 	  client's view of the branch before he can commit.  Since at
bos@686: 	  this time he has no permanent record of the changes he has
bos@686: 	  made, he can corrupt or lose his modifications during and
bos@686: 	  after his update.</para>
bos@686: 
bos@691: 	<para id="x_6ff">Mercurial encourages a commit-then-merge model instead.
bos@686: 	  Bob commits his changes locally before pulling changes from,
bos@686: 	  or pushing them to, the server that he shares with Alice.
bos@686: 	  If Alice pushed her changes before Bob tries to push his, he
bos@686: 	  will not be able to push his changes until he pulls hers,
bos@686: 	  merges with them, and commits the result of the merge.  If
bos@686: 	  he makes a mistake during the merge, he still has the option
bos@686: 	  of reverting to the commit that recorded his changes.</para>
bos@686: 
bos@691: 	<para id="x_700">It is worth emphasizing that these are the common ways
bos@686: 	  of working with these tools. Subversion supports a safer
bos@686: 	  work-in-your-own-branch model, but it is cumbersome enough
bos@686: 	  in practice to not be widely used.  Mercurial can support
bos@686: 	  the less safe mode of allowing changes to be pulled in and
bos@686: 	  merged on top of uncommitted edits, but this is considered
bos@686: 	  highly unusual.</para>
bos@686:       </sect3>
bos@686: 
bos@686:       <sect3>
bos@686: 	<title>Published vs local changes</title>
bos@686: 
bos@691: 	<para id="x_701">A Subversion <command>svn commit</command> command
bos@686: 	  immediately publishes changes to a server, where they can be
bos@686: 	  seen by everyone who has read access.</para>
bos@686: 
bos@691: 	<para id="x_702">With Mercurial, commits are always local, and must be
bos@686: 	  published via a <command>hg push</command> command
bos@686: 	  afterwards.</para>
bos@686: 
bos@691: 	<para id="x_703">Each approach has its advantages and disadvantages.  The
bos@686: 	  Subversion model means that changes are published, and hence
bos@686: 	  reviewable and usable, immediately.  On the other hand, this
bos@686: 	  means that a user must have commit access to a repository in
bos@686: 	  order to use the software in a normal way, and commit access
bos@686: 	  is not lightly given out by most open source
bos@686: 	  projects.</para>
bos@686: 
bos@691: 	<para id="x_704">The Mercurial approach allows anyone who can clone a
bos@686: 	  repository to commit changes without the need for someone
bos@686: 	  else's permission, and they can then publish their changes
bos@686: 	  and continue to participate however they see fit.  The
bos@686: 	  distinction between committing and pushing does open up the
bos@686: 	  possibility of someone committing changes to their laptop
bos@686: 	  and walking away for a few days having forgotten to push
bos@686: 	  them, which in rare cases might leave collaborators
bos@686: 	  temporarily stuck.</para>
bos@686:       </sect3>
bos@686:     </sect2>
bos@686: 
bos@686:     <sect2>
bos@686:       <title>Quick reference</title>
bos@686: 
bos@686:       <table>
bos@686: 	<title>Subversion commands and Mercurial equivalents</title>
bos@686: 	<tgroup cols="3">
bos@686: 	  <thead>
bos@686: 	    <row>
bos@686: 	      <entry>Subversion</entry>
bos@686: 	      <entry>Mercurial</entry>
bos@686: 	      <entry>Notes</entry>
bos@686: 	    </row>
bos@686: 	  </thead>
bos@686: 	  <tbody>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn add</command></entry>
bos@686: 	      <entry><command>hg add</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn blame</command></entry>
bos@686: 	      <entry><command>hg annotate</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn cat</command></entry>
bos@686: 	      <entry><command>hg cat</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn checkout</command></entry>
bos@686: 	      <entry><command>hg clone</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn cleanup</command></entry>
bos@686: 	      <entry>n/a</entry>
bos@686: 	      <entry>No cleanup needed</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn commit</command></entry>
bos@686: 	      <entry><command>hg commit</command>; <command>hg
bos@686: 		  push</command></entry>
bos@686: 	      <entry><command>hg push</command> publishes after
bos@686: 		commit</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn copy</command></entry>
bos@686: 	      <entry><command>hg clone</command></entry>
bos@686: 	      <entry>To create a new branch</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn copy</command></entry>
bos@686: 	      <entry><command>hg copy</command></entry>
bos@686: 	      <entry>To copy files or directories</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn delete</command> (<command>svn
bos@686: 		  remove</command>)</entry>
bos@686: 	      <entry><command>hg remove</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn diff</command></entry>
bos@686: 	      <entry><command>hg diff</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn export</command></entry>
bos@686: 	      <entry><command>hg archive</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn help</command></entry>
bos@686: 	      <entry><command>hg help</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn import</command></entry>
bos@686: 	      <entry><command>hg addremove</command>; <command>hg
bos@686: 		  commit</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn info</command></entry>
bos@686: 	      <entry><command>hg parents</command></entry>
bos@686: 	      <entry>Shows what revision is checked out</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn info</command></entry>
bos@686: 	      <entry><command>hg showconfig
bos@686: 		  paths.parent</command></entry>
bos@686: 	      <entry>Shows what URL is checked out</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn list</command></entry>
bos@686: 	      <entry><command>hg manifest</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn log</command></entry>
bos@686: 	      <entry><command>hg log</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn merge</command></entry>
bos@686: 	      <entry><command>hg merge</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn mkdir</command></entry>
bos@686: 	      <entry>n/a</entry>
bos@686: 	      <entry>Mercurial does not track directories</entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn move</command> (<command>svn
bos@686: 		  rename</command>)</entry>
bos@686: 	      <entry><command>hg rename</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn resolved</command></entry>
bos@686: 	      <entry><command>hg resolve -m</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn revert</command></entry>
bos@686: 	      <entry><command>hg revert</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn status</command></entry>
bos@686: 	      <entry><command>hg status</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	    <row>
bos@686: 	      <entry><command>svn update</command></entry>
bos@686: 	      <entry><command>hg pull -u</command></entry>
bos@686: 	      <entry></entry>
bos@686: 	    </row>
bos@686: 	  </tbody>
bos@686: 	</tgroup>
bos@686:       </table>
bos@686:     </sect2>
bos@686:   </sect1>
bos@686: 
bos@686:   <sect1>
bos@686:     <title>Useful tips for newcomers</title>
bos@686: 
bos@691:     <para id="x_705">Under some revision control systems, printing a diff for a
bos@686:       single committed revision can be painful. For instance, with
bos@686:       Subversion, to see what changed in revision 104654, you must
bos@686:       type <command>svn diff -r104653:104654</command>. Mercurial
bos@686:       eliminates the need to type the revision ID twice in this common
bos@686:       case. For a plain diff, <command>hg export 104654</command>. For
bos@686:       a log message followed by a diff, <command>hg log -r104654
bos@686: 	-p</command>.</para>
bos@686: 
bos@691:     <para id="x_706">When you run <command>hg status</command> without any
bos@686:       arguments, it prints the status of the entire tree, with paths
bos@686:       relative to the root of the repository.  This makes it tricky to
bos@686:       copy a file name from the output of <command>hg status</command>
bos@686:       into the command line.  If you supply a file or directory name
bos@686:       to <command>hg status</command>, it will print paths relative to
bos@686:       your current location instead.  So to get tree-wide status from
bos@686:       <command>hg status</command>, with paths that are relative to
bos@686:       your current directory and not the root of the repository, feed
bos@686:       the output of <command>hg root</command> into <command>hg
bos@686: 	status</command>.  You can easily do this as follows on a
bos@686:       Unix-like system:</para>
bos@686: 
bos@686:     <screen><prompt>$</prompt> <userinput>hg status `hg root`</userinput></screen>
bos@686:   </sect1>
bos@559: </appendix>
bos@559: 
bos@559: <!--
bos@559: local variables: 
bos@559: sgml-parent-document: ("00book.xml" "book" "appendix")
bos@559: end:
bos@559: -->