hgbook
changeset 650:7e7c47481e4f
Oops, this is the real merge for my hg's oddity
author | Dongsheng Song <dongsheng.song@gmail.com> |
---|---|
date | Fri Mar 20 16:43:35 2009 +0800 (2009-03-20) |
parents | d13c7c706a58 |
children | c15e039d98b8 |
files | .hgignore en/00book.xml en/Makefile en/appA-cmdref.xml en/appB-mq-ref.xml en/appC-srcinstall.xml en/appD-license.xml en/autoid.py en/ch00-preface.xml en/ch01-intro.xml en/ch01-tour-basic.xml en/ch02-tour-basic.xml en/ch02-tour-merge.xml en/ch03-concepts.xml en/ch03-tour-merge.xml en/ch04-concepts.xml en/ch04-daily.xml en/ch05-collab.xml en/ch05-daily.xml en/ch06-collab.xml en/ch06-filenames.xml en/ch07-branch.xml en/ch07-filenames.xml en/ch08-branch.xml en/ch08-undo.xml en/ch09-hook.xml en/ch09-undo.xml en/ch10-hook.xml en/ch10-template.xml en/ch11-mq.xml en/ch11-template.xml en/ch12-mq-collab.xml en/ch12-mq.xml en/ch13-hgext.xml en/ch13-mq-collab.xml en/ch14-hgext.xml po/zh.po web/hgbook/dbutil.py web/hgbook/load_elements.py |
line diff
1.1 --- a/.hgignore Fri Mar 20 15:40:06 2009 +0800 1.2 +++ b/.hgignore Fri Mar 20 16:43:35 2009 +0800 1.3 @@ -19,6 +19,7 @@ 1.4 .\#* 1.5 .run 1.6 .validated-00book.xml 1.7 +en/all-ids.dat 1.8 web/hgbook/.database.sqlite3 1.9 web/hgbook/secrets.py 1.10 stylesheets/system-xsl
2.1 --- a/en/00book.xml Fri Mar 20 15:40:06 2009 +0800 2.2 +++ b/en/00book.xml Fri Mar 20 16:43:35 2009 +0800 2.3 @@ -7,20 +7,20 @@ 2.4 2.5 <!-- Chapters. --> 2.6 2.7 -<!ENTITY ch01 SYSTEM "ch01-intro.xml"> 2.8 -<!ENTITY ch02 SYSTEM "ch02-tour-basic.xml"> 2.9 -<!ENTITY ch03 SYSTEM "ch03-tour-merge.xml"> 2.10 -<!ENTITY ch04 SYSTEM "ch04-concepts.xml"> 2.11 -<!ENTITY ch05 SYSTEM "ch05-daily.xml"> 2.12 -<!ENTITY ch06 SYSTEM "ch06-collab.xml"> 2.13 -<!ENTITY ch07 SYSTEM "ch07-filenames.xml"> 2.14 -<!ENTITY ch08 SYSTEM "ch08-branch.xml"> 2.15 -<!ENTITY ch09 SYSTEM "ch09-undo.xml"> 2.16 -<!ENTITY ch10 SYSTEM "ch10-hook.xml"> 2.17 -<!ENTITY ch11 SYSTEM "ch11-template.xml"> 2.18 -<!ENTITY ch12 SYSTEM "ch12-mq.xml"> 2.19 -<!ENTITY ch13 SYSTEM "ch13-mq-collab.xml"> 2.20 -<!ENTITY ch14 SYSTEM "ch14-hgext.xml"> 2.21 +<!ENTITY ch00 SYSTEM "ch00-preface.xml"> 2.22 +<!ENTITY ch01 SYSTEM "ch01-tour-basic.xml"> 2.23 +<!ENTITY ch02 SYSTEM "ch02-tour-merge.xml"> 2.24 +<!ENTITY ch03 SYSTEM "ch03-concepts.xml"> 2.25 +<!ENTITY ch04 SYSTEM "ch04-daily.xml"> 2.26 +<!ENTITY ch05 SYSTEM "ch05-collab.xml"> 2.27 +<!ENTITY ch06 SYSTEM "ch06-filenames.xml"> 2.28 +<!ENTITY ch07 SYSTEM "ch07-branch.xml"> 2.29 +<!ENTITY ch08 SYSTEM "ch08-undo.xml"> 2.30 +<!ENTITY ch09 SYSTEM "ch09-hook.xml"> 2.31 +<!ENTITY ch10 SYSTEM "ch10-template.xml"> 2.32 +<!ENTITY ch11 SYSTEM "ch11-mq.xml"> 2.33 +<!ENTITY ch12 SYSTEM "ch12-mq-collab.xml"> 2.34 +<!ENTITY ch13 SYSTEM "ch13-hgext.xml"> 2.35 <!ENTITY appA SYSTEM "appA-cmdref.xml"> 2.36 <!ENTITY appB SYSTEM "appB-mq-ref.xml"> 2.37 <!ENTITY appC SYSTEM "appC-srcinstall.xml"> 2.38 @@ -79,7 +79,6 @@ 2.39 &ch11; 2.40 &ch12; 2.41 &ch13; 2.42 - &ch14; 2.43 <!-- &appA; --> 2.44 &appB; 2.45 &appC;
3.1 --- a/en/Makefile Fri Mar 20 15:40:06 2009 +0800 3.2 +++ b/en/Makefile Fri Mar 20 16:43:35 2009 +0800 3.3 @@ -130,21 +130,24 @@ 3.4 3.5 all: web 3.6 3.7 -../stylesheets/system-xsl: $(system-xsl-dir) 3.8 +../xsl/system-xsl: $(system-xsl-dir) 3.9 ln -s $< $@ 3.10 3.11 web: ../xsl/system-xsl websup html 3.12 3.13 -html: ../stylesheets/system-xsl $(xml-src-files) valid 3.14 - xsltproc $(xsltproc-opts) -o html/read/x ../stylesheets/chunk-stylesheet.xsl 00book.xml 3.15 +html: ../xsl/system-xsl $(xml-src-files) valid 3.16 + xsltproc $(xsltproc-opts) -o html/read/x ../xsl/chunk-stylesheet.xsl 00book.xml 3.17 for i in html/read/*.html; do \ 3.18 gzip -9 -c $$i > $$i.gz; \ 3.19 done 3.20 3.21 websup: $(extras-web) 3.22 - mkdir -p $(obj-websup)/images 3.23 - cp ../stylesheets/system-xsl/images/*.png $(obj-websup)/images 3.24 - cp -f ../web/icons/*.png $(obj-websup)/images 3.25 + mkdir -p $(obj-websup)/figs 3.26 + cp ../xsl/system-xsl/images/*.png $(obj-websup)/figs 3.27 + cp -f ../web/icons/*.png $(obj-websup)/figs 3.28 + 3.29 +all-ids.dat: ../xsl/all-ids.xsl $(xml-src-files) 3.30 + $(xsltproc) $(xsltproc-opts) -o $@ ../xsl/all-ids.xsl 00book.xml 3.31 3.32 web: websup 3.33
4.1 --- a/en/appA-cmdref.xml Fri Mar 20 15:40:06 2009 +0800 4.2 +++ b/en/appA-cmdref.xml Fri Mar 20 16:43:35 2009 +0800 4.3 @@ -3,113 +3,113 @@ 4.4 <appendix id="cmdref"> 4.5 <title>Command reference</title> 4.6 4.7 -<para>\cmdref{add}{add files at the next commit} 4.8 +<para id="x_653">\cmdref{add}{add files at the next commit} 4.9 \optref{add}{I}{include} 4.10 \optref{add}{X}{exclude} 4.11 \optref{add}{n}{dry-run}</para> 4.12 4.13 -<para>\cmdref{diff}{print changes in history or working directory}</para> 4.14 - 4.15 -<para>Show differences between revisions for the specified files or 4.16 +<para id="x_654">\cmdref{diff}{print changes in history or working directory}</para> 4.17 + 4.18 +<para id="x_655">Show differences between revisions for the specified files or 4.19 directories, using the unified diff format. For a description of the 4.20 unified diff format, see section <xref linkend="sec.mq.patch"/>.</para> 4.21 4.22 -<para>By default, this command does not print diffs for files that Mercurial 4.23 +<para id="x_656">By default, this command does not print diffs for files that Mercurial 4.24 considers to contain binary data. To control this behaviour, see the 4.25 <option role="hg-opt-diff">-a</option> and <option role="hg-opt-diff">--git</option> options.</para> 4.26 4.27 <sect2> 4.28 <title>Options</title> 4.29 4.30 -<para>\loptref{diff}{nodates}</para> 4.31 - 4.32 -<para>Omit date and time information when printing diff headers.</para> 4.33 - 4.34 -<para>\optref{diff}{B}{ignore-blank-lines}</para> 4.35 - 4.36 -<para>Do not print changes that only insert or delete blank lines. A line 4.37 +<para id="x_657">\loptref{diff}{nodates}</para> 4.38 + 4.39 +<para id="x_658">Omit date and time information when printing diff headers.</para> 4.40 + 4.41 +<para id="x_659">\optref{diff}{B}{ignore-blank-lines}</para> 4.42 + 4.43 +<para id="x_65a">Do not print changes that only insert or delete blank lines. A line 4.44 that contains only whitespace is not considered blank. 4.45 </para> 4.46 4.47 -<para>\optref{diff}{I}{include} 4.48 -</para> 4.49 - 4.50 -<para>Include files and directories whose names match the given patterns. 4.51 -</para> 4.52 - 4.53 -<para>\optref{diff}{X}{exclude} 4.54 -</para> 4.55 - 4.56 -<para>Exclude files and directories whose names match the given patterns. 4.57 -</para> 4.58 - 4.59 -<para>\optref{diff}{a}{text} 4.60 -</para> 4.61 - 4.62 -<para>If this option is not specified, <command role="hg-cmd">hg diff</command> will refuse to print 4.63 +<para id="x_65b">\optref{diff}{I}{include} 4.64 +</para> 4.65 + 4.66 +<para id="x_65c">Include files and directories whose names match the given patterns. 4.67 +</para> 4.68 + 4.69 +<para id="x_65d">\optref{diff}{X}{exclude} 4.70 +</para> 4.71 + 4.72 +<para id="x_65e">Exclude files and directories whose names match the given patterns. 4.73 +</para> 4.74 + 4.75 +<para id="x_65f">\optref{diff}{a}{text} 4.76 +</para> 4.77 + 4.78 +<para id="x_660">If this option is not specified, <command role="hg-cmd">hg diff</command> will refuse to print 4.79 diffs for files that it detects as binary. Specifying <option role="hg-opt-diff">-a</option> 4.80 forces <command role="hg-cmd">hg diff</command> to treat all files as text, and generate diffs for 4.81 all of them. 4.82 </para> 4.83 4.84 -<para>This option is useful for files that are <quote>mostly text</quote> but have a 4.85 +<para id="x_661">This option is useful for files that are <quote>mostly text</quote> but have a 4.86 few embedded NUL characters. If you use it on files that contain a 4.87 lot of binary data, its output will be incomprehensible. 4.88 </para> 4.89 4.90 -<para>\optref{diff}{b}{ignore-space-change} 4.91 -</para> 4.92 - 4.93 -<para>Do not print a line if the only change to that line is in the amount 4.94 +<para id="x_662">\optref{diff}{b}{ignore-space-change} 4.95 +</para> 4.96 + 4.97 +<para id="x_663">Do not print a line if the only change to that line is in the amount 4.98 of white space it contains. 4.99 </para> 4.100 4.101 -<para>\optref{diff}{g}{git} 4.102 -</para> 4.103 - 4.104 -<para>Print <command>git</command>-compatible diffs. XXX reference a format 4.105 +<para id="x_664">\optref{diff}{g}{git} 4.106 +</para> 4.107 + 4.108 +<para id="x_665">Print <command>git</command>-compatible diffs. XXX reference a format 4.109 description. 4.110 </para> 4.111 4.112 -<para>\optref{diff}{p}{show-function} 4.113 -</para> 4.114 - 4.115 -<para>Display the name of the enclosing function in a hunk header, using a 4.116 +<para id="x_666">\optref{diff}{p}{show-function} 4.117 +</para> 4.118 + 4.119 +<para id="x_667">Display the name of the enclosing function in a hunk header, using a 4.120 simple heuristic. This functionality is enabled by default, so the 4.121 <option role="hg-opt-diff">-p</option> option has no effect unless you change the value of 4.122 the <envar role="rc-item-diff">showfunc</envar> config item, as in the following example.</para> 4.123 4.124 <!-- &interaction.cmdref.diff-p; --> 4.125 4.126 -<para>\optref{diff}{r}{rev} 4.127 -</para> 4.128 - 4.129 -<para>Specify one or more revisions to compare. The <command role="hg-cmd">hg diff</command> command 4.130 +<para id="x_668">\optref{diff}{r}{rev} 4.131 +</para> 4.132 + 4.133 +<para id="x_669">Specify one or more revisions to compare. The <command role="hg-cmd">hg diff</command> command 4.134 accepts up to two <option role="hg-opt-diff">-r</option> options to specify the revisions to 4.135 compare. 4.136 </para> 4.137 4.138 <orderedlist> 4.139 -<listitem><para>Display the differences between the parent revision of the 4.140 +<listitem><para id="x_66a">Display the differences between the parent revision of the 4.141 working directory and the working directory. 4.142 </para> 4.143 </listitem> 4.144 -<listitem><para>Display the differences between the specified changeset and the 4.145 +<listitem><para id="x_66b">Display the differences between the specified changeset and the 4.146 working directory. 4.147 </para> 4.148 </listitem> 4.149 -<listitem><para>Display the differences between the two specified changesets. 4.150 +<listitem><para id="x_66c">Display the differences between the two specified changesets. 4.151 </para> 4.152 </listitem></orderedlist> 4.153 4.154 -<para>You can specify two revisions using either two <option role="hg-opt-diff">-r</option> 4.155 +<para id="x_66d">You can specify two revisions using either two <option role="hg-opt-diff">-r</option> 4.156 options or revision range notation. For example, the two revision 4.157 specifications below are equivalent. 4.158 </para> 4.159 <programlisting>hg diff -r 10 -r 20 4.160 hg diff -r10:20</programlisting> 4.161 4.162 -<para>When you provide two revisions, Mercurial treats the order of those 4.163 +<para id="x_66e">When you provide two revisions, Mercurial treats the order of those 4.164 revisions as significant. Thus, <command role="hg-cmd">hg diff -r10:20</command> will 4.165 produce a diff that will transform files from their contents as of 4.166 revision 10 to their contents as of revision 20, while 4.167 @@ -119,23 +119,23 @@ 4.168 diffing against the working directory. 4.169 </para> 4.170 4.171 -<para>\optref{diff}{w}{ignore-all-space} 4.172 -</para> 4.173 - 4.174 -<para>\cmdref{version}{print version and copyright information} 4.175 -</para> 4.176 - 4.177 -<para>This command displays the version of Mercurial you are running, and 4.178 +<para id="x_66f">\optref{diff}{w}{ignore-all-space} 4.179 +</para> 4.180 + 4.181 +<para id="x_670">\cmdref{version}{print version and copyright information} 4.182 +</para> 4.183 + 4.184 +<para id="x_671">This command displays the version of Mercurial you are running, and 4.185 its copyright license. There are four kinds of version string that 4.186 you may see. 4.187 </para> 4.188 <itemizedlist> 4.189 -<listitem><para>The string <quote><literal>unknown</literal></quote>. This version of Mercurial was 4.190 +<listitem><para id="x_672">The string <quote><literal>unknown</literal></quote>. This version of Mercurial was 4.191 not built in a Mercurial repository, and cannot determine its own 4.192 version. 4.193 </para> 4.194 </listitem> 4.195 -<listitem><para>A short numeric string, such as <quote><literal>1.1</literal></quote>. This is a 4.196 +<listitem><para id="x_673">A short numeric string, such as <quote><literal>1.1</literal></quote>. This is a 4.197 build of a revision of Mercurial that was identified by a specific 4.198 tag in the repository where it was built. (This doesn't necessarily 4.199 mean that you're running an official release; someone else could 4.200 @@ -143,11 +143,11 @@ 4.201 built Mercurial.) 4.202 </para> 4.203 </listitem> 4.204 -<listitem><para>A hexadecimal string, such as <quote><literal>875489e31abe</literal></quote>. This 4.205 +<listitem><para id="x_674">A hexadecimal string, such as <quote><literal>875489e31abe</literal></quote>. This 4.206 is a build of the given revision of Mercurial. 4.207 </para> 4.208 </listitem> 4.209 -<listitem><para>A hexadecimal string followed by a date, such as 4.210 +<listitem><para id="x_675">A hexadecimal string followed by a date, such as 4.211 <quote><literal>875489e31abe+20070205</literal></quote>. This is a build of the given 4.212 revision of Mercurial, where the build repository contained some 4.213 local changes that had not been committed. 4.214 @@ -161,14 +161,14 @@ 4.215 <sect3 id="cmdref.diff-vs-status"> 4.216 <title>Why do the results of <command role="hg-cmd">hg diff</command> and <command role="hg-cmd">hg status</command> differ?</title> 4.217 4.218 -<para>When you run the <command role="hg-cmd">hg status</command> command, you'll see a list of files 4.219 +<para id="x_676">When you run the <command role="hg-cmd">hg status</command> command, you'll see a list of files 4.220 that Mercurial will record changes for the next time you perform a 4.221 commit. If you run the <command role="hg-cmd">hg diff</command> command, you may notice that it 4.222 prints diffs for only a <emphasis>subset</emphasis> of the files that <command role="hg-cmd">hg status</command> 4.223 listed. There are two possible reasons for this. 4.224 </para> 4.225 4.226 -<para>The first is that <command role="hg-cmd">hg status</command> prints some kinds of modifications 4.227 +<para id="x_677">The first is that <command role="hg-cmd">hg status</command> prints some kinds of modifications 4.228 that <command role="hg-cmd">hg diff</command> doesn't normally display. The <command role="hg-cmd">hg diff</command> command 4.229 normally outputs unified diffs, which don't have the ability to 4.230 represent some changes that Mercurial can track. Most notably, 4.231 @@ -176,12 +176,12 @@ 4.232 executable, but Mercurial records this information. 4.233 </para> 4.234 4.235 -<para>If you use the <option role="hg-opt-diff">--git</option> option to <command role="hg-cmd">hg diff</command>, it will 4.236 +<para id="x_678">If you use the <option role="hg-opt-diff">--git</option> option to <command role="hg-cmd">hg diff</command>, it will 4.237 display <command>git</command>-compatible diffs that <emphasis>can</emphasis> display this 4.238 extra information. 4.239 </para> 4.240 4.241 -<para>The second possible reason that <command role="hg-cmd">hg diff</command> might be printing diffs 4.242 +<para id="x_679">The second possible reason that <command role="hg-cmd">hg diff</command> might be printing diffs 4.243 for a subset of the files displayed by <command role="hg-cmd">hg status</command> is that if you 4.244 invoke it without any arguments, <command role="hg-cmd">hg diff</command> prints diffs against the 4.245 first parent of the working directory. If you have run <command role="hg-cmd">hg merge</command> 4.246 @@ -199,14 +199,14 @@ 4.247 <sect3> 4.248 <title>Generating safe binary diffs</title> 4.249 4.250 -<para>If you use the <option role="hg-opt-diff">-a</option> option to force Mercurial to print 4.251 +<para id="x_67a">If you use the <option role="hg-opt-diff">-a</option> option to force Mercurial to print 4.252 diffs of files that are either <quote>mostly text</quote> or contain lots of 4.253 binary data, those diffs cannot subsequently be applied by either 4.254 Mercurial's <command role="hg-cmd">hg import</command> command or the system's <command>patch</command> 4.255 command. 4.256 </para> 4.257 4.258 -<para>If you want to generate a diff of a binary file that is safe to use as 4.259 +<para id="x_67b">If you want to generate a diff of a binary file that is safe to use as 4.260 input for <command role="hg-cmd">hg import</command>, use the <command role="hg-cmd">hg diff</command>{--git} option when you 4.261 generate the patch. The system <command>patch</command> command cannot handle 4.262 binary patches at all.
5.1 --- a/en/appB-mq-ref.xml Fri Mar 20 15:40:06 2009 +0800 5.2 +++ b/en/appB-mq-ref.xml Fri Mar 20 16:43:35 2009 +0800 5.3 @@ -7,14 +7,14 @@ 5.4 <sect1 id="sec.mqref.cmdref"> 5.5 <title>MQ command reference</title> 5.6 5.7 - <para>For an overview of the commands provided by MQ, use the 5.8 + <para id="x_5e8">For an overview of the commands provided by MQ, use the 5.9 command <command role="hg-cmd">hg help mq</command>.</para> 5.10 5.11 <sect2> 5.12 <title><command role="hg-ext-mq">qapplied</command>&emdash;print 5.13 applied patches</title> 5.14 5.15 - <para>The <command role="hg-ext-mq">qapplied</command> command 5.16 + <para id="x_5e9">The <command role="hg-ext-mq">qapplied</command> command 5.17 prints the current stack of applied patches. Patches are 5.18 printed in oldest-to-newest order, so the last patch in the 5.19 list is the <quote>top</quote> patch.</para> 5.20 @@ -24,7 +24,7 @@ 5.21 <title><command role="hg-ext-mq">qcommit</command>&emdash;commit 5.22 changes in the queue repository</title> 5.23 5.24 - <para>The <command role="hg-ext-mq">qcommit</command> command 5.25 + <para id="x_5ea">The <command role="hg-ext-mq">qcommit</command> command 5.26 commits any outstanding changes in the <filename 5.27 role="special" class="directory">.hg/patches</filename> 5.28 repository. This command only works if the <filename 5.29 @@ -36,7 +36,7 @@ 5.30 after running <command 5.31 role="hg-ext-mq">qinit</command>.</para> 5.32 5.33 - <para>This command is shorthand for <command role="hg-cmd">hg 5.34 + <para id="x_5eb">This command is shorthand for <command role="hg-cmd">hg 5.35 commit --cwd .hg/patches</command>.</para> 5.36 </sect2> 5.37 <sect2> 5.38 @@ -45,7 +45,7 @@ 5.39 from the <filename role="special">series</filename> 5.40 file}</title> 5.41 5.42 - <para>The <command role="hg-ext-mq">qdelete</command> command 5.43 + <para id="x_5ec">The <command role="hg-ext-mq">qdelete</command> command 5.44 removes the entry for a patch from the <filename 5.45 role="special">series</filename> file in the <filename 5.46 role="special" class="directory">.hg/patches</filename> 5.47 @@ -54,9 +54,9 @@ 5.48 the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option 5.49 to do that.</para> 5.50 5.51 - <para>Options:</para> 5.52 - <itemizedlist> 5.53 - <listitem><para><option 5.54 + <para id="x_5ed">Options:</para> 5.55 + <itemizedlist> 5.56 + <listitem><para id="x_5ee"><option 5.57 role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the 5.58 patch file.</para> 5.59 </listitem></itemizedlist> 5.60 @@ -66,7 +66,7 @@ 5.61 <title><command role="hg-ext-mq">qdiff</command>&emdash;print a 5.62 diff of the topmost applied patch</title> 5.63 5.64 - <para>The <command role="hg-ext-mq">qdiff</command> command 5.65 + <para id="x_5ef">The <command role="hg-ext-mq">qdiff</command> command 5.66 prints a diff of the topmost applied patch. It is equivalent 5.67 to <command role="hg-cmd">hg diff -r-2:-1</command>.</para> 5.68 5.69 @@ -75,12 +75,12 @@ 5.70 <title><command role="hg-ext-mq">qfold</command>&emdash;merge 5.71 (<quote>fold</quote>) several patches into one</title> 5.72 5.73 - <para>The <command role="hg-ext-mq">qfold</command> command 5.74 + <para id="x_5f0">The <command role="hg-ext-mq">qfold</command> command 5.75 merges multiple patches into the topmost applied patch, so 5.76 that the topmost applied patch makes the union of all of the 5.77 changes in the patches in question.</para> 5.78 5.79 - <para>The patches to fold must not be applied; <command 5.80 + <para id="x_5f1">The patches to fold must not be applied; <command 5.81 role="hg-ext-mq">qfold</command> will exit with an error if 5.82 any is. The order in which patches are folded is significant; 5.83 <command role="hg-cmd">hg qfold a b</command> means 5.84 @@ -88,7 +88,7 @@ 5.85 <literal>a</literal>, followed by 5.86 <literal>b</literal></quote>.</para> 5.87 5.88 - <para>The comments from the folded patches are appended to the 5.89 + <para id="x_5f2">The comments from the folded patches are appended to the 5.90 comments of the destination patch, with each block of comments 5.91 separated by three asterisk 5.92 (<quote><literal>*</literal></quote>) characters. Use the 5.93 @@ -96,19 +96,19 @@ 5.94 edit the commit message for the combined patch/changeset after 5.95 the folding has completed.</para> 5.96 5.97 - <para>Options:</para> 5.98 - <itemizedlist> 5.99 - <listitem><para><option 5.100 + <para id="x_5f3">Options:</para> 5.101 + <itemizedlist> 5.102 + <listitem><para id="x_5f4"><option 5.103 role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the 5.104 commit message and patch description for the newly folded 5.105 patch.</para> 5.106 </listitem> 5.107 - <listitem><para><option 5.108 + <listitem><para id="x_5f5"><option 5.109 role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the 5.110 contents of the given file as the new commit message and 5.111 patch description for the folded patch.</para> 5.112 </listitem> 5.113 - <listitem><para><option 5.114 + <listitem><para id="x_5f6"><option 5.115 role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the 5.116 given text as the new commit message and patch description 5.117 for the folded patch.</para> 5.118 @@ -120,7 +120,7 @@ 5.119 role="hg-ext-mq">qheader</command>&emdash;display the 5.120 header/description of a patch</title> 5.121 5.122 - <para>The <command role="hg-ext-mq">qheader</command> command 5.123 + <para id="x_5f7">The <command role="hg-ext-mq">qheader</command> command 5.124 prints the header, or description, of a patch. By default, it 5.125 prints the header of the topmost applied patch. Given an 5.126 argument, it prints the header of the named patch.</para> 5.127 @@ -130,7 +130,7 @@ 5.128 <title><command role="hg-ext-mq">qimport</command>&emdash;import 5.129 a third-party patch into the queue</title> 5.130 5.131 - <para>The <command role="hg-ext-mq">qimport</command> command 5.132 + <para id="x_5f8">The <command role="hg-ext-mq">qimport</command> command 5.133 adds an entry for an external patch to the <filename 5.134 role="special">series</filename> file, and copies the patch 5.135 into the <filename role="special" 5.136 @@ -138,7 +138,7 @@ 5.137 the entry immediately after the topmost applied patch, but 5.138 does not push the patch.</para> 5.139 5.140 - <para>If the <filename role="special" 5.141 + <para id="x_5f9">If the <filename role="special" 5.142 class="directory">.hg/patches</filename> directory is a 5.143 repository, <command role="hg-ext-mq">qimport</command> 5.144 automatically does an <command role="hg-cmd">hg add</command> 5.145 @@ -149,14 +149,14 @@ 5.146 <title><command role="hg-ext-mq">qinit</command>&emdash;prepare 5.147 a repository to work with MQ</title> 5.148 5.149 - <para>The <command role="hg-ext-mq">qinit</command> command 5.150 + <para id="x_5fa">The <command role="hg-ext-mq">qinit</command> command 5.151 prepares a repository to work with MQ. It creates a directory 5.152 called <filename role="special" 5.153 class="directory">.hg/patches</filename>.</para> 5.154 5.155 - <para>Options:</para> 5.156 - <itemizedlist> 5.157 - <listitem><para><option 5.158 + <para id="x_5fb">Options:</para> 5.159 + <itemizedlist> 5.160 + <listitem><para id="x_5fc"><option 5.161 role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create 5.162 <filename role="special" 5.163 class="directory">.hg/patches</filename> as a repository 5.164 @@ -166,7 +166,7 @@ 5.165 file.</para> 5.166 </listitem></itemizedlist> 5.167 5.168 - <para>When the <filename role="special" 5.169 + <para id="x_5fd">When the <filename role="special" 5.170 class="directory">.hg/patches</filename> directory is a 5.171 repository, the <command role="hg-ext-mq">qimport</command> 5.172 and <command role="hg-ext-mq">qnew</command> commands 5.173 @@ -178,7 +178,7 @@ 5.174 <title><command role="hg-ext-mq">qnew</command>&emdash;create a 5.175 new patch</title> 5.176 5.177 - <para>The <command role="hg-ext-mq">qnew</command> command 5.178 + <para id="x_5fe">The <command role="hg-ext-mq">qnew</command> command 5.179 creates a new patch. It takes one mandatory argument, the 5.180 name to use for the patch file. The newly created patch is 5.181 created empty by default. It is added to the <filename 5.182 @@ -186,7 +186,7 @@ 5.183 topmost applied patch, and is immediately pushed on top of 5.184 that patch.</para> 5.185 5.186 - <para>If <command role="hg-ext-mq">qnew</command> finds modified 5.187 + <para id="x_5ff">If <command role="hg-ext-mq">qnew</command> finds modified 5.188 files in the working directory, it will refuse to create a new 5.189 patch unless the <option 5.190 role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used 5.191 @@ -194,16 +194,16 @@ 5.192 role="hg-ext-mq">qrefresh</command> your topmost applied 5.193 patch before you apply a new patch on top of it.</para> 5.194 5.195 - <para>Options:</para> 5.196 - <itemizedlist> 5.197 - <listitem><para><option 5.198 + <para id="x_600">Options:</para> 5.199 + <itemizedlist> 5.200 + <listitem><para id="x_601"><option 5.201 role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new 5.202 patch if the contents of the working directory are 5.203 modified. Any outstanding modifications are added to the 5.204 newly created patch, so after this command completes, the 5.205 working directory will no longer be modified.</para> 5.206 </listitem> 5.207 - <listitem><para><option 5.208 + <listitem><para id="x_602"><option 5.209 role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given 5.210 text as the commit message. This text will be stored at 5.211 the beginning of the patch file, before the patch 5.212 @@ -215,7 +215,7 @@ 5.213 <title><command role="hg-ext-mq">qnext</command>&emdash;print 5.214 the name of the next patch</title> 5.215 5.216 - <para>The <command role="hg-ext-mq">qnext</command> command 5.217 + <para id="x_603">The <command role="hg-ext-mq">qnext</command> command 5.218 prints the name name of the next patch in the <filename 5.219 role="special">series</filename> file after the topmost 5.220 applied patch. This patch will become the topmost applied 5.221 @@ -227,15 +227,15 @@ 5.222 <title><command role="hg-ext-mq">qpop</command>&emdash;pop 5.223 patches off the stack</title> 5.224 5.225 - <para>The <command role="hg-ext-mq">qpop</command> command 5.226 + <para id="x_604">The <command role="hg-ext-mq">qpop</command> command 5.227 removes applied patches from the top of the stack of applied 5.228 patches. By default, it removes only one patch.</para> 5.229 5.230 - <para>This command removes the changesets that represent the 5.231 + <para id="x_605">This command removes the changesets that represent the 5.232 popped patches from the repository, and updates the working 5.233 directory to undo the effects of the patches.</para> 5.234 5.235 - <para>This command takes an optional argument, which it uses as 5.236 + <para id="x_606">This command takes an optional argument, which it uses as 5.237 the name or index of the patch to pop to. If given a name, it 5.238 will pop patches until the named patch is the topmost applied 5.239 patch. If given a number, <command 5.240 @@ -245,7 +245,7 @@ 5.241 It pops patches until the patch identified by the given index 5.242 is the topmost applied patch.</para> 5.243 5.244 - <para>The <command role="hg-ext-mq">qpop</command> command does 5.245 + <para id="x_607">The <command role="hg-ext-mq">qpop</command> command does 5.246 not read or write patches or the <filename 5.247 role="special">series</filename> file. It is thus safe to 5.248 <command role="hg-ext-mq">qpop</command> a patch that you have 5.249 @@ -254,31 +254,31 @@ 5.250 In the latter two cases, use the name of the patch as it was 5.251 when you applied it.</para> 5.252 5.253 - <para>By default, the <command role="hg-ext-mq">qpop</command> 5.254 + <para id="x_608">By default, the <command role="hg-ext-mq">qpop</command> 5.255 command will not pop any patches if the working directory has 5.256 been modified. You can override this behaviour using the 5.257 <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option, 5.258 which reverts all modifications in the working 5.259 directory.</para> 5.260 5.261 - <para>Options:</para> 5.262 - <itemizedlist> 5.263 - <listitem><para><option 5.264 + <para id="x_609">Options:</para> 5.265 + <itemizedlist> 5.266 + <listitem><para id="x_60a"><option 5.267 role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all 5.268 applied patches. This returns the repository to its state 5.269 before you applied any patches.</para> 5.270 </listitem> 5.271 - <listitem><para><option 5.272 + <listitem><para id="x_60b"><option 5.273 role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly 5.274 revert any modifications to the working directory when 5.275 popping.</para> 5.276 </listitem> 5.277 - <listitem><para><option 5.278 + <listitem><para id="x_60c"><option 5.279 role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch 5.280 from the named queue.</para> 5.281 </listitem></itemizedlist> 5.282 5.283 - <para>The <command role="hg-ext-mq">qpop</command> command 5.284 + <para id="x_60d">The <command role="hg-ext-mq">qpop</command> command 5.285 removes one line from the end of the <filename 5.286 role="special">status</filename> file for each patch that it 5.287 pops.</para> 5.288 @@ -288,7 +288,7 @@ 5.289 <title><command role="hg-ext-mq">qprev</command>&emdash;print 5.290 the name of the previous patch</title> 5.291 5.292 - <para>The <command role="hg-ext-mq">qprev</command> command 5.293 + <para id="x_60e">The <command role="hg-ext-mq">qprev</command> command 5.294 prints the name of the patch in the <filename 5.295 role="special">series</filename> file that comes before the 5.296 topmost applied patch. This will become the topmost applied 5.297 @@ -300,18 +300,18 @@ 5.298 <title><command role="hg-ext-mq">qpush</command>&emdash;push 5.299 patches onto the stack</title> 5.300 5.301 - <para>The <command role="hg-ext-mq">qpush</command> command adds 5.302 + <para id="x_60f">The <command role="hg-ext-mq">qpush</command> command adds 5.303 patches onto the applied stack. By default, it adds only one 5.304 patch.</para> 5.305 5.306 - <para>This command creates a new changeset to represent each 5.307 + <para id="x_610">This command creates a new changeset to represent each 5.308 applied patch, and updates the working directory to apply the 5.309 effects of the patches.</para> 5.310 5.311 - <para>The default data used when creating a changeset are as 5.312 + <para id="x_611">The default data used when creating a changeset are as 5.313 follows:</para> 5.314 <itemizedlist> 5.315 - <listitem><para>The commit date and time zone are the current 5.316 + <listitem><para id="x_612">The commit date and time zone are the current 5.317 date and time zone. Because these data are used to 5.318 compute the identity of a changeset, this means that if 5.319 you <command role="hg-ext-mq">qpop</command> a patch and 5.320 @@ -319,32 +319,32 @@ 5.321 changeset that you push will have a different identity 5.322 than the changeset you popped.</para> 5.323 </listitem> 5.324 - <listitem><para>The author is the same as the default used by 5.325 + <listitem><para id="x_613">The author is the same as the default used by 5.326 the <command role="hg-cmd">hg commit</command> 5.327 command.</para> 5.328 </listitem> 5.329 - <listitem><para>The commit message is any text from the patch 5.330 + <listitem><para id="x_614">The commit message is any text from the patch 5.331 file that comes before the first diff header. If there is 5.332 no such text, a default commit message is used that 5.333 identifies the name of the patch.</para> 5.334 </listitem></itemizedlist> 5.335 - <para>If a patch contains a Mercurial patch header (XXX add 5.336 + <para id="x_615">If a patch contains a Mercurial patch header (XXX add 5.337 link), the information in the patch header overrides these 5.338 defaults.</para> 5.339 5.340 - <para>Options:</para> 5.341 - <itemizedlist> 5.342 - <listitem><para><option 5.343 + <para id="x_616">Options:</para> 5.344 + <itemizedlist> 5.345 + <listitem><para id="x_617"><option 5.346 role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all 5.347 unapplied patches from the <filename 5.348 role="special">series</filename> file until there are 5.349 none left to push.</para> 5.350 </listitem> 5.351 - <listitem><para><option 5.352 + <listitem><para id="x_618"><option 5.353 role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name 5.354 of the patch to the end of the commit message.</para> 5.355 </listitem> 5.356 - <listitem><para><option 5.357 + <listitem><para id="x_619"><option 5.358 role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch 5.359 fails to apply cleanly, use the entry for the patch in 5.360 another saved queue to compute the parameters for a 5.361 @@ -352,12 +352,12 @@ 5.362 normal Mercurial merge machinery. Use the resolution of 5.363 the merge as the new patch content.</para> 5.364 </listitem> 5.365 - <listitem><para><option 5.366 + <listitem><para id="x_61a"><option 5.367 role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the 5.368 named queue if merging while pushing.</para> 5.369 </listitem></itemizedlist> 5.370 5.371 - <para>The <command role="hg-ext-mq">qpush</command> command 5.372 + <para id="x_61b">The <command role="hg-ext-mq">qpush</command> command 5.373 reads, but does not modify, the <filename 5.374 role="special">series</filename> file. It appends one line 5.375 to the <command role="hg-cmd">hg status</command> file for 5.376 @@ -369,24 +369,24 @@ 5.377 role="hg-ext-mq">qrefresh</command>&emdash;update the 5.378 topmost applied patch</title> 5.379 5.380 - <para>The <command role="hg-ext-mq">qrefresh</command> command 5.381 + <para id="x_61c">The <command role="hg-ext-mq">qrefresh</command> command 5.382 updates the topmost applied patch. It modifies the patch, 5.383 removes the old changeset that represented the patch, and 5.384 creates a new changeset to represent the modified 5.385 patch.</para> 5.386 5.387 - <para>The <command role="hg-ext-mq">qrefresh</command> command 5.388 + <para id="x_61d">The <command role="hg-ext-mq">qrefresh</command> command 5.389 looks for the following modifications:</para> 5.390 <itemizedlist> 5.391 - <listitem><para>Changes to the commit message, i.e. the text 5.392 + <listitem><para id="x_61e">Changes to the commit message, i.e. the text 5.393 before the first diff header in the patch file, are 5.394 reflected in the new changeset that represents the 5.395 patch.</para> 5.396 </listitem> 5.397 - <listitem><para>Modifications to tracked files in the working 5.398 + <listitem><para id="x_61f">Modifications to tracked files in the working 5.399 directory are added to the patch.</para> 5.400 </listitem> 5.401 - <listitem><para>Changes to the files tracked using <command 5.402 + <listitem><para id="x_620">Changes to the files tracked using <command 5.403 role="hg-cmd">hg add</command>, <command 5.404 role="hg-cmd">hg copy</command>, <command 5.405 role="hg-cmd">hg remove</command>, or <command 5.406 @@ -395,25 +395,25 @@ 5.407 removed files and rename sources are removed.</para> 5.408 </listitem></itemizedlist> 5.409 5.410 - <para>Even if <command role="hg-ext-mq">qrefresh</command> 5.411 + <para id="x_621">Even if <command role="hg-ext-mq">qrefresh</command> 5.412 detects no changes, it still recreates the changeset that 5.413 represents the patch. This causes the identity of the 5.414 changeset to differ from the previous changeset that 5.415 identified the patch.</para> 5.416 5.417 - <para>Options:</para> 5.418 - <itemizedlist> 5.419 - <listitem><para><option 5.420 + <para id="x_622">Options:</para> 5.421 + <itemizedlist> 5.422 + <listitem><para id="x_623"><option 5.423 role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify 5.424 the commit and patch description, using the preferred text 5.425 editor.</para> 5.426 </listitem> 5.427 - <listitem><para><option 5.428 + <listitem><para id="x_624"><option 5.429 role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify 5.430 the commit message and patch description, using the given 5.431 text.</para> 5.432 </listitem> 5.433 - <listitem><para><option 5.434 + <listitem><para id="x_625"><option 5.435 role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify 5.436 the commit message and patch description, using text from 5.437 the given file.</para> 5.438 @@ -424,11 +424,11 @@ 5.439 <title><command role="hg-ext-mq">qrename</command>&emdash;rename 5.440 a patch</title> 5.441 5.442 - <para>The <command role="hg-ext-mq">qrename</command> command 5.443 + <para id="x_626">The <command role="hg-ext-mq">qrename</command> command 5.444 renames a patch, and changes the entry for the patch in the 5.445 <filename role="special">series</filename> file.</para> 5.446 5.447 - <para>With a single argument, <command 5.448 + <para id="x_627">With a single argument, <command 5.449 role="hg-ext-mq">qrename</command> renames the topmost 5.450 applied patch. With two arguments, it renames its first 5.451 argument to its second.</para> 5.452 @@ -439,21 +439,21 @@ 5.453 role="hg-ext-mq">qrestore</command>&emdash;restore saved 5.454 queue state</title> 5.455 5.456 - <para>XXX No idea what this does.</para> 5.457 + <para id="x_628">XXX No idea what this does.</para> 5.458 5.459 </sect2> 5.460 <sect2> 5.461 <title><command role="hg-ext-mq">qsave</command>&emdash;save 5.462 current queue state</title> 5.463 5.464 - <para>XXX Likewise.</para> 5.465 + <para id="x_629">XXX Likewise.</para> 5.466 5.467 </sect2> 5.468 <sect2> 5.469 <title><command role="hg-ext-mq">qseries</command>&emdash;print 5.470 the entire patch series</title> 5.471 5.472 - <para>The <command role="hg-ext-mq">qseries</command> command 5.473 + <para id="x_62a">The <command role="hg-ext-mq">qseries</command> command 5.474 prints the entire patch series from the <filename 5.475 role="special">series</filename> file. It prints only patch 5.476 names, not empty lines or comments. It prints in order from 5.477 @@ -464,7 +464,7 @@ 5.478 <title><command role="hg-ext-mq">qtop</command>&emdash;print the 5.479 name of the current patch</title> 5.480 5.481 - <para>The <command role="hg-ext-mq">qtop</command> prints the 5.482 + <para id="x_62b">The <command role="hg-ext-mq">qtop</command> prints the 5.483 name of the topmost currently applied patch.</para> 5.484 5.485 </sect2> 5.486 @@ -473,7 +473,7 @@ 5.487 role="hg-ext-mq">qunapplied</command>&emdash;print patches 5.488 not yet applied</title> 5.489 5.490 - <para>The <command role="hg-ext-mq">qunapplied</command> command 5.491 + <para id="x_62c">The <command role="hg-ext-mq">qunapplied</command> command 5.492 prints the names of patches from the <filename 5.493 role="special">series</filename> file that are not yet 5.494 applied. It prints them in order from the next patch that 5.495 @@ -484,28 +484,28 @@ 5.496 <title><command role="hg-cmd">hg strip</command>&emdash;remove a 5.497 revision and descendants</title> 5.498 5.499 - <para>The <command role="hg-cmd">hg strip</command> command 5.500 + <para id="x_62d">The <command role="hg-cmd">hg strip</command> command 5.501 removes a revision, and all of its descendants, from the 5.502 repository. It undoes the effects of the removed revisions 5.503 from the repository, and updates the working directory to the 5.504 first parent of the removed revision.</para> 5.505 5.506 - <para>The <command role="hg-cmd">hg strip</command> command 5.507 + <para id="x_62e">The <command role="hg-cmd">hg strip</command> command 5.508 saves a backup of the removed changesets in a bundle, so that 5.509 they can be reapplied if removed in error.</para> 5.510 5.511 - <para>Options:</para> 5.512 - <itemizedlist> 5.513 - <listitem><para><option role="hg-opt-strip">-b</option>: Save 5.514 + <para id="x_62f">Options:</para> 5.515 + <itemizedlist> 5.516 + <listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save 5.517 unrelated changesets that are intermixed with the stripped 5.518 changesets in the backup bundle.</para> 5.519 </listitem> 5.520 - <listitem><para><option role="hg-opt-strip">-f</option>: If a 5.521 + <listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a 5.522 branch has multiple heads, remove all heads. XXX This 5.523 should be renamed, and use <literal>-f</literal> to strip 5.524 revs when there are pending changes.</para> 5.525 </listitem> 5.526 - <listitem><para><option role="hg-opt-strip">-n</option>: Do 5.527 + <listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do 5.528 not save a backup bundle.</para> 5.529 </listitem></itemizedlist> 5.530 5.531 @@ -518,18 +518,18 @@ 5.532 <title>The <filename role="special">series</filename> 5.533 file</title> 5.534 5.535 - <para>The <filename role="special">series</filename> file 5.536 + <para id="x_633">The <filename role="special">series</filename> file 5.537 contains a list of the names of all patches that MQ can apply. 5.538 It is represented as a list of names, with one name saved per 5.539 line. Leading and trailing white space in each line are 5.540 ignored.</para> 5.541 5.542 - <para>Lines may contain comments. A comment begins with the 5.543 + <para id="x_634">Lines may contain comments. A comment begins with the 5.544 <quote><literal>#</literal></quote> character, and extends to 5.545 the end of the line. Empty lines, and lines that contain only 5.546 comments, are ignored.</para> 5.547 5.548 - <para>You will often need to edit the <filename 5.549 + <para id="x_635">You will often need to edit the <filename 5.550 role="special">series</filename> file by hand, hence the 5.551 support for comments and empty lines noted above. For 5.552 example, you can comment out a patch temporarily, and <command 5.553 @@ -538,7 +538,7 @@ 5.554 patches are applied by reordering their entries in the 5.555 <filename role="special">series</filename> file.</para> 5.556 5.557 - <para>Placing the <filename role="special">series</filename> 5.558 + <para id="x_636">Placing the <filename role="special">series</filename> 5.559 file under revision control is also supported; it is a good 5.560 idea to place all of the patches that it refers to under 5.561 revision control, as well. If you create a patch directory 5.562 @@ -551,7 +551,7 @@ 5.563 <title>The <filename role="special">status</filename> 5.564 file</title> 5.565 5.566 - <para>The <filename role="special">status</filename> file 5.567 + <para id="x_637">The <filename role="special">status</filename> file 5.568 contains the names and changeset hashes of all patches that MQ 5.569 currently has applied. Unlike the <filename 5.570 role="special">series</filename> file, this file is not
6.1 --- a/en/appC-srcinstall.xml Fri Mar 20 15:40:06 2009 +0800 6.2 +++ b/en/appC-srcinstall.xml Fri Mar 20 16:43:35 2009 +0800 6.3 @@ -7,29 +7,29 @@ 6.4 <sect1 id="sec.srcinstall.unixlike"> 6.5 <title>On a Unix-like system</title> 6.6 6.7 - <para>If you are using a Unix-like system that has a sufficiently 6.8 + <para id="x_5e0">If you are using a Unix-like system that has a sufficiently 6.9 recent version of Python (2.3 or newer) available, it is easy to 6.10 install Mercurial from source.</para> 6.11 <orderedlist> 6.12 - <listitem><para>Download a recent source tarball from <ulink 6.13 + <listitem><para id="x_5e1">Download a recent source tarball from <ulink 6.14 url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para> 6.15 </listitem> 6.16 - <listitem><para>Unpack the tarball:</para> 6.17 + <listitem><para id="x_5e2">Unpack the tarball:</para> 6.18 <programlisting>gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting> 6.19 </listitem> 6.20 - <listitem><para>Go into the source directory and run the 6.21 + <listitem><para id="x_5e3">Go into the source directory and run the 6.22 installer script. This will build Mercurial and install it 6.23 in your home directory.</para> 6.24 <programlisting>cd mercurial-MYVERSION 6.25 python setup.py install --force --home=$HOME</programlisting> 6.26 </listitem> 6.27 </orderedlist> 6.28 - <para>Once the install finishes, Mercurial will be in the 6.29 + <para id="x_5e4">Once the install finishes, Mercurial will be in the 6.30 <literal>bin</literal> subdirectory of your home directory. 6.31 Don't forget to make sure that this directory is present in your 6.32 shell's search path.</para> 6.33 6.34 - <para>You will probably need to set the <envar>PYTHONPATH</envar> 6.35 + <para id="x_5e5">You will probably need to set the <envar>PYTHONPATH</envar> 6.36 environment variable so that the Mercurial executable can find 6.37 the rest of the Mercurial packages. For example, on my laptop, 6.38 I have set it to <literal>/home/bos/lib/python</literal>. The 6.39 @@ -43,14 +43,14 @@ 6.40 <sect1> 6.41 <title>On Windows</title> 6.42 6.43 - <para>Building and installing Mercurial on Windows requires a 6.44 + <para id="x_5e6">Building and installing Mercurial on Windows requires a 6.45 variety of tools, a fair amount of technical knowledge, and 6.46 considerable patience. I very much <emphasis>do not 6.47 recommend</emphasis> this route if you are a <quote>casual 6.48 user</quote>. Unless you intend to hack on Mercurial, I 6.49 strongly suggest that you use a binary package instead.</para> 6.50 6.51 - <para>If you are intent on building Mercurial from source on 6.52 + <para id="x_5e7">If you are intent on building Mercurial from source on 6.53 Windows, follow the <quote>hard way</quote> directions on the 6.54 Mercurial wiki at <ulink 6.55 url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>,
7.1 --- a/en/appD-license.xml Fri Mar 20 15:40:06 2009 +0800 7.2 +++ b/en/appD-license.xml Fri Mar 20 16:43:35 2009 +0800 7.3 @@ -4,24 +4,24 @@ 7.4 <?dbhtml filename="open-publication-license.html"?> 7.5 <title>Open Publication License</title> 7.6 7.7 - <para>Version 1.0, 8 June 1999</para> 7.8 + <para id="x_638">Version 1.0, 8 June 1999</para> 7.9 7.10 <sect1> 7.11 <title>Requirements on both unmodified and modified 7.12 versions</title> 7.13 7.14 - <para>The Open Publication works may be reproduced and distributed 7.15 + <para id="x_639">The Open Publication works may be reproduced and distributed 7.16 in whole or in part, in any medium physical or electronic, 7.17 provided that the terms of this license are adhered to, and that 7.18 this license or an incorporation of it by reference (with any 7.19 options elected by the author(s) and/or publisher) is displayed 7.20 in the reproduction.</para> 7.21 7.22 - <para>Proper form for an incorporation by reference is as 7.23 + <para id="x_63a">Proper form for an incorporation by reference is as 7.24 follows:</para> 7.25 7.26 <blockquote> 7.27 - <para> Copyright (c) <emphasis>year</emphasis> by 7.28 + <para id="x_63b"> Copyright (c) <emphasis>year</emphasis> by 7.29 <emphasis>author's name or designee</emphasis>. This material 7.30 may be distributed only subject to the terms and conditions 7.31 set forth in the Open Publication License, 7.32 @@ -30,14 +30,14 @@ 7.33 url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para> 7.34 </blockquote> 7.35 7.36 - <para>The reference must be immediately followed with any options 7.37 + <para id="x_63c">The reference must be immediately followed with any options 7.38 elected by the author(s) and/or publisher of the document (see 7.39 section <xref linkend="sec.opl.options"/>).</para> 7.40 7.41 - <para>Commercial redistribution of Open Publication-licensed 7.42 + <para id="x_63d">Commercial redistribution of Open Publication-licensed 7.43 material is permitted.</para> 7.44 7.45 - <para>Any publication in standard (paper) book form shall require 7.46 + <para id="x_63e">Any publication in standard (paper) book form shall require 7.47 the citation of the original publisher and author. The publisher 7.48 and author's names shall appear on all outer surfaces of the 7.49 book. On all outer surfaces of the book the original publisher's 7.50 @@ -48,30 +48,30 @@ 7.51 <sect1> 7.52 <title>Copyright</title> 7.53 7.54 - <para>The copyright to each Open Publication is owned by its 7.55 + <para id="x_63f">The copyright to each Open Publication is owned by its 7.56 author(s) or designee.</para> 7.57 7.58 </sect1> 7.59 <sect1> 7.60 <title>Scope of license</title> 7.61 7.62 - <para>The following license terms apply to all Open Publication 7.63 + <para id="x_640">The following license terms apply to all Open Publication 7.64 works, unless otherwise explicitly stated in the 7.65 document.</para> 7.66 7.67 - <para>Mere aggregation of Open Publication works or a portion of 7.68 + <para id="x_641">Mere aggregation of Open Publication works or a portion of 7.69 an Open Publication work with other works or programs on the 7.70 same media shall not cause this license to apply to those other 7.71 works. The aggregate work shall contain a notice specifying the 7.72 inclusion of the Open Publication material and appropriate 7.73 copyright notice.</para> 7.74 7.75 - <para><emphasis role="bold">Severability</emphasis>. If any part 7.76 + <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part 7.77 of this license is found to be unenforceable in any 7.78 jurisdiction, the remaining portions of the license remain in 7.79 force.</para> 7.80 7.81 - <para><emphasis role="bold">No warranty</emphasis>. Open 7.82 + <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open 7.83 Publication works are licensed and provided <quote>as is</quote> 7.84 without warranty of any kind, express or implied, including, but 7.85 not limited to, the implied warranties of merchantability and 7.86 @@ -82,25 +82,25 @@ 7.87 <sect1> 7.88 <title>Requirements on modified works</title> 7.89 7.90 - <para>All modified versions of documents covered by this license, 7.91 + <para id="x_644">All modified versions of documents covered by this license, 7.92 including translations, anthologies, compilations and partial 7.93 documents, must meet the following requirements:</para> 7.94 7.95 <orderedlist> 7.96 - <listitem><para>The modified version must be labeled as 7.97 + <listitem><para id="x_645">The modified version must be labeled as 7.98 such.</para> 7.99 </listitem> 7.100 - <listitem><para>The person making the modifications must be 7.101 + <listitem><para id="x_646">The person making the modifications must be 7.102 identified and the modifications dated.</para> 7.103 </listitem> 7.104 - <listitem><para>Acknowledgement of the original author and 7.105 + <listitem><para id="x_647">Acknowledgement of the original author and 7.106 publisher if applicable must be retained according to normal 7.107 academic citation practices.</para> 7.108 </listitem> 7.109 - <listitem><para>The location of the original unmodified document 7.110 + <listitem><para id="x_648">The location of the original unmodified document 7.111 must be identified.</para> 7.112 </listitem> 7.113 - <listitem><para>The original author's (or authors') name(s) may 7.114 + <listitem><para id="x_649">The original author's (or authors') name(s) may 7.115 not be used to assert or imply endorsement of the resulting 7.116 document without the original author's (or authors') 7.117 permission.</para> 7.118 @@ -110,23 +110,23 @@ 7.119 <sect1> 7.120 <title>Good-practice recommendations</title> 7.121 7.122 - <para>In addition to the requirements of this license, it is 7.123 + <para id="x_64a">In addition to the requirements of this license, it is 7.124 requested from and strongly recommended of redistributors 7.125 that:</para> 7.126 7.127 <orderedlist> 7.128 - <listitem><para>If you are distributing Open Publication works 7.129 + <listitem><para id="x_64b">If you are distributing Open Publication works 7.130 on hardcopy or CD-ROM, you provide email notification to the 7.131 authors of your intent to redistribute at least thirty days 7.132 before your manuscript or media freeze, to give the authors 7.133 time to provide updated documents. This notification should 7.134 describe modifications, if any, made to the document.</para> 7.135 </listitem> 7.136 - <listitem><para>All substantive modifications (including 7.137 + <listitem><para id="x_64c">All substantive modifications (including 7.138 deletions) be either clearly marked up in the document or 7.139 else described in an attachment to the document.</para> 7.140 </listitem> 7.141 - <listitem><para>Finally, while it is not mandatory under this 7.142 + <listitem><para id="x_64d">Finally, while it is not mandatory under this 7.143 license, it is considered good form to offer a free copy of 7.144 any hardcopy and CD-ROM expression of an Open 7.145 Publication-licensed work to its author(s).</para> 7.146 @@ -136,7 +136,7 @@ 7.147 <sect1 id="sec.opl.options"> 7.148 <title>License options</title> 7.149 7.150 - <para>The author(s) and/or publisher of an Open 7.151 + <para id="x_64e">The author(s) and/or publisher of an Open 7.152 Publication-licensed document may elect certain options by 7.153 appending language to the reference to or copy of the license. 7.154 These options are considered part of the license instance and 7.155 @@ -144,25 +144,25 @@ 7.156 reference) in derived works.</para> 7.157 7.158 <orderedlist> 7.159 - <listitem><para>To prohibit distribution of substantively 7.160 + <listitem><para id="x_64f">To prohibit distribution of substantively 7.161 modified versions without the explicit permission of the 7.162 author(s). <quote>Substantive modification</quote> is 7.163 defined as a change to the semantic content of the document, 7.164 and excludes mere changes in format or typographical 7.165 corrections.</para> 7.166 </listitem> 7.167 - <listitem><para> To accomplish this, add the phrase 7.168 + <listitem><para id="x_650"> To accomplish this, add the phrase 7.169 <quote>Distribution of substantively modified versions of 7.170 this document is prohibited without the explicit 7.171 permission of the copyright holder.</quote> to the license 7.172 reference or copy.</para> 7.173 </listitem> 7.174 - <listitem><para>To prohibit any publication of this work or 7.175 + <listitem><para id="x_651">To prohibit any publication of this work or 7.176 derivative works in whole or in part in standard (paper) 7.177 book form for commercial purposes is prohibited unless prior 7.178 permission is obtained from the copyright holder.</para> 7.179 </listitem> 7.180 - <listitem><para>To accomplish this, add the phrase 7.181 + <listitem><para id="x_652">To accomplish this, add the phrase 7.182 <quote>Distribution of the work or derivative of the work in 7.183 any standard (paper) book form is prohibited unless prior 7.184 permission is obtained from the copyright holder.</quote>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/autoid.py Fri Mar 20 16:43:35 2009 +0800 8.3 @@ -0,0 +1,47 @@ 8.4 +#!/usr/bin/env python 8.5 +# 8.6 +# Add unique ID attributes to para tags. This script should only be 8.7 +# run by one person, since otherwise it introduces the possibility of 8.8 +# chaotic conflicts among tags. 8.9 + 8.10 +import glob, os, re, sys 8.11 + 8.12 +tagged = re.compile('<para[^>]* id="x_([0-9a-f]+)"[^>]*>', re.M) 8.13 +untagged = re.compile('<para>') 8.14 + 8.15 +names = glob.glob('ch*.xml') + glob.glob('app*.xml') 8.16 + 8.17 +# First pass: find the highest-numbered paragraph ID. 8.18 + 8.19 +biggest_id = 0 8.20 +seen = set() 8.21 +errs = 0 8.22 + 8.23 +for name in names: 8.24 + for m in tagged.finditer(open(name).read()): 8.25 + i = int(m.group(1),16) 8.26 + if i in seen: 8.27 + print >> sys.stderr, '%s: duplication of ID %s' % (name, i) 8.28 + errs += 1 8.29 + seen.add(i) 8.30 + if i > biggest_id: 8.31 + biggest_id = i 8.32 + 8.33 +def retag(s): 8.34 + global biggest_id 8.35 + biggest_id += 1 8.36 + return '<para id="x_%x">' % biggest_id 8.37 + 8.38 +# Second pass: add IDs to paragraphs that currently lack them. 8.39 + 8.40 +for name in names: 8.41 + f = open(name).read() 8.42 + f1 = untagged.sub(retag, f) 8.43 + if f1 != f: 8.44 + tmpname = name + '.tmp' 8.45 + fp = open(tmpname, 'w') 8.46 + fp.write(f1) 8.47 + fp.close() 8.48 + os.rename(tmpname, name) 8.49 + 8.50 +sys.exit(errs)
9.1 --- a/en/ch00-preface.xml Fri Mar 20 15:40:06 2009 +0800 9.2 +++ b/en/ch00-preface.xml Fri Mar 20 16:43:35 2009 +0800 9.3 @@ -1,45 +1,162 @@ 9.4 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 9.5 9.6 <preface id="chap.preface"> 9.7 + <?dbhtml filename="preface.html"?> 9.8 <title>Preface</title> 9.9 9.10 - <para>Distributed revision control is a relatively new territory, 9.11 - and has thus far grown due to people's willingness to strike out 9.12 - into ill-charted territory.</para> 9.13 - 9.14 - <para>I am writing a book about distributed revision control because 9.15 - I believe that it is an important subject that deserves a field 9.16 - guide. I chose to write about Mercurial because it is the easiest 9.17 - tool to learn the terrain with, and yet it scales to the demands 9.18 - of real, challenging environments where many other revision 9.19 - control tools fail.</para> 9.20 + <sect1> 9.21 + <title>Why revision control? Why Mercurial?</title> 9.22 + 9.23 + <para id="x_6d">Revision control is the process of managing multiple 9.24 + versions of a piece of information. In its simplest form, this 9.25 + is something that many people do by hand: every time you modify 9.26 + a file, save it under a new name that contains a number, each 9.27 + one higher than the number of the preceding version.</para> 9.28 + 9.29 + <para id="x_6e">Manually managing multiple versions of even a single file is 9.30 + an error-prone task, though, so software tools to help automate 9.31 + this process have long been available. The earliest automated 9.32 + revision control tools were intended to help a single user to 9.33 + manage revisions of a single file. Over the past few decades, 9.34 + the scope of revision control tools has expanded greatly; they 9.35 + now manage multiple files, and help multiple people to work 9.36 + together. The best modern revision control tools have no 9.37 + problem coping with thousands of people working together on 9.38 + projects that consist of hundreds of thousands of files.</para> 9.39 + 9.40 + <para id="x_6f">The arrival of distributed revision control is relatively 9.41 + recent, and so far this new field has grown due to people's 9.42 + willingness to explore ill-charted territory.</para> 9.43 + 9.44 + <para id="x_70">I am writing a book about distributed revision control 9.45 + because I believe that it is an important subject that deserves 9.46 + a field guide. I chose to write about Mercurial because it is 9.47 + the easiest tool to learn the terrain with, and yet it scales to 9.48 + the demands of real, challenging environments where many other 9.49 + revision control tools buckle.</para> 9.50 + 9.51 + <sect2> 9.52 + <title>Why use revision control?</title> 9.53 + 9.54 + <para id="x_71">There are a number of reasons why you or your team might 9.55 + want to use an automated revision control tool for a 9.56 + project.</para> 9.57 + 9.58 + <itemizedlist> 9.59 + <listitem><para id="x_72">It will track the history and evolution of 9.60 + your project, so you don't have to. For every change, 9.61 + you'll have a log of <emphasis>who</emphasis> made it; 9.62 + <emphasis>why</emphasis> they made it; 9.63 + <emphasis>when</emphasis> they made it; and 9.64 + <emphasis>what</emphasis> the change 9.65 + was.</para></listitem> 9.66 + <listitem><para id="x_73">When you're working with other people, 9.67 + revision control software makes it easier for you to 9.68 + collaborate. For example, when people more or less 9.69 + simultaneously make potentially incompatible changes, the 9.70 + software will help you to identify and resolve those 9.71 + conflicts.</para></listitem> 9.72 + <listitem><para id="x_74">It can help you to recover from mistakes. If 9.73 + you make a change that later turns out to be in error, you 9.74 + can revert to an earlier version of one or more files. In 9.75 + fact, a <emphasis>really</emphasis> good revision control 9.76 + tool will even help you to efficiently figure out exactly 9.77 + when a problem was introduced (see section <xref 9.78 + linkend="sec.undo.bisect"/> for details).</para></listitem> 9.79 + <listitem><para id="x_75">It will help you to work simultaneously on, 9.80 + and manage the drift between, multiple versions of your 9.81 + project.</para></listitem> 9.82 + </itemizedlist> 9.83 + 9.84 + <para id="x_76">Most of these reasons are equally valid---at least in 9.85 + theory---whether you're working on a project by yourself, or 9.86 + with a hundred other people.</para> 9.87 + 9.88 + <para id="x_77">A key question about the practicality of revision control 9.89 + at these two different scales (<quote>lone hacker</quote> and 9.90 + <quote>huge team</quote>) is how its 9.91 + <emphasis>benefits</emphasis> compare to its 9.92 + <emphasis>costs</emphasis>. A revision control tool that's 9.93 + difficult to understand or use is going to impose a high 9.94 + cost.</para> 9.95 + 9.96 + <para id="x_78">A five-hundred-person project is likely to collapse under 9.97 + its own weight almost immediately without a revision control 9.98 + tool and process. In this case, the cost of using revision 9.99 + control might hardly seem worth considering, since 9.100 + <emphasis>without</emphasis> it, failure is almost 9.101 + guaranteed.</para> 9.102 + 9.103 + <para id="x_79">On the other hand, a one-person <quote>quick hack</quote> 9.104 + might seem like a poor place to use a revision control tool, 9.105 + because surely the cost of using one must be close to the 9.106 + overall cost of the project. Right?</para> 9.107 + 9.108 + <para id="x_7a">Mercurial uniquely supports <emphasis>both</emphasis> of 9.109 + these scales of development. You can learn the basics in just 9.110 + a few minutes, and due to its low overhead, you can apply 9.111 + revision control to the smallest of projects with ease. Its 9.112 + simplicity means you won't have a lot of abstruse concepts or 9.113 + command sequences competing for mental space with whatever 9.114 + you're <emphasis>really</emphasis> trying to do. At the same 9.115 + time, Mercurial's high performance and peer-to-peer nature let 9.116 + you scale painlessly to handle large projects.</para> 9.117 + 9.118 + <para id="x_7b">No revision control tool can rescue a poorly run project, 9.119 + but a good choice of tools can make a huge difference to the 9.120 + fluidity with which you can work on a project.</para> 9.121 + 9.122 + </sect2> 9.123 + 9.124 + <sect2> 9.125 + <title>The many names of revision control</title> 9.126 + 9.127 + <para id="x_7c">Revision control is a diverse field, so much so that it is 9.128 + referred to by many names and acronyms. Here are a few of the 9.129 + more common variations you'll encounter:</para> 9.130 + <itemizedlist> 9.131 + <listitem><para id="x_7d">Revision control (RCS)</para></listitem> 9.132 + <listitem><para id="x_7e">Software configuration management (SCM), or 9.133 + configuration management</para></listitem> 9.134 + <listitem><para id="x_7f">Source code management</para></listitem> 9.135 + <listitem><para id="x_80">Source code control, or source 9.136 + control</para></listitem> 9.137 + <listitem><para id="x_81">Version control 9.138 + (VCS)</para></listitem></itemizedlist> 9.139 + <para id="x_82">Some people claim that these terms actually have different 9.140 + meanings, but in practice they overlap so much that there's no 9.141 + agreed or even useful way to tease them apart.</para> 9.142 + 9.143 + </sect2> 9.144 + </sect1> 9.145 9.146 <sect1> 9.147 <title>This book is a work in progress</title> 9.148 9.149 - <para>I am releasing this book while I am still writing it, in the 9.150 - hope that it will prove useful to others. I also hope that 9.151 - readers will contribute as they see fit.</para> 9.152 + <para id="x_83">I am releasing this book while I am still writing it, in the 9.153 + hope that it will prove useful to others. I am writing under an 9.154 + open license in the hope that you, my readers, will contribute 9.155 + feedback and perhaps content of your own.</para> 9.156 9.157 </sect1> 9.158 <sect1> 9.159 <title>About the examples in this book</title> 9.160 9.161 - <para>This book takes an unusual approach to code samples. Every 9.162 + <para id="x_84">This book takes an unusual approach to code samples. Every 9.163 example is <quote>live</quote>---each one is actually the result 9.164 of a shell script that executes the Mercurial commands you see. 9.165 Every time an image of the book is built from its sources, all 9.166 the example scripts are automatically run, and their current 9.167 results compared against their expected results.</para> 9.168 9.169 - <para>The advantage of this approach is that the examples are 9.170 + <para id="x_85">The advantage of this approach is that the examples are 9.171 always accurate; they describe <emphasis>exactly</emphasis> the 9.172 behaviour of the version of Mercurial that's mentioned at the 9.173 front of the book. If I update the version of Mercurial that 9.174 I'm documenting, and the output of some command changes, the 9.175 build fails.</para> 9.176 9.177 - <para>There is a small disadvantage to this approach, which is 9.178 + <para id="x_86">There is a small disadvantage to this approach, which is 9.179 that the dates and times you'll see in examples tend to be 9.180 <quote>squashed</quote> together in a way that they wouldn't be 9.181 if the same commands were being typed by a human. Where a human 9.182 @@ -47,27 +164,586 @@ 9.183 resulting timestamps correspondingly spread out, my automated 9.184 example scripts run many commands in one second.</para> 9.185 9.186 - <para>As an instance of this, several consecutive commits in an 9.187 + <para id="x_87">As an instance of this, several consecutive commits in an 9.188 example can show up as having occurred during the same second. 9.189 You can see this occur in the <literal 9.190 role="hg-ext">bisect</literal> example in section <xref 9.191 id="sec.undo.bisect"/>, for instance.</para> 9.192 9.193 - <para>So when you're reading examples, don't place too much weight 9.194 + <para id="x_88">So when you're reading examples, don't place too much weight 9.195 on the dates or times you see in the output of commands. But 9.196 <emphasis>do</emphasis> be confident that the behaviour you're 9.197 seeing is consistent and reproducible.</para> 9.198 9.199 </sect1> 9.200 - <sect1> 9.201 - <title>Colophon---this book is Free</title> 9.202 - 9.203 - <para>This book is licensed under the Open Publication License, 9.204 + 9.205 + <sect1> 9.206 + <title>Trends in the field</title> 9.207 + 9.208 + <para id="x_89">There has been an unmistakable trend in the development and 9.209 + use of revision control tools over the past four decades, as 9.210 + people have become familiar with the capabilities of their tools 9.211 + and constrained by their limitations.</para> 9.212 + 9.213 + <para id="x_8a">The first generation began by managing single files on 9.214 + individual computers. Although these tools represented a huge 9.215 + advance over ad-hoc manual revision control, their locking model 9.216 + and reliance on a single computer limited them to small, 9.217 + tightly-knit teams.</para> 9.218 + 9.219 + <para id="x_8b">The second generation loosened these constraints by moving 9.220 + to network-centered architectures, and managing entire projects 9.221 + at a time. As projects grew larger, they ran into new problems. 9.222 + With clients needing to talk to servers very frequently, server 9.223 + scaling became an issue for large projects. An unreliable 9.224 + network connection could prevent remote users from being able to 9.225 + talk to the server at all. As open source projects started 9.226 + making read-only access available anonymously to anyone, people 9.227 + without commit privileges found that they could not use the 9.228 + tools to interact with a project in a natural way, as they could 9.229 + not record their changes.</para> 9.230 + 9.231 + <para id="x_8c">The current generation of revision control tools is 9.232 + peer-to-peer in nature. All of these systems have dropped the 9.233 + dependency on a single central server, and allow people to 9.234 + distribute their revision control data to where it's actually 9.235 + needed. Collaboration over the Internet has moved from 9.236 + constrained by technology to a matter of choice and consensus. 9.237 + Modern tools can operate offline indefinitely and autonomously, 9.238 + with a network connection only needed when syncing changes with 9.239 + another repository.</para> 9.240 + 9.241 + </sect1> 9.242 + <sect1> 9.243 + <title>A few of the advantages of distributed revision 9.244 + control</title> 9.245 + 9.246 + <para id="x_8d">Even though distributed revision control tools have for 9.247 + several years been as robust and usable as their 9.248 + previous-generation counterparts, people using older tools have 9.249 + not yet necessarily woken up to their advantages. There are a 9.250 + number of ways in which distributed tools shine relative to 9.251 + centralised ones.</para> 9.252 + 9.253 + <para id="x_8e">For an individual developer, distributed tools are almost 9.254 + always much faster than centralised tools. This is for a simple 9.255 + reason: a centralised tool needs to talk over the network for 9.256 + many common operations, because most metadata is stored in a 9.257 + single copy on the central server. A distributed tool stores 9.258 + all of its metadata locally. All else being equal, talking over 9.259 + the network adds overhead to a centralised tool. Don't 9.260 + underestimate the value of a snappy, responsive tool: you're 9.261 + going to spend a lot of time interacting with your revision 9.262 + control software.</para> 9.263 + 9.264 + <para id="x_8f">Distributed tools are indifferent to the vagaries of your 9.265 + server infrastructure, again because they replicate metadata to 9.266 + so many locations. If you use a centralised system and your 9.267 + server catches fire, you'd better hope that your backup media 9.268 + are reliable, and that your last backup was recent and actually 9.269 + worked. With a distributed tool, you have many backups 9.270 + available on every contributor's computer.</para> 9.271 + 9.272 + <para id="x_90">The reliability of your network will affect distributed 9.273 + tools far less than it will centralised tools. You can't even 9.274 + use a centralised tool without a network connection, except for 9.275 + a few highly constrained commands. With a distributed tool, if 9.276 + your network connection goes down while you're working, you may 9.277 + not even notice. The only thing you won't be able to do is talk 9.278 + to repositories on other computers, something that is relatively 9.279 + rare compared with local operations. If you have a far-flung 9.280 + team of collaborators, this may be significant.</para> 9.281 + 9.282 + <sect2> 9.283 + <title>Advantages for open source projects</title> 9.284 + 9.285 + <para id="x_91">If you take a shine to an open source project and decide 9.286 + that you would like to start hacking on it, and that project 9.287 + uses a distributed revision control tool, you are at once a 9.288 + peer with the people who consider themselves the 9.289 + <quote>core</quote> of that project. If they publish their 9.290 + repositories, you can immediately copy their project history, 9.291 + start making changes, and record your work, using the same 9.292 + tools in the same ways as insiders. By contrast, with a 9.293 + centralised tool, you must use the software in a <quote>read 9.294 + only</quote> mode unless someone grants you permission to 9.295 + commit changes to their central server. Until then, you won't 9.296 + be able to record changes, and your local modifications will 9.297 + be at risk of corruption any time you try to update your 9.298 + client's view of the repository.</para> 9.299 + 9.300 + <sect3> 9.301 + <title>The forking non-problem</title> 9.302 + 9.303 + <para id="x_92">It has been suggested that distributed revision control 9.304 + tools pose some sort of risk to open source projects because 9.305 + they make it easy to <quote>fork</quote> the development of 9.306 + a project. A fork happens when there are differences in 9.307 + opinion or attitude between groups of developers that cause 9.308 + them to decide that they can't work together any longer. 9.309 + Each side takes a more or less complete copy of the 9.310 + project's source code, and goes off in its own 9.311 + direction.</para> 9.312 + 9.313 + <para id="x_93">Sometimes the camps in a fork decide to reconcile their 9.314 + differences. With a centralised revision control system, the 9.315 + <emphasis>technical</emphasis> process of reconciliation is 9.316 + painful, and has to be performed largely by hand. You have 9.317 + to decide whose revision history is going to 9.318 + <quote>win</quote>, and graft the other team's changes into 9.319 + the tree somehow. This usually loses some or all of one 9.320 + side's revision history.</para> 9.321 + 9.322 + <para id="x_94">What distributed tools do with respect to forking is 9.323 + they make forking the <emphasis>only</emphasis> way to 9.324 + develop a project. Every single change that you make is 9.325 + potentially a fork point. The great strength of this 9.326 + approach is that a distributed revision control tool has to 9.327 + be really good at <emphasis>merging</emphasis> forks, 9.328 + because forks are absolutely fundamental: they happen all 9.329 + the time.</para> 9.330 + 9.331 + <para id="x_95">If every piece of work that everybody does, all the 9.332 + time, is framed in terms of forking and merging, then what 9.333 + the open source world refers to as a <quote>fork</quote> 9.334 + becomes <emphasis>purely</emphasis> a social issue. If 9.335 + anything, distributed tools <emphasis>lower</emphasis> the 9.336 + likelihood of a fork:</para> 9.337 + <itemizedlist> 9.338 + <listitem><para id="x_96">They eliminate the social distinction that 9.339 + centralised tools impose: that between insiders (people 9.340 + with commit access) and outsiders (people 9.341 + without).</para></listitem> 9.342 + <listitem><para id="x_97">They make it easier to reconcile after a 9.343 + social fork, because all that's involved from the 9.344 + perspective of the revision control software is just 9.345 + another merge.</para></listitem></itemizedlist> 9.346 + 9.347 + <para id="x_98">Some people resist distributed tools because they want 9.348 + to retain tight control over their projects, and they 9.349 + believe that centralised tools give them this control. 9.350 + However, if you're of this belief, and you publish your CVS 9.351 + or Subversion repositories publicly, there are plenty of 9.352 + tools available that can pull out your entire project's 9.353 + history (albeit slowly) and recreate it somewhere that you 9.354 + don't control. So while your control in this case is 9.355 + illusory, you are forgoing the ability to fluidly 9.356 + collaborate with whatever people feel compelled to mirror 9.357 + and fork your history.</para> 9.358 + 9.359 + </sect3> 9.360 + </sect2> 9.361 + <sect2> 9.362 + <title>Advantages for commercial projects</title> 9.363 + 9.364 + <para id="x_99">Many commercial projects are undertaken by teams that are 9.365 + scattered across the globe. Contributors who are far from a 9.366 + central server will see slower command execution and perhaps 9.367 + less reliability. Commercial revision control systems attempt 9.368 + to ameliorate these problems with remote-site replication 9.369 + add-ons that are typically expensive to buy and cantankerous 9.370 + to administer. A distributed system doesn't suffer from these 9.371 + problems in the first place. Better yet, you can easily set 9.372 + up multiple authoritative servers, say one per site, so that 9.373 + there's no redundant communication between repositories over 9.374 + expensive long-haul network links.</para> 9.375 + 9.376 + <para id="x_9a">Centralised revision control systems tend to have 9.377 + relatively low scalability. It's not unusual for an expensive 9.378 + centralised system to fall over under the combined load of 9.379 + just a few dozen concurrent users. Once again, the typical 9.380 + response tends to be an expensive and clunky replication 9.381 + facility. Since the load on a central server---if you have 9.382 + one at all---is many times lower with a distributed tool 9.383 + (because all of the data is replicated everywhere), a single 9.384 + cheap server can handle the needs of a much larger team, and 9.385 + replication to balance load becomes a simple matter of 9.386 + scripting.</para> 9.387 + 9.388 + <para id="x_9b">If you have an employee in the field, troubleshooting a 9.389 + problem at a customer's site, they'll benefit from distributed 9.390 + revision control. The tool will let them generate custom 9.391 + builds, try different fixes in isolation from each other, and 9.392 + search efficiently through history for the sources of bugs and 9.393 + regressions in the customer's environment, all without needing 9.394 + to connect to your company's network.</para> 9.395 + 9.396 + </sect2> 9.397 + </sect1> 9.398 + <sect1> 9.399 + <title>Why choose Mercurial?</title> 9.400 + 9.401 + <para id="x_9c">Mercurial has a unique set of properties that make it a 9.402 + particularly good choice as a revision control system.</para> 9.403 + <itemizedlist> 9.404 + <listitem><para id="x_9d">It is easy to learn and use.</para></listitem> 9.405 + <listitem><para id="x_9e">It is lightweight.</para></listitem> 9.406 + <listitem><para id="x_9f">It scales excellently.</para></listitem> 9.407 + <listitem><para id="x_a0">It is easy to 9.408 + customise.</para></listitem></itemizedlist> 9.409 + 9.410 + <para id="x_a1">If you are at all familiar with revision control systems, 9.411 + you should be able to get up and running with Mercurial in less 9.412 + than five minutes. Even if not, it will take no more than a few 9.413 + minutes longer. Mercurial's command and feature sets are 9.414 + generally uniform and consistent, so you can keep track of a few 9.415 + general rules instead of a host of exceptions.</para> 9.416 + 9.417 + <para id="x_a2">On a small project, you can start working with Mercurial in 9.418 + moments. Creating new changes and branches; transferring changes 9.419 + around (whether locally or over a network); and history and 9.420 + status operations are all fast. Mercurial attempts to stay 9.421 + nimble and largely out of your way by combining low cognitive 9.422 + overhead with blazingly fast operations.</para> 9.423 + 9.424 + <para id="x_a3">The usefulness of Mercurial is not limited to small 9.425 + projects: it is used by projects with hundreds to thousands of 9.426 + contributors, each containing tens of thousands of files and 9.427 + hundreds of megabytes of source code.</para> 9.428 + 9.429 + <para id="x_a4">If the core functionality of Mercurial is not enough for 9.430 + you, it's easy to build on. Mercurial is well suited to 9.431 + scripting tasks, and its clean internals and implementation in 9.432 + Python make it easy to add features in the form of extensions. 9.433 + There are a number of popular and useful extensions already 9.434 + available, ranging from helping to identify bugs to improving 9.435 + performance.</para> 9.436 + 9.437 + </sect1> 9.438 + <sect1> 9.439 + <title>Mercurial compared with other tools</title> 9.440 + 9.441 + <para id="x_a5">Before you read on, please understand that this section 9.442 + necessarily reflects my own experiences, interests, and (dare I 9.443 + say it) biases. I have used every one of the revision control 9.444 + tools listed below, in most cases for several years at a 9.445 + time.</para> 9.446 + 9.447 + 9.448 + <sect2> 9.449 + <title>Subversion</title> 9.450 + 9.451 + <para id="x_a6">Subversion is a popular revision control tool, developed 9.452 + to replace CVS. It has a centralised client/server 9.453 + architecture.</para> 9.454 + 9.455 + <para id="x_a7">Subversion and Mercurial have similarly named commands for 9.456 + performing the same operations, so if you're familiar with 9.457 + one, it is easy to learn to use the other. Both tools are 9.458 + portable to all popular operating systems.</para> 9.459 + 9.460 + <para id="x_a8">Prior to version 1.5, Subversion had no useful support for 9.461 + merges. At the time of writing, its merge tracking capability 9.462 + is new, and known to be <ulink 9.463 + url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">complicated 9.464 + and buggy</ulink>.</para> 9.465 + 9.466 + <para id="x_a9">Mercurial has a substantial performance advantage over 9.467 + Subversion on every revision control operation I have 9.468 + benchmarked. I have measured its advantage as ranging from a 9.469 + factor of two to a factor of six when compared with Subversion 9.470 + 1.4.3's <emphasis>ra_local</emphasis> file store, which is the 9.471 + fastest access method available. In more realistic 9.472 + deployments involving a network-based store, Subversion will 9.473 + be at a substantially larger disadvantage. Because many 9.474 + Subversion commands must talk to the server and Subversion 9.475 + does not have useful replication facilities, server capacity 9.476 + and network bandwidth become bottlenecks for modestly large 9.477 + projects.</para> 9.478 + 9.479 + <para id="x_aa">Additionally, Subversion incurs substantial storage 9.480 + overhead to avoid network transactions for a few common 9.481 + operations, such as finding modified files 9.482 + (<literal>status</literal>) and displaying modifications 9.483 + against the current revision (<literal>diff</literal>). As a 9.484 + result, a Subversion working copy is often the same size as, 9.485 + or larger than, a Mercurial repository and working directory, 9.486 + even though the Mercurial repository contains a complete 9.487 + history of the project.</para> 9.488 + 9.489 + <para id="x_ab">Subversion is widely supported by third party tools. 9.490 + Mercurial currently lags considerably in this area. This gap 9.491 + is closing, however, and indeed some of Mercurial's GUI tools 9.492 + now outshine their Subversion equivalents. Like Mercurial, 9.493 + Subversion has an excellent user manual.</para> 9.494 + 9.495 + <para id="x_ac">Because Subversion doesn't store revision history on the 9.496 + client, it is well suited to managing projects that deal with 9.497 + lots of large, opaque binary files. If you check in fifty 9.498 + revisions to an incompressible 10MB file, Subversion's 9.499 + client-side space usage stays constant The space used by any 9.500 + distributed SCM will grow rapidly in proportion to the number 9.501 + of revisions, because the differences between each revision 9.502 + are large.</para> 9.503 + 9.504 + <para id="x_ad">In addition, it's often difficult or, more usually, 9.505 + impossible to merge different versions of a binary file. 9.506 + Subversion's ability to let a user lock a file, so that they 9.507 + temporarily have the exclusive right to commit changes to it, 9.508 + can be a significant advantage to a project where binary files 9.509 + are widely used.</para> 9.510 + 9.511 + <para id="x_ae">Mercurial can import revision history from a Subversion 9.512 + repository. It can also export revision history to a 9.513 + Subversion repository. This makes it easy to <quote>test the 9.514 + waters</quote> and use Mercurial and Subversion in parallel 9.515 + before deciding to switch. History conversion is incremental, 9.516 + so you can perform an initial conversion, then small 9.517 + additional conversions afterwards to bring in new 9.518 + changes.</para> 9.519 + 9.520 + 9.521 + </sect2> 9.522 + <sect2> 9.523 + <title>Git</title> 9.524 + 9.525 + <para id="x_af">Git is a distributed revision control tool that was 9.526 + developed for managing the Linux kernel source tree. Like 9.527 + Mercurial, its early design was somewhat influenced by 9.528 + Monotone.</para> 9.529 + 9.530 + <para id="x_b0">Git has a very large command set, with version 1.5.0 9.531 + providing 139 individual commands. It has something of a 9.532 + reputation for being difficult to learn. Compared to Git, 9.533 + Mercurial has a strong focus on simplicity.</para> 9.534 + 9.535 + <para id="x_b1">In terms of performance, Git is extremely fast. In 9.536 + several cases, it is faster than Mercurial, at least on Linux, 9.537 + while Mercurial performs better on other operations. However, 9.538 + on Windows, the performance and general level of support that 9.539 + Git provides is, at the time of writing, far behind that of 9.540 + Mercurial.</para> 9.541 + 9.542 + <para id="x_b2">While a Mercurial repository needs no maintenance, a Git 9.543 + repository requires frequent manual <quote>repacks</quote> of 9.544 + its metadata. Without these, performance degrades, while 9.545 + space usage grows rapidly. A server that contains many Git 9.546 + repositories that are not rigorously and frequently repacked 9.547 + will become heavily disk-bound during backups, and there have 9.548 + been instances of daily backups taking far longer than 24 9.549 + hours as a result. A freshly packed Git repository is 9.550 + slightly smaller than a Mercurial repository, but an unpacked 9.551 + repository is several orders of magnitude larger.</para> 9.552 + 9.553 + <para id="x_b3">The core of Git is written in C. Many Git commands are 9.554 + implemented as shell or Perl scripts, and the quality of these 9.555 + scripts varies widely. I have encountered several instances 9.556 + where scripts charged along blindly in the presence of errors 9.557 + that should have been fatal.</para> 9.558 + 9.559 + <para id="x_b4">Mercurial can import revision history from a Git 9.560 + repository.</para> 9.561 + 9.562 + 9.563 + </sect2> 9.564 + <sect2> 9.565 + <title>CVS</title> 9.566 + 9.567 + <para id="x_b5">CVS is probably the most widely used revision control tool 9.568 + in the world. Due to its age and internal untidiness, it has 9.569 + been only lightly maintained for many years.</para> 9.570 + 9.571 + <para id="x_b6">It has a centralised client/server architecture. It does 9.572 + not group related file changes into atomic commits, making it 9.573 + easy for people to <quote>break the build</quote>: one person 9.574 + can successfully commit part of a change and then be blocked 9.575 + by the need for a merge, causing other people to see only a 9.576 + portion of the work they intended to do. This also affects 9.577 + how you work with project history. If you want to see all of 9.578 + the modifications someone made as part of a task, you will 9.579 + need to manually inspect the descriptions and timestamps of 9.580 + the changes made to each file involved (if you even know what 9.581 + those files were).</para> 9.582 + 9.583 + <para id="x_b7">CVS has a muddled notion of tags and branches that I will 9.584 + not attempt to even describe. It does not support renaming of 9.585 + files or directories well, making it easy to corrupt a 9.586 + repository. It has almost no internal consistency checking 9.587 + capabilities, so it is usually not even possible to tell 9.588 + whether or how a repository is corrupt. I would not recommend 9.589 + CVS for any project, existing or new.</para> 9.590 + 9.591 + <para id="x_b8">Mercurial can import CVS revision history. However, there 9.592 + are a few caveats that apply; these are true of every other 9.593 + revision control tool's CVS importer, too. Due to CVS's lack 9.594 + of atomic changes and unversioned filesystem hierarchy, it is 9.595 + not possible to reconstruct CVS history completely accurately; 9.596 + some guesswork is involved, and renames will usually not show 9.597 + up. Because a lot of advanced CVS administration has to be 9.598 + done by hand and is hence error-prone, it's common for CVS 9.599 + importers to run into multiple problems with corrupted 9.600 + repositories (completely bogus revision timestamps and files 9.601 + that have remained locked for over a decade are just two of 9.602 + the less interesting problems I can recall from personal 9.603 + experience).</para> 9.604 + 9.605 + <para id="x_b9">Mercurial can import revision history from a CVS 9.606 + repository.</para> 9.607 + 9.608 + 9.609 + </sect2> 9.610 + <sect2> 9.611 + <title>Commercial tools</title> 9.612 + 9.613 + <para id="x_ba">Perforce has a centralised client/server architecture, 9.614 + with no client-side caching of any data. Unlike modern 9.615 + revision control tools, Perforce requires that a user run a 9.616 + command to inform the server about every file they intend to 9.617 + edit.</para> 9.618 + 9.619 + <para id="x_bb">The performance of Perforce is quite good for small teams, 9.620 + but it falls off rapidly as the number of users grows beyond a 9.621 + few dozen. Modestly large Perforce installations require the 9.622 + deployment of proxies to cope with the load their users 9.623 + generate.</para> 9.624 + 9.625 + 9.626 + </sect2> 9.627 + <sect2> 9.628 + <title>Choosing a revision control tool</title> 9.629 + 9.630 + <para id="x_bc">With the exception of CVS, all of the tools listed above 9.631 + have unique strengths that suit them to particular styles of 9.632 + work. There is no single revision control tool that is best 9.633 + in all situations.</para> 9.634 + 9.635 + <para id="x_bd">As an example, Subversion is a good choice for working 9.636 + with frequently edited binary files, due to its centralised 9.637 + nature and support for file locking.</para> 9.638 + 9.639 + <para id="x_be">I personally find Mercurial's properties of simplicity, 9.640 + performance, and good merge support to be a compelling 9.641 + combination that has served me well for several years.</para> 9.642 + 9.643 + 9.644 + </sect2> 9.645 + </sect1> 9.646 + <sect1> 9.647 + <title>Switching from another tool to Mercurial</title> 9.648 + 9.649 + <para id="x_bf">Mercurial is bundled with an extension named <literal 9.650 + role="hg-ext">convert</literal>, which can incrementally 9.651 + import revision history from several other revision control 9.652 + tools. By <quote>incremental</quote>, I mean that you can 9.653 + convert all of a project's history to date in one go, then rerun 9.654 + the conversion later to obtain new changes that happened after 9.655 + the initial conversion.</para> 9.656 + 9.657 + <para id="x_c0">The revision control tools supported by <literal 9.658 + role="hg-ext">convert</literal> are as follows:</para> 9.659 + <itemizedlist> 9.660 + <listitem><para id="x_c1">Subversion</para></listitem> 9.661 + <listitem><para id="x_c2">CVS</para></listitem> 9.662 + <listitem><para id="x_c3">Git</para></listitem> 9.663 + <listitem><para id="x_c4">Darcs</para></listitem></itemizedlist> 9.664 + 9.665 + <para id="x_c5">In addition, <literal role="hg-ext">convert</literal> can 9.666 + export changes from Mercurial to Subversion. This makes it 9.667 + possible to try Subversion and Mercurial in parallel before 9.668 + committing to a switchover, without risking the loss of any 9.669 + work.</para> 9.670 + 9.671 + <para id="x_c6">The <command role="hg-ext-convert">convert</command> command 9.672 + is easy to use. Simply point it at the path or URL of the 9.673 + source repository, optionally give it the name of the 9.674 + destination repository, and it will start working. After the 9.675 + initial conversion, just run the same command again to import 9.676 + new changes.</para> 9.677 + </sect1> 9.678 + 9.679 + <sect1> 9.680 + <title>A short history of revision control</title> 9.681 + 9.682 + <para id="x_c7">The best known of the old-time revision control tools is 9.683 + SCCS (Source Code Control System), which Marc Rochkind wrote at 9.684 + Bell Labs, in the early 1970s. SCCS operated on individual 9.685 + files, and required every person working on a project to have 9.686 + access to a shared workspace on a single system. Only one 9.687 + person could modify a file at any time; arbitration for access 9.688 + to files was via locks. It was common for people to lock files, 9.689 + and later forget to unlock them, preventing anyone else from 9.690 + modifying those files without the help of an 9.691 + administrator.</para> 9.692 + 9.693 + <para id="x_c8">Walter Tichy developed a free alternative to SCCS in the 9.694 + early 1980s; he called his program RCS (Revision Control System). 9.695 + Like SCCS, RCS required developers to work in a single shared 9.696 + workspace, and to lock files to prevent multiple people from 9.697 + modifying them simultaneously.</para> 9.698 + 9.699 + <para id="x_c9">Later in the 1980s, Dick Grune used RCS as a building block 9.700 + for a set of shell scripts he initially called cmt, but then 9.701 + renamed to CVS (Concurrent Versions System). The big innovation 9.702 + of CVS was that it let developers work simultaneously and 9.703 + somewhat independently in their own personal workspaces. The 9.704 + personal workspaces prevented developers from stepping on each 9.705 + other's toes all the time, as was common with SCCS and RCS. Each 9.706 + developer had a copy of every project file, and could modify 9.707 + their copies independently. They had to merge their edits prior 9.708 + to committing changes to the central repository.</para> 9.709 + 9.710 + <para id="x_ca">Brian Berliner took Grune's original scripts and rewrote 9.711 + them in C, releasing in 1989 the code that has since developed 9.712 + into the modern version of CVS. CVS subsequently acquired the 9.713 + ability to operate over a network connection, giving it a 9.714 + client/server architecture. CVS's architecture is centralised; 9.715 + only the server has a copy of the history of the project. Client 9.716 + workspaces just contain copies of recent versions of the 9.717 + project's files, and a little metadata to tell them where the 9.718 + server is. CVS has been enormously successful; it is probably 9.719 + the world's most widely used revision control system.</para> 9.720 + 9.721 + <para id="x_cb">In the early 1990s, Sun Microsystems developed an early 9.722 + distributed revision control system, called TeamWare. A 9.723 + TeamWare workspace contains a complete copy of the project's 9.724 + history. TeamWare has no notion of a central repository. (CVS 9.725 + relied upon RCS for its history storage; TeamWare used 9.726 + SCCS.)</para> 9.727 + 9.728 + <para id="x_cc">As the 1990s progressed, awareness grew of a number of 9.729 + problems with CVS. It records simultaneous changes to multiple 9.730 + files individually, instead of grouping them together as a 9.731 + single logically atomic operation. It does not manage its file 9.732 + hierarchy well; it is easy to make a mess of a repository by 9.733 + renaming files and directories. Worse, its source code is 9.734 + difficult to read and maintain, which made the <quote>pain 9.735 + level</quote> of fixing these architectural problems 9.736 + prohibitive.</para> 9.737 + 9.738 + <para id="x_cd">In 2001, Jim Blandy and Karl Fogel, two developers who had 9.739 + worked on CVS, started a project to replace it with a tool that 9.740 + would have a better architecture and cleaner code. The result, 9.741 + Subversion, does not stray from CVS's centralised client/server 9.742 + model, but it adds multi-file atomic commits, better namespace 9.743 + management, and a number of other features that make it a 9.744 + generally better tool than CVS. Since its initial release, it 9.745 + has rapidly grown in popularity.</para> 9.746 + 9.747 + <para id="x_ce">More or less simultaneously, Graydon Hoare began working on 9.748 + an ambitious distributed revision control system that he named 9.749 + Monotone. While Monotone addresses many of CVS's design flaws 9.750 + and has a peer-to-peer architecture, it goes beyond earlier (and 9.751 + subsequent) revision control tools in a number of innovative 9.752 + ways. It uses cryptographic hashes as identifiers, and has an 9.753 + integral notion of <quote>trust</quote> for code from different 9.754 + sources.</para> 9.755 + 9.756 + <para id="x_cf">Mercurial began life in 2005. While a few aspects of its 9.757 + design are influenced by Monotone, Mercurial focuses on ease of 9.758 + use, high performance, and scalability to very large 9.759 + projects.</para> 9.760 + 9.761 + </sect1> 9.762 + 9.763 + <sect1> 9.764 + <title>Colophon&emdash;this book is Free</title> 9.765 + 9.766 + <para id="x_d0">This book is licensed under the Open Publication License, 9.767 and is produced entirely using Free Software tools. It is 9.768 typeset with DocBook XML. Illustrations are drawn and rendered with 9.769 <ulink url="http://www.inkscape.org/">Inkscape</ulink>.</para> 9.770 9.771 - <para>The complete source code for this book is published as a 9.772 + <para id="x_d1">The complete source code for this book is published as a 9.773 Mercurial repository, at <ulink 9.774 url="http://hg.serpentine.com/mercurial/book">http://hg.serpentine.com/mercurial/book</ulink>.</para> 9.775
10.1 --- a/en/ch01-intro.xml Fri Mar 20 15:40:06 2009 +0800 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,680 +0,0 @@ 10.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 10.5 - 10.6 -<chapter id="chap.intro"> 10.7 - <?dbhtml filename="introduction.html"?> 10.8 - <title>Introduction</title> 10.9 - 10.10 - <sect1> 10.11 - <title>About revision control</title> 10.12 - 10.13 - <para>Revision control is the process of managing multiple 10.14 - versions of a piece of information. In its simplest form, this 10.15 - is something that many people do by hand: every time you modify 10.16 - a file, save it under a new name that contains a number, each 10.17 - one higher than the number of the preceding version.</para> 10.18 - 10.19 - <para>Manually managing multiple versions of even a single file is 10.20 - an error-prone task, though, so software tools to help automate 10.21 - this process have long been available. The earliest automated 10.22 - revision control tools were intended to help a single user to 10.23 - manage revisions of a single file. Over the past few decades, 10.24 - the scope of revision control tools has expanded greatly; they 10.25 - now manage multiple files, and help multiple people to work 10.26 - together. The best modern revision control tools have no 10.27 - problem coping with thousands of people working together on 10.28 - projects that consist of hundreds of thousands of files.</para> 10.29 - 10.30 - <sect2> 10.31 - <title>Why use revision control?</title> 10.32 - 10.33 - <para>There are a number of reasons why you or your team might 10.34 - want to use an automated revision control tool for a 10.35 - project.</para> 10.36 - <itemizedlist> 10.37 - <listitem><para>It will track the history and evolution of 10.38 - your project, so you don't have to. For every change, 10.39 - you'll have a log of <emphasis>who</emphasis> made it; 10.40 - <emphasis>why</emphasis> they made it; 10.41 - <emphasis>when</emphasis> they made it; and 10.42 - <emphasis>what</emphasis> the change 10.43 - was.</para></listitem> 10.44 - <listitem><para>When you're working with other people, 10.45 - revision control software makes it easier for you to 10.46 - collaborate. For example, when people more or less 10.47 - simultaneously make potentially incompatible changes, the 10.48 - software will help you to identify and resolve those 10.49 - conflicts.</para></listitem> 10.50 - <listitem><para>It can help you to recover from mistakes. If 10.51 - you make a change that later turns out to be in error, you 10.52 - can revert to an earlier version of one or more files. In 10.53 - fact, a <emphasis>really</emphasis> good revision control 10.54 - tool will even help you to efficiently figure out exactly 10.55 - when a problem was introduced (see section <xref 10.56 - linkend="sec.undo.bisect"/> for details).</para></listitem> 10.57 - <listitem><para>It will help you to work simultaneously on, 10.58 - and manage the drift between, multiple versions of your 10.59 - project.</para></listitem></itemizedlist> 10.60 - <para>Most of these reasons are equally valid---at least in 10.61 - theory---whether you're working on a project by yourself, or 10.62 - with a hundred other people.</para> 10.63 - 10.64 - <para>A key question about the practicality of revision control 10.65 - at these two different scales (<quote>lone hacker</quote> and 10.66 - <quote>huge team</quote>) is how its 10.67 - <emphasis>benefits</emphasis> compare to its 10.68 - <emphasis>costs</emphasis>. A revision control tool that's 10.69 - difficult to understand or use is going to impose a high 10.70 - cost.</para> 10.71 - 10.72 - <para>A five-hundred-person project is likely to collapse under 10.73 - its own weight almost immediately without a revision control 10.74 - tool and process. In this case, the cost of using revision 10.75 - control might hardly seem worth considering, since 10.76 - <emphasis>without</emphasis> it, failure is almost 10.77 - guaranteed.</para> 10.78 - 10.79 - <para>On the other hand, a one-person <quote>quick hack</quote> 10.80 - might seem like a poor place to use a revision control tool, 10.81 - because surely the cost of using one must be close to the 10.82 - overall cost of the project. Right?</para> 10.83 - 10.84 - <para>Mercurial uniquely supports <emphasis>both</emphasis> of 10.85 - these scales of development. You can learn the basics in just 10.86 - a few minutes, and due to its low overhead, you can apply 10.87 - revision control to the smallest of projects with ease. Its 10.88 - simplicity means you won't have a lot of abstruse concepts or 10.89 - command sequences competing for mental space with whatever 10.90 - you're <emphasis>really</emphasis> trying to do. At the same 10.91 - time, Mercurial's high performance and peer-to-peer nature let 10.92 - you scale painlessly to handle large projects.</para> 10.93 - 10.94 - <para>No revision control tool can rescue a poorly run project, 10.95 - but a good choice of tools can make a huge difference to the 10.96 - fluidity with which you can work on a project.</para> 10.97 - 10.98 - </sect2> 10.99 - <sect2> 10.100 - <title>The many names of revision control</title> 10.101 - 10.102 - <para>Revision control is a diverse field, so much so that it 10.103 - doesn't actually have a single name or acronym. Here are a 10.104 - few of the more common names and acronyms you'll 10.105 - encounter:</para> 10.106 - <itemizedlist> 10.107 - <listitem><para>Revision control (RCS)</para></listitem> 10.108 - <listitem><para>Software configuration management (SCM), or 10.109 - configuration management</para></listitem> 10.110 - <listitem><para>Source code management</para></listitem> 10.111 - <listitem><para>Source code control, or source 10.112 - control</para></listitem> 10.113 - <listitem><para>Version control 10.114 - (VCS)</para></listitem></itemizedlist> 10.115 - <para>Some people claim that these terms actually have different 10.116 - meanings, but in practice they overlap so much that there's no 10.117 - agreed or even useful way to tease them apart.</para> 10.118 - 10.119 - </sect2> 10.120 - </sect1> 10.121 - <sect1> 10.122 - <title>A short history of revision control</title> 10.123 - 10.124 - <para>The best known of the old-time revision control tools is 10.125 - SCCS (Source Code Control System), which Marc Rochkind wrote at 10.126 - Bell Labs, in the early 1970s. SCCS operated on individual 10.127 - files, and required every person working on a project to have 10.128 - access to a shared workspace on a single system. Only one 10.129 - person could modify a file at any time; arbitration for access 10.130 - to files was via locks. It was common for people to lock files, 10.131 - and later forget to unlock them, preventing anyone else from 10.132 - modifying those files without the help of an 10.133 - administrator.</para> 10.134 - 10.135 - <para>Walter Tichy developed a free alternative to SCCS in the 10.136 - early 1980s; he called his program RCS (Revision Control System). 10.137 - Like SCCS, RCS required developers to work in a single shared 10.138 - workspace, and to lock files to prevent multiple people from 10.139 - modifying them simultaneously.</para> 10.140 - 10.141 - <para>Later in the 1980s, Dick Grune used RCS as a building block 10.142 - for a set of shell scripts he initially called cmt, but then 10.143 - renamed to CVS (Concurrent Versions System). The big innovation 10.144 - of CVS was that it let developers work simultaneously and 10.145 - somewhat independently in their own personal workspaces. The 10.146 - personal workspaces prevented developers from stepping on each 10.147 - other's toes all the time, as was common with SCCS and RCS. Each 10.148 - developer had a copy of every project file, and could modify 10.149 - their copies independently. They had to merge their edits prior 10.150 - to committing changes to the central repository.</para> 10.151 - 10.152 - <para>Brian Berliner took Grune's original scripts and rewrote 10.153 - them in C, releasing in 1989 the code that has since developed 10.154 - into the modern version of CVS. CVS subsequently acquired the 10.155 - ability to operate over a network connection, giving it a 10.156 - client/server architecture. CVS's architecture is centralised; 10.157 - only the server has a copy of the history of the project. Client 10.158 - workspaces just contain copies of recent versions of the 10.159 - project's files, and a little metadata to tell them where the 10.160 - server is. CVS has been enormously successful; it is probably 10.161 - the world's most widely used revision control system.</para> 10.162 - 10.163 - <para>In the early 1990s, Sun Microsystems developed an early 10.164 - distributed revision control system, called TeamWare. A 10.165 - TeamWare workspace contains a complete copy of the project's 10.166 - history. TeamWare has no notion of a central repository. (CVS 10.167 - relied upon RCS for its history storage; TeamWare used 10.168 - SCCS.)</para> 10.169 - 10.170 - <para>As the 1990s progressed, awareness grew of a number of 10.171 - problems with CVS. It records simultaneous changes to multiple 10.172 - files individually, instead of grouping them together as a 10.173 - single logically atomic operation. It does not manage its file 10.174 - hierarchy well; it is easy to make a mess of a repository by 10.175 - renaming files and directories. Worse, its source code is 10.176 - difficult to read and maintain, which made the <quote>pain 10.177 - level</quote> of fixing these architectural problems 10.178 - prohibitive.</para> 10.179 - 10.180 - <para>In 2001, Jim Blandy and Karl Fogel, two developers who had 10.181 - worked on CVS, started a project to replace it with a tool that 10.182 - would have a better architecture and cleaner code. The result, 10.183 - Subversion, does not stray from CVS's centralised client/server 10.184 - model, but it adds multi-file atomic commits, better namespace 10.185 - management, and a number of other features that make it a 10.186 - generally better tool than CVS. Since its initial release, it 10.187 - has rapidly grown in popularity.</para> 10.188 - 10.189 - <para>More or less simultaneously, Graydon Hoare began working on 10.190 - an ambitious distributed revision control system that he named 10.191 - Monotone. While Monotone addresses many of CVS's design flaws 10.192 - and has a peer-to-peer architecture, it goes beyond earlier (and 10.193 - subsequent) revision control tools in a number of innovative 10.194 - ways. It uses cryptographic hashes as identifiers, and has an 10.195 - integral notion of <quote>trust</quote> for code from different 10.196 - sources.</para> 10.197 - 10.198 - <para>Mercurial began life in 2005. While a few aspects of its 10.199 - design are influenced by Monotone, Mercurial focuses on ease of 10.200 - use, high performance, and scalability to very large 10.201 - projects.</para> 10.202 - 10.203 - </sect1> 10.204 - <sect1> 10.205 - <title>Trends in revision control</title> 10.206 - 10.207 - <para>There has been an unmistakable trend in the development and 10.208 - use of revision control tools over the past four decades, as 10.209 - people have become familiar with the capabilities of their tools 10.210 - and constrained by their limitations.</para> 10.211 - 10.212 - <para>The first generation began by managing single files on 10.213 - individual computers. Although these tools represented a huge 10.214 - advance over ad-hoc manual revision control, their locking model 10.215 - and reliance on a single computer limited them to small, 10.216 - tightly-knit teams.</para> 10.217 - 10.218 - <para>The second generation loosened these constraints by moving 10.219 - to network-centered architectures, and managing entire projects 10.220 - at a time. As projects grew larger, they ran into new problems. 10.221 - With clients needing to talk to servers very frequently, server 10.222 - scaling became an issue for large projects. An unreliable 10.223 - network connection could prevent remote users from being able to 10.224 - talk to the server at all. As open source projects started 10.225 - making read-only access available anonymously to anyone, people 10.226 - without commit privileges found that they could not use the 10.227 - tools to interact with a project in a natural way, as they could 10.228 - not record their changes.</para> 10.229 - 10.230 - <para>The current generation of revision control tools is 10.231 - peer-to-peer in nature. All of these systems have dropped the 10.232 - dependency on a single central server, and allow people to 10.233 - distribute their revision control data to where it's actually 10.234 - needed. Collaboration over the Internet has moved from 10.235 - constrained by technology to a matter of choice and consensus. 10.236 - Modern tools can operate offline indefinitely and autonomously, 10.237 - with a network connection only needed when syncing changes with 10.238 - another repository.</para> 10.239 - 10.240 - </sect1> 10.241 - <sect1> 10.242 - <title>A few of the advantages of distributed revision 10.243 - control</title> 10.244 - 10.245 - <para>Even though distributed revision control tools have for 10.246 - several years been as robust and usable as their 10.247 - previous-generation counterparts, people using older tools have 10.248 - not yet necessarily woken up to their advantages. There are a 10.249 - number of ways in which distributed tools shine relative to 10.250 - centralised ones.</para> 10.251 - 10.252 - <para>For an individual developer, distributed tools are almost 10.253 - always much faster than centralised tools. This is for a simple 10.254 - reason: a centralised tool needs to talk over the network for 10.255 - many common operations, because most metadata is stored in a 10.256 - single copy on the central server. A distributed tool stores 10.257 - all of its metadata locally. All else being equal, talking over 10.258 - the network adds overhead to a centralised tool. Don't 10.259 - underestimate the value of a snappy, responsive tool: you're 10.260 - going to spend a lot of time interacting with your revision 10.261 - control software.</para> 10.262 - 10.263 - <para>Distributed tools are indifferent to the vagaries of your 10.264 - server infrastructure, again because they replicate metadata to 10.265 - so many locations. If you use a centralised system and your 10.266 - server catches fire, you'd better hope that your backup media 10.267 - are reliable, and that your last backup was recent and actually 10.268 - worked. With a distributed tool, you have many backups 10.269 - available on every contributor's computer.</para> 10.270 - 10.271 - <para>The reliability of your network will affect distributed 10.272 - tools far less than it will centralised tools. You can't even 10.273 - use a centralised tool without a network connection, except for 10.274 - a few highly constrained commands. With a distributed tool, if 10.275 - your network connection goes down while you're working, you may 10.276 - not even notice. The only thing you won't be able to do is talk 10.277 - to repositories on other computers, something that is relatively 10.278 - rare compared with local operations. If you have a far-flung 10.279 - team of collaborators, this may be significant.</para> 10.280 - 10.281 - <sect2> 10.282 - <title>Advantages for open source projects</title> 10.283 - 10.284 - <para>If you take a shine to an open source project and decide 10.285 - that you would like to start hacking on it, and that project 10.286 - uses a distributed revision control tool, you are at once a 10.287 - peer with the people who consider themselves the 10.288 - <quote>core</quote> of that project. If they publish their 10.289 - repositories, you can immediately copy their project history, 10.290 - start making changes, and record your work, using the same 10.291 - tools in the same ways as insiders. By contrast, with a 10.292 - centralised tool, you must use the software in a <quote>read 10.293 - only</quote> mode unless someone grants you permission to 10.294 - commit changes to their central server. Until then, you won't 10.295 - be able to record changes, and your local modifications will 10.296 - be at risk of corruption any time you try to update your 10.297 - client's view of the repository.</para> 10.298 - 10.299 - <sect3> 10.300 - <title>The forking non-problem</title> 10.301 - 10.302 - <para>It has been suggested that distributed revision control 10.303 - tools pose some sort of risk to open source projects because 10.304 - they make it easy to <quote>fork</quote> the development of 10.305 - a project. A fork happens when there are differences in 10.306 - opinion or attitude between groups of developers that cause 10.307 - them to decide that they can't work together any longer. 10.308 - Each side takes a more or less complete copy of the 10.309 - project's source code, and goes off in its own 10.310 - direction.</para> 10.311 - 10.312 - <para>Sometimes the camps in a fork decide to reconcile their 10.313 - differences. With a centralised revision control system, the 10.314 - <emphasis>technical</emphasis> process of reconciliation is 10.315 - painful, and has to be performed largely by hand. You have 10.316 - to decide whose revision history is going to 10.317 - <quote>win</quote>, and graft the other team's changes into 10.318 - the tree somehow. This usually loses some or all of one 10.319 - side's revision history.</para> 10.320 - 10.321 - <para>What distributed tools do with respect to forking is 10.322 - they make forking the <emphasis>only</emphasis> way to 10.323 - develop a project. Every single change that you make is 10.324 - potentially a fork point. The great strength of this 10.325 - approach is that a distributed revision control tool has to 10.326 - be really good at <emphasis>merging</emphasis> forks, 10.327 - because forks are absolutely fundamental: they happen all 10.328 - the time.</para> 10.329 - 10.330 - <para>If every piece of work that everybody does, all the 10.331 - time, is framed in terms of forking and merging, then what 10.332 - the open source world refers to as a <quote>fork</quote> 10.333 - becomes <emphasis>purely</emphasis> a social issue. If 10.334 - anything, distributed tools <emphasis>lower</emphasis> the 10.335 - likelihood of a fork:</para> 10.336 - <itemizedlist> 10.337 - <listitem><para>They eliminate the social distinction that 10.338 - centralised tools impose: that between insiders (people 10.339 - with commit access) and outsiders (people 10.340 - without).</para></listitem> 10.341 - <listitem><para>They make it easier to reconcile after a 10.342 - social fork, because all that's involved from the 10.343 - perspective of the revision control software is just 10.344 - another merge.</para></listitem></itemizedlist> 10.345 - 10.346 - <para>Some people resist distributed tools because they want 10.347 - to retain tight control over their projects, and they 10.348 - believe that centralised tools give them this control. 10.349 - However, if you're of this belief, and you publish your CVS 10.350 - or Subversion repositories publicly, there are plenty of 10.351 - tools available that can pull out your entire project's 10.352 - history (albeit slowly) and recreate it somewhere that you 10.353 - don't control. So while your control in this case is 10.354 - illusory, you are forgoing the ability to fluidly 10.355 - collaborate with whatever people feel compelled to mirror 10.356 - and fork your history.</para> 10.357 - 10.358 - </sect3> 10.359 - </sect2> 10.360 - <sect2> 10.361 - <title>Advantages for commercial projects</title> 10.362 - 10.363 - <para>Many commercial projects are undertaken by teams that are 10.364 - scattered across the globe. Contributors who are far from a 10.365 - central server will see slower command execution and perhaps 10.366 - less reliability. Commercial revision control systems attempt 10.367 - to ameliorate these problems with remote-site replication 10.368 - add-ons that are typically expensive to buy and cantankerous 10.369 - to administer. A distributed system doesn't suffer from these 10.370 - problems in the first place. Better yet, you can easily set 10.371 - up multiple authoritative servers, say one per site, so that 10.372 - there's no redundant communication between repositories over 10.373 - expensive long-haul network links.</para> 10.374 - 10.375 - <para>Centralised revision control systems tend to have 10.376 - relatively low scalability. It's not unusual for an expensive 10.377 - centralised system to fall over under the combined load of 10.378 - just a few dozen concurrent users. Once again, the typical 10.379 - response tends to be an expensive and clunky replication 10.380 - facility. Since the load on a central server---if you have 10.381 - one at all---is many times lower with a distributed tool 10.382 - (because all of the data is replicated everywhere), a single 10.383 - cheap server can handle the needs of a much larger team, and 10.384 - replication to balance load becomes a simple matter of 10.385 - scripting.</para> 10.386 - 10.387 - <para>If you have an employee in the field, troubleshooting a 10.388 - problem at a customer's site, they'll benefit from distributed 10.389 - revision control. The tool will let them generate custom 10.390 - builds, try different fixes in isolation from each other, and 10.391 - search efficiently through history for the sources of bugs and 10.392 - regressions in the customer's environment, all without needing 10.393 - to connect to your company's network.</para> 10.394 - 10.395 - </sect2> 10.396 - </sect1> 10.397 - <sect1> 10.398 - <title>Why choose Mercurial?</title> 10.399 - 10.400 - <para>Mercurial has a unique set of properties that make it a 10.401 - particularly good choice as a revision control system.</para> 10.402 - <itemizedlist> 10.403 - <listitem><para>It is easy to learn and use.</para></listitem> 10.404 - <listitem><para>It is lightweight.</para></listitem> 10.405 - <listitem><para>It scales excellently.</para></listitem> 10.406 - <listitem><para>It is easy to 10.407 - customise.</para></listitem></itemizedlist> 10.408 - 10.409 - <para>If you are at all familiar with revision control systems, 10.410 - you should be able to get up and running with Mercurial in less 10.411 - than five minutes. Even if not, it will take no more than a few 10.412 - minutes longer. Mercurial's command and feature sets are 10.413 - generally uniform and consistent, so you can keep track of a few 10.414 - general rules instead of a host of exceptions.</para> 10.415 - 10.416 - <para>On a small project, you can start working with Mercurial in 10.417 - moments. Creating new changes and branches; transferring changes 10.418 - around (whether locally or over a network); and history and 10.419 - status operations are all fast. Mercurial attempts to stay 10.420 - nimble and largely out of your way by combining low cognitive 10.421 - overhead with blazingly fast operations.</para> 10.422 - 10.423 - <para>The usefulness of Mercurial is not limited to small 10.424 - projects: it is used by projects with hundreds to thousands of 10.425 - contributors, each containing tens of thousands of files and 10.426 - hundreds of megabytes of source code.</para> 10.427 - 10.428 - <para>If the core functionality of Mercurial is not enough for 10.429 - you, it's easy to build on. Mercurial is well suited to 10.430 - scripting tasks, and its clean internals and implementation in 10.431 - Python make it easy to add features in the form of extensions. 10.432 - There are a number of popular and useful extensions already 10.433 - available, ranging from helping to identify bugs to improving 10.434 - performance.</para> 10.435 - 10.436 - </sect1> 10.437 - <sect1> 10.438 - <title>Mercurial compared with other tools</title> 10.439 - 10.440 - <para>Before you read on, please understand that this section 10.441 - necessarily reflects my own experiences, interests, and (dare I 10.442 - say it) biases. I have used every one of the revision control 10.443 - tools listed below, in most cases for several years at a 10.444 - time.</para> 10.445 - 10.446 - 10.447 - <sect2> 10.448 - <title>Subversion</title> 10.449 - 10.450 - <para>Subversion is a popular revision control tool, developed 10.451 - to replace CVS. It has a centralised client/server 10.452 - architecture.</para> 10.453 - 10.454 - <para>Subversion and Mercurial have similarly named commands for 10.455 - performing the same operations, so if you're familiar with 10.456 - one, it is easy to learn to use the other. Both tools are 10.457 - portable to all popular operating systems.</para> 10.458 - 10.459 - <para>Prior to version 1.5, Subversion had no useful support for 10.460 - merges. At the time of writing, its merge tracking capability 10.461 - is new, and known to be <ulink 10.462 - url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">complicated 10.463 - and buggy</ulink>.</para> 10.464 - 10.465 - <para>Mercurial has a substantial performance advantage over 10.466 - Subversion on every revision control operation I have 10.467 - benchmarked. I have measured its advantage as ranging from a 10.468 - factor of two to a factor of six when compared with Subversion 10.469 - 1.4.3's <emphasis>ra_local</emphasis> file store, which is the 10.470 - fastest access method available. In more realistic 10.471 - deployments involving a network-based store, Subversion will 10.472 - be at a substantially larger disadvantage. Because many 10.473 - Subversion commands must talk to the server and Subversion 10.474 - does not have useful replication facilities, server capacity 10.475 - and network bandwidth become bottlenecks for modestly large 10.476 - projects.</para> 10.477 - 10.478 - <para>Additionally, Subversion incurs substantial storage 10.479 - overhead to avoid network transactions for a few common 10.480 - operations, such as finding modified files 10.481 - (<literal>status</literal>) and displaying modifications 10.482 - against the current revision (<literal>diff</literal>). As a 10.483 - result, a Subversion working copy is often the same size as, 10.484 - or larger than, a Mercurial repository and working directory, 10.485 - even though the Mercurial repository contains a complete 10.486 - history of the project.</para> 10.487 - 10.488 - <para>Subversion is widely supported by third party tools. 10.489 - Mercurial currently lags considerably in this area. This gap 10.490 - is closing, however, and indeed some of Mercurial's GUI tools 10.491 - now outshine their Subversion equivalents. Like Mercurial, 10.492 - Subversion has an excellent user manual.</para> 10.493 - 10.494 - <para>Because Subversion doesn't store revision history on the 10.495 - client, it is well suited to managing projects that deal with 10.496 - lots of large, opaque binary files. If you check in fifty 10.497 - revisions to an incompressible 10MB file, Subversion's 10.498 - client-side space usage stays constant The space used by any 10.499 - distributed SCM will grow rapidly in proportion to the number 10.500 - of revisions, because the differences between each revision 10.501 - are large.</para> 10.502 - 10.503 - <para>In addition, it's often difficult or, more usually, 10.504 - impossible to merge different versions of a binary file. 10.505 - Subversion's ability to let a user lock a file, so that they 10.506 - temporarily have the exclusive right to commit changes to it, 10.507 - can be a significant advantage to a project where binary files 10.508 - are widely used.</para> 10.509 - 10.510 - <para>Mercurial can import revision history from a Subversion 10.511 - repository. It can also export revision history to a 10.512 - Subversion repository. This makes it easy to <quote>test the 10.513 - waters</quote> and use Mercurial and Subversion in parallel 10.514 - before deciding to switch. History conversion is incremental, 10.515 - so you can perform an initial conversion, then small 10.516 - additional conversions afterwards to bring in new 10.517 - changes.</para> 10.518 - 10.519 - 10.520 - </sect2> 10.521 - <sect2> 10.522 - <title>Git</title> 10.523 - 10.524 - <para>Git is a distributed revision control tool that was 10.525 - developed for managing the Linux kernel source tree. Like 10.526 - Mercurial, its early design was somewhat influenced by 10.527 - Monotone.</para> 10.528 - 10.529 - <para>Git has a very large command set, with version 1.5.0 10.530 - providing 139 individual commands. It has something of a 10.531 - reputation for being difficult to learn. Compared to Git, 10.532 - Mercurial has a strong focus on simplicity.</para> 10.533 - 10.534 - <para>In terms of performance, Git is extremely fast. In 10.535 - several cases, it is faster than Mercurial, at least on Linux, 10.536 - while Mercurial performs better on other operations. However, 10.537 - on Windows, the performance and general level of support that 10.538 - Git provides is, at the time of writing, far behind that of 10.539 - Mercurial.</para> 10.540 - 10.541 - <para>While a Mercurial repository needs no maintenance, a Git 10.542 - repository requires frequent manual <quote>repacks</quote> of 10.543 - its metadata. Without these, performance degrades, while 10.544 - space usage grows rapidly. A server that contains many Git 10.545 - repositories that are not rigorously and frequently repacked 10.546 - will become heavily disk-bound during backups, and there have 10.547 - been instances of daily backups taking far longer than 24 10.548 - hours as a result. A freshly packed Git repository is 10.549 - slightly smaller than a Mercurial repository, but an unpacked 10.550 - repository is several orders of magnitude larger.</para> 10.551 - 10.552 - <para>The core of Git is written in C. Many Git commands are 10.553 - implemented as shell or Perl scripts, and the quality of these 10.554 - scripts varies widely. I have encountered several instances 10.555 - where scripts charged along blindly in the presence of errors 10.556 - that should have been fatal.</para> 10.557 - 10.558 - <para>Mercurial can import revision history from a Git 10.559 - repository.</para> 10.560 - 10.561 - 10.562 - </sect2> 10.563 - <sect2> 10.564 - <title>CVS</title> 10.565 - 10.566 - <para>CVS is probably the most widely used revision control tool 10.567 - in the world. Due to its age and internal untidiness, it has 10.568 - been only lightly maintained for many years.</para> 10.569 - 10.570 - <para>It has a centralised client/server architecture. It does 10.571 - not group related file changes into atomic commits, making it 10.572 - easy for people to <quote>break the build</quote>: one person 10.573 - can successfully commit part of a change and then be blocked 10.574 - by the need for a merge, causing other people to see only a 10.575 - portion of the work they intended to do. This also affects 10.576 - how you work with project history. If you want to see all of 10.577 - the modifications someone made as part of a task, you will 10.578 - need to manually inspect the descriptions and timestamps of 10.579 - the changes made to each file involved (if you even know what 10.580 - those files were).</para> 10.581 - 10.582 - <para>CVS has a muddled notion of tags and branches that I will 10.583 - not attempt to even describe. It does not support renaming of 10.584 - files or directories well, making it easy to corrupt a 10.585 - repository. It has almost no internal consistency checking 10.586 - capabilities, so it is usually not even possible to tell 10.587 - whether or how a repository is corrupt. I would not recommend 10.588 - CVS for any project, existing or new.</para> 10.589 - 10.590 - <para>Mercurial can import CVS revision history. However, there 10.591 - are a few caveats that apply; these are true of every other 10.592 - revision control tool's CVS importer, too. Due to CVS's lack 10.593 - of atomic changes and unversioned filesystem hierarchy, it is 10.594 - not possible to reconstruct CVS history completely accurately; 10.595 - some guesswork is involved, and renames will usually not show 10.596 - up. Because a lot of advanced CVS administration has to be 10.597 - done by hand and is hence error-prone, it's common for CVS 10.598 - importers to run into multiple problems with corrupted 10.599 - repositories (completely bogus revision timestamps and files 10.600 - that have remained locked for over a decade are just two of 10.601 - the less interesting problems I can recall from personal 10.602 - experience).</para> 10.603 - 10.604 - <para>Mercurial can import revision history from a CVS 10.605 - repository.</para> 10.606 - 10.607 - 10.608 - </sect2> 10.609 - <sect2> 10.610 - <title>Commercial tools</title> 10.611 - 10.612 - <para>Perforce has a centralised client/server architecture, 10.613 - with no client-side caching of any data. Unlike modern 10.614 - revision control tools, Perforce requires that a user run a 10.615 - command to inform the server about every file they intend to 10.616 - edit.</para> 10.617 - 10.618 - <para>The performance of Perforce is quite good for small teams, 10.619 - but it falls off rapidly as the number of users grows beyond a 10.620 - few dozen. Modestly large Perforce installations require the 10.621 - deployment of proxies to cope with the load their users 10.622 - generate.</para> 10.623 - 10.624 - 10.625 - </sect2> 10.626 - <sect2> 10.627 - <title>Choosing a revision control tool</title> 10.628 - 10.629 - <para>With the exception of CVS, all of the tools listed above 10.630 - have unique strengths that suit them to particular styles of 10.631 - work. There is no single revision control tool that is best 10.632 - in all situations.</para> 10.633 - 10.634 - <para>As an example, Subversion is a good choice for working 10.635 - with frequently edited binary files, due to its centralised 10.636 - nature and support for file locking.</para> 10.637 - 10.638 - <para>I personally find Mercurial's properties of simplicity, 10.639 - performance, and good merge support to be a compelling 10.640 - combination that has served me well for several years.</para> 10.641 - 10.642 - 10.643 - </sect2> 10.644 - </sect1> 10.645 - <sect1> 10.646 - <title>Switching from another tool to Mercurial</title> 10.647 - 10.648 - <para>Mercurial is bundled with an extension named <literal 10.649 - role="hg-ext">convert</literal>, which can incrementally 10.650 - import revision history from several other revision control 10.651 - tools. By <quote>incremental</quote>, I mean that you can 10.652 - convert all of a project's history to date in one go, then rerun 10.653 - the conversion later to obtain new changes that happened after 10.654 - the initial conversion.</para> 10.655 - 10.656 - <para>The revision control tools supported by <literal 10.657 - role="hg-ext">convert</literal> are as follows:</para> 10.658 - <itemizedlist> 10.659 - <listitem><para>Subversion</para></listitem> 10.660 - <listitem><para>CVS</para></listitem> 10.661 - <listitem><para>Git</para></listitem> 10.662 - <listitem><para>Darcs</para></listitem></itemizedlist> 10.663 - 10.664 - <para>In addition, <literal role="hg-ext">convert</literal> can 10.665 - export changes from Mercurial to Subversion. This makes it 10.666 - possible to try Subversion and Mercurial in parallel before 10.667 - committing to a switchover, without risking the loss of any 10.668 - work.</para> 10.669 - 10.670 - <para>The <command role="hg-ext-conver">convert</command> command 10.671 - is easy to use. Simply point it at the path or URL of the 10.672 - source repository, optionally give it the name of the 10.673 - destination repository, and it will start working. After the 10.674 - initial conversion, just run the same command again to import 10.675 - new changes.</para> 10.676 - </sect1> 10.677 -</chapter> 10.678 - 10.679 -<!-- 10.680 -local variables: 10.681 -sgml-parent-document: ("00book.xml" "book" "chapter") 10.682 -end: 10.683 --->
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/en/ch01-tour-basic.xml Fri Mar 20 16:43:35 2009 +0800 11.3 @@ -0,0 +1,862 @@ 11.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 11.5 + 11.6 +<chapter id="chap.tour-basic"> 11.7 + <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?> 11.8 + <title>A tour of Mercurial: the basics</title> 11.9 + 11.10 + <sect1 id="sec.tour.install"> 11.11 + <title>Installing Mercurial on your system</title> 11.12 + 11.13 + <para>Prebuilt binary packages of Mercurial are available for 11.14 + every popular operating system. These make it easy to start 11.15 + using Mercurial on your computer immediately.</para> 11.16 + 11.17 + <sect2> 11.18 + <title>Linux</title> 11.19 + 11.20 + <para>Because each Linux distribution has its own packaging 11.21 + tools, policies, and rate of development, it's difficult to 11.22 + give a comprehensive set of instructions on how to install 11.23 + Mercurial binaries. The version of Mercurial that you will 11.24 + end up with can vary depending on how active the person is who 11.25 + maintains the package for your distribution.</para> 11.26 + 11.27 + <para>To keep things simple, I will focus on installing 11.28 + Mercurial from the command line under the most popular Linux 11.29 + distributions. Most of these distributions provide graphical 11.30 + package managers that will let you install Mercurial with a 11.31 + single click; the package name to look for is 11.32 + <literal>mercurial</literal>.</para> 11.33 + 11.34 + <itemizedlist> 11.35 + <listitem><para>Debian:</para> 11.36 + <programlisting>apt-get install mercurial</programlisting></listitem> 11.37 + <listitem><para>Fedora Core:</para> 11.38 + <programlisting>yum install mercurial</programlisting></listitem> 11.39 + <listitem><para>Gentoo:</para> 11.40 + <programlisting>emerge mercurial</programlisting></listitem> 11.41 + <listitem><para>OpenSUSE:</para> 11.42 + <programlisting>yum install mercurial</programlisting></listitem> 11.43 + <listitem><para>Ubuntu: Ubuntu's Mercurial package is based on 11.44 + Debian's. To install it, run the following 11.45 + command.</para> 11.46 + <programlisting>apt-get install mercurial</programlisting></listitem> 11.47 + </itemizedlist> 11.48 + 11.49 + </sect2> 11.50 + <sect2> 11.51 + <title>Solaris</title> 11.52 + 11.53 + <para>SunFreeWare, at <ulink 11.54 + url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>, 11.55 + is a good source for a large number of pre-built Solaris 11.56 + packages for 32 and 64 bit Intel and Sparc architectures, 11.57 + including current versions of Mercurial.</para> 11.58 + 11.59 + </sect2> 11.60 + <sect2> 11.61 + <title>Mac OS X</title> 11.62 + 11.63 + <para>Lee Cantey publishes an installer of Mercurial for Mac OS 11.64 + X at <ulink 11.65 + url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 11.66 + This package works on both Intel- and Power-based Macs. Before 11.67 + you can use it, you must install a compatible version of 11.68 + Universal MacPython <citation>web:macpython</citation>. This 11.69 + is easy to do; simply follow the instructions on Lee's 11.70 + site.</para> 11.71 + 11.72 + <para>It's also possible to install Mercurial using Fink or 11.73 + MacPorts, two popular free package managers for Mac OS X. If 11.74 + you have Fink, use <command>sudo apt-get install 11.75 + mercurial-py25</command>. If MacPorts, <command>sudo port 11.76 + install mercurial</command>.</para> 11.77 + 11.78 + </sect2> 11.79 + <sect2> 11.80 + <title>Windows</title> 11.81 + 11.82 + <para>Lee Cantey publishes an installer of Mercurial for Windows 11.83 + at <ulink 11.84 + url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 11.85 + This package has no external dependencies; it <quote>just 11.86 + works</quote>.</para> 11.87 + 11.88 + <note> 11.89 + <para> The Windows version of Mercurial does not 11.90 + automatically convert line endings between Windows and Unix 11.91 + styles. If you want to share work with Unix users, you must 11.92 + do a little additional configuration work. XXX Flesh this 11.93 + out.</para> 11.94 + </note> 11.95 + 11.96 + </sect2> 11.97 + </sect1> 11.98 + <sect1> 11.99 + <title>Getting started</title> 11.100 + 11.101 + <para>To begin, we'll use the <command role="hg-cmd">hg 11.102 + version</command> command to find out whether Mercurial is 11.103 + actually installed properly. The actual version information 11.104 + that it prints isn't so important; it's whether it prints 11.105 + anything at all that we care about.</para> 11.106 + 11.107 + &interaction.tour.version; 11.108 + 11.109 + <sect2> 11.110 + <title>Built-in help</title> 11.111 + 11.112 + <para>Mercurial provides a built-in help system. This is 11.113 + invaluable for those times when you find yourself stuck 11.114 + trying to remember how to run a command. If you are 11.115 + completely stuck, simply run <command role="hg-cmd">hg 11.116 + help</command>; it will print a brief list of commands, 11.117 + along with a description of what each does. If you ask for 11.118 + help on a specific command (as below), it prints more 11.119 + detailed information.</para> 11.120 + 11.121 + &interaction.tour.help; 11.122 + 11.123 + <para>For a more impressive level of detail (which you won't 11.124 + usually need) run <command role="hg-cmd">hg help <option 11.125 + role="hg-opt-global">-v</option></command>. The <option 11.126 + role="hg-opt-global">-v</option> option is short for 11.127 + <option role="hg-opt-global">--verbose</option>, and tells 11.128 + Mercurial to print more information than it usually 11.129 + would.</para> 11.130 + 11.131 + </sect2> 11.132 + </sect1> 11.133 + <sect1> 11.134 + <title>Working with a repository</title> 11.135 + 11.136 + <para>In Mercurial, everything happens inside a 11.137 + <emphasis>repository</emphasis>. The repository for a project 11.138 + contains all of the files that <quote>belong to</quote> that 11.139 + project, along with a historical record of the project's 11.140 + files.</para> 11.141 + 11.142 + <para>There's nothing particularly magical about a repository; it 11.143 + is simply a directory tree in your filesystem that Mercurial 11.144 + treats as special. You can rename or delete a repository any 11.145 + time you like, using either the command line or your file 11.146 + browser.</para> 11.147 + 11.148 + <sect2> 11.149 + <title>Making a local copy of a repository</title> 11.150 + 11.151 + <para><emphasis>Copying</emphasis> a repository is just a little 11.152 + bit special. While you could use a normal file copying 11.153 + command to make a copy of a repository, it's best to use a 11.154 + built-in command that Mercurial provides. This command is 11.155 + called <command role="hg-cmd">hg clone</command>, because it 11.156 + creates an identical copy of an existing repository.</para> 11.157 + 11.158 + &interaction.tour.clone; 11.159 + 11.160 + <para>If our clone succeeded, we should now have a local 11.161 + directory called <filename class="directory">hello</filename>. 11.162 + This directory will contain some files.</para> 11.163 + 11.164 + &interaction.tour.ls; 11.165 + 11.166 + <para>These files have the same contents and history in our 11.167 + repository as they do in the repository we cloned.</para> 11.168 + 11.169 + <para>Every Mercurial repository is complete, self-contained, 11.170 + and independent. It contains its own private copy of a 11.171 + project's files and history. A cloned repository remembers 11.172 + the location of the repository it was cloned from, but it does 11.173 + not communicate with that repository, or any other, unless you 11.174 + tell it to.</para> 11.175 + 11.176 + <para>What this means for now is that we're free to experiment 11.177 + with our repository, safe in the knowledge that it's a private 11.178 + <quote>sandbox</quote> that won't affect anyone else.</para> 11.179 + 11.180 + </sect2> 11.181 + <sect2> 11.182 + <title>What's in a repository?</title> 11.183 + 11.184 + <para>When we take a more detailed look inside a repository, we 11.185 + can see that it contains a directory named <filename 11.186 + class="directory">.hg</filename>. This is where Mercurial 11.187 + keeps all of its metadata for the repository.</para> 11.188 + 11.189 + &interaction.tour.ls-a; 11.190 + 11.191 + <para>The contents of the <filename 11.192 + class="directory">.hg</filename> directory and its 11.193 + subdirectories are private to Mercurial. Every other file and 11.194 + directory in the repository is yours to do with as you 11.195 + please.</para> 11.196 + 11.197 + <para>To introduce a little terminology, the <filename 11.198 + class="directory">.hg</filename> directory is the 11.199 + <quote>real</quote> repository, and all of the files and 11.200 + directories that coexist with it are said to live in the 11.201 + <emphasis>working directory</emphasis>. An easy way to 11.202 + remember the distinction is that the 11.203 + <emphasis>repository</emphasis> contains the 11.204 + <emphasis>history</emphasis> of your project, while the 11.205 + <emphasis>working directory</emphasis> contains a 11.206 + <emphasis>snapshot</emphasis> of your project at a particular 11.207 + point in history.</para> 11.208 + 11.209 + </sect2> 11.210 + </sect1> 11.211 + <sect1> 11.212 + <title>A tour through history</title> 11.213 + 11.214 + <para>One of the first things we might want to do with a new, 11.215 + unfamiliar repository is understand its history. The <command 11.216 + role="hg-cmd">hg log</command> command gives us a view of 11.217 + history.</para> 11.218 + 11.219 + &interaction.tour.log; 11.220 + 11.221 + <para>By default, this command prints a brief paragraph of output 11.222 + for each change to the project that was recorded. In Mercurial 11.223 + terminology, we call each of these recorded events a 11.224 + <emphasis>changeset</emphasis>, because it can contain a record 11.225 + of changes to several files.</para> 11.226 + 11.227 + <para>The fields in a record of output from <command 11.228 + role="hg-cmd">hg log</command> are as follows.</para> 11.229 + <itemizedlist> 11.230 + <listitem><para><literal>changeset</literal>: This field has the 11.231 + format of a number, followed by a colon, followed by a 11.232 + hexadecimal string. These are 11.233 + <emphasis>identifiers</emphasis> for the changeset. There 11.234 + are two identifiers because the number is shorter and easier 11.235 + to type than the hex string.</para></listitem> 11.236 + <listitem><para><literal>user</literal>: The identity of the 11.237 + person who created the changeset. This is a free-form 11.238 + field, but it most often contains a person's name and email 11.239 + address.</para></listitem> 11.240 + <listitem><para><literal>date</literal>: The date and time on 11.241 + which the changeset was created, and the timezone in which 11.242 + it was created. (The date and time are local to that 11.243 + timezone; they display what time and date it was for the 11.244 + person who created the changeset.)</para></listitem> 11.245 + <listitem><para><literal>summary</literal>: The first line of 11.246 + the text message that the creator of the changeset entered 11.247 + to describe the changeset.</para></listitem></itemizedlist> 11.248 + <para>The default output printed by <command role="hg-cmd">hg 11.249 + log</command> is purely a summary; it is missing a lot of 11.250 + detail.</para> 11.251 + 11.252 + <para>Figure <xref endterm="fig.tour-basic.history.caption" 11.253 + linkend="fig.tour-basic.history"/> provides a 11.254 + graphical representation of the history of the <filename 11.255 + class="directory">hello</filename> repository, to make it a 11.256 + little easier to see which direction history is 11.257 + <quote>flowing</quote> in. We'll be returning to this figure 11.258 + several times in this chapter and the chapter that 11.259 + follows.</para> 11.260 + 11.261 + <informalfigure id="fig.tour-basic.history"> 11.262 + <mediaobject> 11.263 + <imageobject><imagedata fileref="images/tour-history.png"/></imageobject> 11.264 + <textobject><phrase>XXX add text</phrase></textobject> 11.265 + <caption><para id="fig.tour-basic.history.caption">Graphical history of 11.266 + the <filename class="directory">hello</filename> repository</para> 11.267 + </caption> 11.268 + </mediaobject> 11.269 + </informalfigure> 11.270 + 11.271 + <sect2> 11.272 + <title>Changesets, revisions, and talking to other 11.273 + people</title> 11.274 + 11.275 + <para>As English is a notoriously sloppy language, and computer 11.276 + science has a hallowed history of terminological confusion 11.277 + (why use one term when four will do?), revision control has a 11.278 + variety of words and phrases that mean the same thing. If you 11.279 + are talking about Mercurial history with other people, you 11.280 + will find that the word <quote>changeset</quote> is often 11.281 + compressed to <quote>change</quote> or (when written) 11.282 + <quote>cset</quote>, and sometimes a changeset is referred to 11.283 + as a <quote>revision</quote> or a <quote>rev</quote>.</para> 11.284 + 11.285 + <para>While it doesn't matter what <emphasis>word</emphasis> you 11.286 + use to refer to the concept of <quote>a changeset</quote>, the 11.287 + <emphasis>identifier</emphasis> that you use to refer to 11.288 + <quote>a <emphasis>specific</emphasis> changeset</quote> is of 11.289 + great importance. Recall that the <literal>changeset</literal> 11.290 + field in the output from <command role="hg-cmd">hg 11.291 + log</command> identifies a changeset using both a number and 11.292 + a hexadecimal string.</para> 11.293 + <itemizedlist> 11.294 + <listitem><para>The revision number is <emphasis>only valid in 11.295 + that repository</emphasis>,</para></listitem> 11.296 + <listitem><para>while the hex string is the 11.297 + <emphasis>permanent, unchanging identifier</emphasis> that 11.298 + will always identify that exact changeset in 11.299 + <emphasis>every</emphasis> copy of the 11.300 + repository.</para></listitem></itemizedlist> 11.301 + <para>This distinction is important. If you send someone an 11.302 + email talking about <quote>revision 33</quote>, there's a high 11.303 + likelihood that their revision 33 will <emphasis>not be the 11.304 + same</emphasis> as yours. The reason for this is that a 11.305 + revision number depends on the order in which changes arrived 11.306 + in a repository, and there is no guarantee that the same 11.307 + changes will happen in the same order in different 11.308 + repositories. Three changes $a,b,c$ can easily appear in one 11.309 + repository as $0,1,2$, while in another as $1,0,2$.</para> 11.310 + 11.311 + <para>Mercurial uses revision numbers purely as a convenient 11.312 + shorthand. If you need to discuss a changeset with someone, 11.313 + or make a record of a changeset for some other reason (for 11.314 + example, in a bug report), use the hexadecimal 11.315 + identifier.</para> 11.316 + 11.317 + </sect2> 11.318 + <sect2> 11.319 + <title>Viewing specific revisions</title> 11.320 + 11.321 + <para>To narrow the output of <command role="hg-cmd">hg 11.322 + log</command> down to a single revision, use the <option 11.323 + role="hg-opt-log">-r</option> (or <option 11.324 + role="hg-opt-log">--rev</option>) option. You can use 11.325 + either a revision number or a long-form changeset identifier, 11.326 + and you can provide as many revisions as you want.</para> 11.327 + 11.328 + &interaction.tour.log-r; 11.329 + 11.330 + <para>If you want to see the history of several revisions 11.331 + without having to list each one, you can use <emphasis>range 11.332 + notation</emphasis>; this lets you express the idea <quote>I 11.333 + want all revisions between <literal>abc</literal> and 11.334 + <literal>def</literal>, inclusive</quote>.</para> 11.335 + 11.336 + &interaction.tour.log.range; 11.337 + 11.338 + <para>Mercurial also honours the order in which you specify 11.339 + revisions, so <command role="hg-cmd">hg log -r 2:4</command> 11.340 + prints 2, 3, and 4. while <command role="hg-cmd">hg log -r 11.341 + 4:2</command> prints 4, 3, and 2.</para> 11.342 + 11.343 + </sect2> 11.344 + <sect2> 11.345 + <title>More detailed information</title> 11.346 + 11.347 + <para>While the summary information printed by <command 11.348 + role="hg-cmd">hg log</command> is useful if you already know 11.349 + what you're looking for, you may need to see a complete 11.350 + description of the change, or a list of the files changed, if 11.351 + you're trying to decide whether a changeset is the one you're 11.352 + looking for. The <command role="hg-cmd">hg log</command> 11.353 + command's <option role="hg-opt-global">-v</option> (or <option 11.354 + role="hg-opt-global">--verbose</option>) option gives you 11.355 + this extra detail.</para> 11.356 + 11.357 + &interaction.tour.log-v; 11.358 + 11.359 + <para>If you want to see both the description and content of a 11.360 + change, add the <option role="hg-opt-log">-p</option> (or 11.361 + <option role="hg-opt-log">--patch</option>) option. This 11.362 + displays the content of a change as a <emphasis>unified 11.363 + diff</emphasis> (if you've never seen a unified diff before, 11.364 + see section <xref linkend="sec.mq.patch"/> for an 11.365 + overview).</para> 11.366 + 11.367 + &interaction.tour.log-vp; 11.368 + 11.369 + </sect2> 11.370 + </sect1> 11.371 + <sect1> 11.372 + <title>All about command options</title> 11.373 + 11.374 + <para>Let's take a brief break from exploring Mercurial commands 11.375 + to discuss a pattern in the way that they work; you may find 11.376 + this useful to keep in mind as we continue our tour.</para> 11.377 + 11.378 + <para>Mercurial has a consistent and straightforward approach to 11.379 + dealing with the options that you can pass to commands. It 11.380 + follows the conventions for options that are common to modern 11.381 + Linux and Unix systems.</para> 11.382 + <itemizedlist> 11.383 + <listitem><para>Every option has a long name. For example, as 11.384 + we've already seen, the <command role="hg-cmd">hg 11.385 + log</command> command accepts a <option 11.386 + role="hg-opt-log">--rev</option> option.</para></listitem> 11.387 + <listitem><para>Most options have short names, too. Instead of 11.388 + <option role="hg-opt-log">--rev</option>, we can use <option 11.389 + role="hg-opt-log">-r</option>. (The reason that some 11.390 + options don't have short names is that the options in 11.391 + question are rarely used.)</para></listitem> 11.392 + <listitem><para>Long options start with two dashes (e.g. <option 11.393 + role="hg-opt-log">--rev</option>), while short options 11.394 + start with one (e.g. <option 11.395 + role="hg-opt-log">-r</option>).</para></listitem> 11.396 + <listitem><para>Option naming and usage is consistent across 11.397 + commands. For example, every command that lets you specify 11.398 + a changeset ID or revision number accepts both <option 11.399 + role="hg-opt-log">-r</option> and <option 11.400 + role="hg-opt-log">--rev</option> 11.401 + arguments.</para></listitem></itemizedlist> 11.402 + <para>In the examples throughout this book, I use short options 11.403 + instead of long. This just reflects my own preference, so don't 11.404 + read anything significant into it.</para> 11.405 + 11.406 + <para>Most commands that print output of some kind will print more 11.407 + output when passed a <option role="hg-opt-global">-v</option> 11.408 + (or <option role="hg-opt-global">--verbose</option>) option, and 11.409 + less when passed <option role="hg-opt-global">-q</option> (or 11.410 + <option role="hg-opt-global">--quiet</option>).</para> 11.411 + 11.412 + </sect1> 11.413 + <sect1> 11.414 + <title>Making and reviewing changes</title> 11.415 + 11.416 + <para>Now that we have a grasp of viewing history in Mercurial, 11.417 + let's take a look at making some changes and examining 11.418 + them.</para> 11.419 + 11.420 + <para>The first thing we'll do is isolate our experiment in a 11.421 + repository of its own. We use the <command role="hg-cmd">hg 11.422 + clone</command> command, but we don't need to clone a copy of 11.423 + the remote repository. Since we already have a copy of it 11.424 + locally, we can just clone that instead. This is much faster 11.425 + than cloning over the network, and cloning a local repository 11.426 + uses less disk space in most cases, too.</para> 11.427 + 11.428 + &interaction.tour.reclone; 11.429 + 11.430 + <para>As an aside, it's often good practice to keep a 11.431 + <quote>pristine</quote> copy of a remote repository around, 11.432 + which you can then make temporary clones of to create sandboxes 11.433 + for each task you want to work on. This lets you work on 11.434 + multiple tasks in parallel, each isolated from the others until 11.435 + it's complete and you're ready to integrate it back. Because 11.436 + local clones are so cheap, there's almost no overhead to cloning 11.437 + and destroying repositories whenever you want.</para> 11.438 + 11.439 + <para>In our <filename class="directory">my-hello</filename> 11.440 + repository, we have a file <filename>hello.c</filename> that 11.441 + contains the classic <quote>hello, world</quote> program. Let's 11.442 + use the ancient and venerable <command>sed</command> command to 11.443 + edit this file so that it prints a second line of output. (I'm 11.444 + only using <command>sed</command> to do this because it's easy 11.445 + to write a scripted example this way. Since you're not under 11.446 + the same constraint, you probably won't want to use 11.447 + <command>sed</command>; simply use your preferred text editor to 11.448 + do the same thing.)</para> 11.449 + 11.450 + &interaction.tour.sed; 11.451 + 11.452 + <para>Mercurial's <command role="hg-cmd">hg status</command> 11.453 + command will tell us what Mercurial knows about the files in the 11.454 + repository.</para> 11.455 + 11.456 + &interaction.tour.status; 11.457 + 11.458 + <para>The <command role="hg-cmd">hg status</command> command 11.459 + prints no output for some files, but a line starting with 11.460 + <quote><literal>M</literal></quote> for 11.461 + <filename>hello.c</filename>. Unless you tell it to, <command 11.462 + role="hg-cmd">hg status</command> will not print any output 11.463 + for files that have not been modified.</para> 11.464 + 11.465 + <para>The <quote><literal>M</literal></quote> indicates that 11.466 + Mercurial has noticed that we modified 11.467 + <filename>hello.c</filename>. We didn't need to 11.468 + <emphasis>inform</emphasis> Mercurial that we were going to 11.469 + modify the file before we started, or that we had modified the 11.470 + file after we were done; it was able to figure this out 11.471 + itself.</para> 11.472 + 11.473 + <para>It's a little bit helpful to know that we've modified 11.474 + <filename>hello.c</filename>, but we might prefer to know 11.475 + exactly <emphasis>what</emphasis> changes we've made to it. To 11.476 + do this, we use the <command role="hg-cmd">hg diff</command> 11.477 + command.</para> 11.478 + 11.479 + &interaction.tour.diff; 11.480 + 11.481 + </sect1> 11.482 + <sect1> 11.483 + <title>Recording changes in a new changeset</title> 11.484 + 11.485 + <para>We can modify files, build and test our changes, and use 11.486 + <command role="hg-cmd">hg status</command> and <command 11.487 + role="hg-cmd">hg diff</command> to review our changes, until 11.488 + we're satisfied with what we've done and arrive at a natural 11.489 + stopping point where we want to record our work in a new 11.490 + changeset.</para> 11.491 + 11.492 + <para>The <command role="hg-cmd">hg commit</command> command lets 11.493 + us create a new changeset; we'll usually refer to this as 11.494 + <quote>making a commit</quote> or 11.495 + <quote>committing</quote>.</para> 11.496 + 11.497 + <sect2> 11.498 + <title>Setting up a username</title> 11.499 + 11.500 + <para>When you try to run <command role="hg-cmd">hg 11.501 + commit</command> for the first time, it is not guaranteed to 11.502 + succeed. Mercurial records your name and address with each 11.503 + change that you commit, so that you and others will later be 11.504 + able to tell who made each change. Mercurial tries to 11.505 + automatically figure out a sensible username to commit the 11.506 + change with. It will attempt each of the following methods, 11.507 + in order:</para> 11.508 + <orderedlist> 11.509 + <listitem><para>If you specify a <option 11.510 + role="hg-opt-commit">-u</option> option to the <command 11.511 + role="hg-cmd">hg commit</command> command on the command 11.512 + line, followed by a username, this is always given the 11.513 + highest precedence.</para></listitem> 11.514 + <listitem><para>If you have set the <envar>HGUSER</envar> 11.515 + environment variable, this is checked 11.516 + next.</para></listitem> 11.517 + <listitem><para>If you create a file in your home directory 11.518 + called <filename role="special">.hgrc</filename>, with a 11.519 + <envar role="rc-item-ui">username</envar> entry, that will 11.520 + be used next. To see what the contents of this file 11.521 + should look like, refer to section <xref 11.522 + linkend="sec.tour-basic.username"/> 11.523 + below.</para></listitem> 11.524 + <listitem><para>If you have set the <envar>EMAIL</envar> 11.525 + environment variable, this will be used 11.526 + next.</para></listitem> 11.527 + <listitem><para>Mercurial will query your system to find out 11.528 + your local user name and host name, and construct a 11.529 + username from these components. Since this often results 11.530 + in a username that is not very useful, it will print a 11.531 + warning if it has to do 11.532 + this.</para></listitem> 11.533 + </orderedlist> 11.534 + <para>If all of these mechanisms fail, Mercurial will 11.535 + fail, printing an error message. In this case, it will not 11.536 + let you commit until you set up a 11.537 + username.</para> 11.538 + <para>You should think of the <envar>HGUSER</envar> environment 11.539 + variable and the <option role="hg-opt-commit">-u</option> 11.540 + option to the <command role="hg-cmd">hg commit</command> 11.541 + command as ways to <emphasis>override</emphasis> Mercurial's 11.542 + default selection of username. For normal use, the simplest 11.543 + and most robust way to set a username for yourself is by 11.544 + creating a <filename role="special">.hgrc</filename> file; see 11.545 + below for details.</para> 11.546 + <sect3 id="sec.tour-basic.username"> 11.547 + <title>Creating a Mercurial configuration file</title> 11.548 + 11.549 + <para>To set a user name, use your favourite editor 11.550 + to create a file called <filename 11.551 + role="special">.hgrc</filename> in your home directory. 11.552 + Mercurial will use this file to look up your personalised 11.553 + configuration settings. The initial contents of your 11.554 + <filename role="special">.hgrc</filename> should look like 11.555 + this.</para> 11.556 + <programlisting># This is a Mercurial configuration file. 11.557 +[ui] 11.558 +username = Firstname Lastname 11.559 +<email.address@domain.net></programlisting> 11.560 + 11.561 + <para>The <quote><literal>[ui]</literal></quote> line begins a 11.562 + <emphasis>section</emphasis> of the config file, so you can 11.563 + read the <quote><literal>username = ...</literal></quote> 11.564 + line as meaning <quote>set the value of the 11.565 + <literal>username</literal> item in the 11.566 + <literal>ui</literal> section</quote>. A section continues 11.567 + until a new section begins, or the end of the file. 11.568 + Mercurial ignores empty lines and treats any text from 11.569 + <quote><literal>#</literal></quote> to the end of a line as 11.570 + a comment.</para> 11.571 + </sect3> 11.572 + 11.573 + <sect3> 11.574 + <title>Choosing a user name</title> 11.575 + 11.576 + <para>You can use any text you like as the value of 11.577 + the <literal>username</literal> config item, since this 11.578 + information is for reading by other people, but for 11.579 + interpreting by Mercurial. The convention that most 11.580 + people follow is to use their name and email address, as 11.581 + in the example above.</para> 11.582 + <note> 11.583 + <para>Mercurial's built-in web server obfuscates 11.584 + email addresses, to make it more difficult for the email 11.585 + harvesting tools that spammers use. This reduces the 11.586 + likelihood that you'll start receiving more junk email 11.587 + if you publish a Mercurial repository on the 11.588 + web.</para></note> 11.589 + 11.590 + </sect3> 11.591 + </sect2> 11.592 + <sect2> 11.593 + <title>Writing a commit message</title> 11.594 + 11.595 + <para>When we commit a change, Mercurial drops us into 11.596 + a text editor, to enter a message that will describe the 11.597 + modifications we've made in this changeset. This is called 11.598 + the <emphasis>commit message</emphasis>. It will be a 11.599 + record for readers of what we did and why, and it will be 11.600 + printed by <command role="hg-cmd">hg log</command> after 11.601 + we've finished committing.</para> 11.602 + 11.603 + &interaction.tour.commit; 11.604 + 11.605 + <para>The editor that the <command role="hg-cmd">hg 11.606 + commit</command> command drops us into will contain an 11.607 + empty line, followed by a number of lines starting with 11.608 + <quote><literal>HG:</literal></quote>.</para> 11.609 + 11.610 + <programlisting>XXX fix this XXX</programlisting> 11.611 + 11.612 + <para>Mercurial ignores the lines that start with 11.613 + <quote><literal>HG:</literal></quote>; it uses them only to 11.614 + tell us which files it's recording changes to. Modifying or 11.615 + deleting these lines has no effect.</para> 11.616 + </sect2> 11.617 + <sect2> 11.618 + <title>Writing a good commit message</title> 11.619 + 11.620 + <para>Since <command role="hg-cmd">hg log</command> 11.621 + only prints the first line of a commit message by default, 11.622 + it's best to write a commit message whose first line stands 11.623 + alone. Here's a real example of a commit message that 11.624 + <emphasis>doesn't</emphasis> follow this guideline, and 11.625 + hence has a summary that is not 11.626 + readable.</para> 11.627 + 11.628 + <programlisting> 11.629 +changeset: 73:584af0e231be 11.630 +user: Censored Person <censored.person@example.org> 11.631 +date: Tue Sep 26 21:37:07 2006 -0700 11.632 +summary: include buildmeister/commondefs. Add exports.</programlisting> 11.633 + 11.634 + <para>As far as the remainder of the contents of the 11.635 + commit message are concerned, there are no hard-and-fast 11.636 + rules. Mercurial itself doesn't interpret or care about the 11.637 + contents of the commit message, though your project may have 11.638 + policies that dictate a certain kind of 11.639 + formatting.</para> 11.640 + <para>My personal preference is for short, but 11.641 + informative, commit messages that tell me something that I 11.642 + can't figure out with a quick glance at the output of 11.643 + <command role="hg-cmd">hg log 11.644 + --patch</command>.</para> 11.645 + </sect2> 11.646 + <sect2> 11.647 + <title>Aborting a commit</title> 11.648 + 11.649 + <para>If you decide that you don't want to commit 11.650 + while in the middle of editing a commit message, simply exit 11.651 + from your editor without saving the file that it's editing. 11.652 + This will cause nothing to happen to either the repository 11.653 + or the working directory.</para> 11.654 + <para>If we run the <command role="hg-cmd">hg 11.655 + commit</command> command without any arguments, it records 11.656 + all of the changes we've made, as reported by <command 11.657 + role="hg-cmd">hg status</command> and <command 11.658 + role="hg-cmd">hg diff</command>.</para> 11.659 + </sect2> 11.660 + <sect2> 11.661 + <title>Admiring our new handiwork</title> 11.662 + 11.663 + <para>Once we've finished the commit, we can use the 11.664 + <command role="hg-cmd">hg tip</command> command to display 11.665 + the changeset we just created. This command produces output 11.666 + that is identical to <command role="hg-cmd">hg 11.667 + log</command>, but it only displays the newest revision in 11.668 + the repository.</para> 11.669 + 11.670 + &interaction.tour.tip; 11.671 + 11.672 + <para>We refer to 11.673 + the newest revision in the repository as the tip revision, 11.674 + or simply the tip.</para> 11.675 + </sect2> 11.676 + </sect1> 11.677 + 11.678 + <sect1> 11.679 + <title>Sharing changes</title> 11.680 + 11.681 + <para>We mentioned earlier that repositories in 11.682 + Mercurial are self-contained. This means that the changeset 11.683 + we just created exists only in our <filename 11.684 + class="directory">my-hello</filename> repository. Let's 11.685 + look at a few ways that we can propagate this change into 11.686 + other repositories.</para> 11.687 + 11.688 + <sect2 id="sec.tour.pull"> 11.689 + <title>Pulling changes from another repository</title> 11.690 + <para>To get started, let's clone our original 11.691 + <filename class="directory">hello</filename> repository, 11.692 + which does not contain the change we just committed. We'll 11.693 + call our temporary repository <filename 11.694 + class="directory">hello-pull</filename>.</para> 11.695 + 11.696 + &interaction.tour.clone-pull; 11.697 + 11.698 + <para>We'll use the <command role="hg-cmd">hg 11.699 + pull</command> command to bring changes from <filename 11.700 + class="directory">my-hello</filename> into <filename 11.701 + class="directory">hello-pull</filename>. However, blindly 11.702 + pulling unknown changes into a repository is a somewhat 11.703 + scary prospect. Mercurial provides the <command 11.704 + role="hg-cmd">hg incoming</command> command to tell us 11.705 + what changes the <command role="hg-cmd">hg pull</command> 11.706 + command <emphasis>would</emphasis> pull into the repository, 11.707 + without actually pulling the changes in.</para> 11.708 + 11.709 + &interaction.tour.incoming; 11.710 + 11.711 + <para>(Of course, someone could 11.712 + cause more changesets to appear in the repository that we 11.713 + ran <command role="hg-cmd">hg incoming</command> in, before 11.714 + we get a chance to <command role="hg-cmd">hg pull</command> 11.715 + the changes, so that we could end up pulling changes that we 11.716 + didn't expect.)</para> 11.717 + 11.718 + <para>Bringing changes into a repository is a simple 11.719 + matter of running the <command role="hg-cmd">hg 11.720 + pull</command> command, and telling it which repository to 11.721 + pull from.</para> 11.722 + 11.723 + &interaction.tour.pull; 11.724 + 11.725 + <para>As you can see 11.726 + from the before-and-after output of <command 11.727 + role="hg-cmd">hg tip</command>, we have successfully 11.728 + pulled changes into our repository. There remains one step 11.729 + before we can see these changes in the working 11.730 + directory.</para> 11.731 + </sect2> 11.732 + <sect2> 11.733 + <title>Updating the working directory</title> 11.734 + 11.735 + <para>We have so far glossed over the relationship between a 11.736 + repository and its working directory. The <command 11.737 + role="hg-cmd">hg pull</command> command that we ran in 11.738 + section <xref linkend="sec.tour.pull"/> brought changes 11.739 + into the repository, but if we check, there's no sign of those 11.740 + changes in the working directory. This is because <command 11.741 + role="hg-cmd">hg pull</command> does not (by default) touch 11.742 + the working directory. Instead, we use the <command 11.743 + role="hg-cmd">hg update</command> command to do this.</para> 11.744 + 11.745 + &interaction.tour.update; 11.746 + 11.747 + <para>It might seem a bit strange that <command role="hg-cmd">hg 11.748 + pull</command> doesn't update the working directory 11.749 + automatically. There's actually a good reason for this: you 11.750 + can use <command role="hg-cmd">hg update</command> to update 11.751 + the working directory to the state it was in at <emphasis>any 11.752 + revision</emphasis> in the history of the repository. If 11.753 + you had the working directory updated to an old revision---to 11.754 + hunt down the origin of a bug, say---and ran a <command 11.755 + role="hg-cmd">hg pull</command> which automatically updated 11.756 + the working directory to a new revision, you might not be 11.757 + terribly happy.</para> 11.758 + <para>However, since pull-then-update is such a common thing to 11.759 + do, Mercurial lets you combine the two by passing the <option 11.760 + role="hg-opt-pull">-u</option> option to <command 11.761 + role="hg-cmd">hg pull</command>.</para> 11.762 + 11.763 + <para>If you look back at the output of <command 11.764 + role="hg-cmd">hg pull</command> in section <xref 11.765 + linkend="sec.tour.pull"/> when we ran it without <option 11.766 + role="hg-opt-pull">-u</option>, you can see that it printed 11.767 + a helpful reminder that we'd have to take an explicit step to 11.768 + update the working directory:</para> 11.769 + 11.770 + <!-- &interaction.xxx.fixme; --> 11.771 + 11.772 + <para>To find out what revision the working directory is at, use 11.773 + the <command role="hg-cmd">hg parents</command> 11.774 + command.</para> 11.775 + 11.776 + &interaction.tour.parents; 11.777 + 11.778 + <para>If you look back at figure <xref 11.779 + endterm="fig.tour-basic.history.caption" 11.780 + linkend="fig.tour-basic.history"/>, 11.781 + you'll see arrows connecting each changeset. The node that 11.782 + the arrow leads <emphasis>from</emphasis> in each case is a 11.783 + parent, and the node that the arrow leads 11.784 + <emphasis>to</emphasis> is its child. The working directory 11.785 + has a parent in just the same way; this is the changeset that 11.786 + the working directory currently contains.</para> 11.787 + 11.788 + <para>To update the working directory to a particular revision, 11.789 + 11.790 + give a revision number or changeset ID to the <command 11.791 + role="hg-cmd">hg update</command> command.</para> 11.792 + 11.793 + &interaction.tour.older; 11.794 + 11.795 + <para>If you omit an explicit revision, <command 11.796 + role="hg-cmd">hg update</command> will update to the tip 11.797 + revision, as shown by the second call to <command 11.798 + role="hg-cmd">hg update</command> in the example 11.799 + above.</para> 11.800 + </sect2> 11.801 + 11.802 + <sect2> 11.803 + <title>Pushing changes to another repository</title> 11.804 + 11.805 + <para>Mercurial lets us push changes to another 11.806 + repository, from the repository we're currently visiting. 11.807 + As with the example of <command role="hg-cmd">hg 11.808 + pull</command> above, we'll create a temporary repository 11.809 + to push our changes into.</para> 11.810 + 11.811 + &interaction.tour.clone-push; 11.812 + 11.813 + <para>The <command role="hg-cmd">hg outgoing</command> command 11.814 + tells us what changes would be pushed into another 11.815 + repository.</para> 11.816 + 11.817 + &interaction.tour.outgoing; 11.818 + 11.819 + <para>And the 11.820 + <command role="hg-cmd">hg push</command> command does the 11.821 + actual push.</para> 11.822 + 11.823 + &interaction.tour.push; 11.824 + 11.825 + <para>As with 11.826 + <command role="hg-cmd">hg pull</command>, the <command 11.827 + role="hg-cmd">hg push</command> command does not update 11.828 + the working directory in the repository that it's pushing 11.829 + changes into. (Unlike <command role="hg-cmd">hg 11.830 + pull</command>, <command role="hg-cmd">hg push</command> 11.831 + does not provide a <literal>-u</literal> option that updates 11.832 + the other repository's working directory.)</para> 11.833 + 11.834 + <para>What happens if we try to pull or push changes 11.835 + and the receiving repository already has those changes? 11.836 + Nothing too exciting.</para> 11.837 + 11.838 + &interaction.tour.push.nothing; 11.839 + </sect2> 11.840 + <sect2> 11.841 + <title>Sharing changes over a network</title> 11.842 + 11.843 + <para>The commands we have covered in the previous few 11.844 + sections are not limited to working with local repositories. 11.845 + Each works in exactly the same fashion over a network 11.846 + connection; simply pass in a URL instead of a local 11.847 + path.</para> 11.848 + 11.849 + &interaction.tour.outgoing.net; 11.850 + 11.851 + <para>In this example, we 11.852 + can see what changes we could push to the remote repository, 11.853 + but the repository is understandably not set up to let 11.854 + anonymous users push to it.</para> 11.855 + 11.856 + &interaction.tour.push.net; 11.857 + </sect2> 11.858 + </sect1> 11.859 +</chapter> 11.860 + 11.861 +<!-- 11.862 +local variables: 11.863 +sgml-parent-document: ("00book.xml" "book" "chapter") 11.864 +end: 11.865 +-->
12.1 --- a/en/ch02-tour-basic.xml Fri Mar 20 15:40:06 2009 +0800 12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 12.3 @@ -1,862 +0,0 @@ 12.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 12.5 - 12.6 -<chapter id="chap.tour-basic"> 12.7 - <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?> 12.8 - <title>A tour of Mercurial: the basics</title> 12.9 - 12.10 - <sect1 id="sec.tour.install"> 12.11 - <title>Installing Mercurial on your system</title> 12.12 - 12.13 - <para>Prebuilt binary packages of Mercurial are available for 12.14 - every popular operating system. These make it easy to start 12.15 - using Mercurial on your computer immediately.</para> 12.16 - 12.17 - <sect2> 12.18 - <title>Linux</title> 12.19 - 12.20 - <para>Because each Linux distribution has its own packaging 12.21 - tools, policies, and rate of development, it's difficult to 12.22 - give a comprehensive set of instructions on how to install 12.23 - Mercurial binaries. The version of Mercurial that you will 12.24 - end up with can vary depending on how active the person is who 12.25 - maintains the package for your distribution.</para> 12.26 - 12.27 - <para>To keep things simple, I will focus on installing 12.28 - Mercurial from the command line under the most popular Linux 12.29 - distributions. Most of these distributions provide graphical 12.30 - package managers that will let you install Mercurial with a 12.31 - single click; the package name to look for is 12.32 - <literal>mercurial</literal>.</para> 12.33 - 12.34 - <itemizedlist> 12.35 - <listitem><para>Debian:</para> 12.36 - <programlisting>apt-get install mercurial</programlisting></listitem> 12.37 - <listitem><para>Fedora Core:</para> 12.38 - <programlisting>yum install mercurial</programlisting></listitem> 12.39 - <listitem><para>Gentoo:</para> 12.40 - <programlisting>emerge mercurial</programlisting></listitem> 12.41 - <listitem><para>OpenSUSE:</para> 12.42 - <programlisting>yum install mercurial</programlisting></listitem> 12.43 - <listitem><para>Ubuntu: Ubuntu's Mercurial package is based on 12.44 - Debian's. To install it, run the following 12.45 - command.</para> 12.46 - <programlisting>apt-get install mercurial</programlisting></listitem> 12.47 - </itemizedlist> 12.48 - 12.49 - </sect2> 12.50 - <sect2> 12.51 - <title>Solaris</title> 12.52 - 12.53 - <para>SunFreeWare, at <ulink 12.54 - url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>, 12.55 - is a good source for a large number of pre-built Solaris 12.56 - packages for 32 and 64 bit Intel and Sparc architectures, 12.57 - including current versions of Mercurial.</para> 12.58 - 12.59 - </sect2> 12.60 - <sect2> 12.61 - <title>Mac OS X</title> 12.62 - 12.63 - <para>Lee Cantey publishes an installer of Mercurial for Mac OS 12.64 - X at <ulink 12.65 - url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 12.66 - This package works on both Intel- and Power-based Macs. Before 12.67 - you can use it, you must install a compatible version of 12.68 - Universal MacPython <citation>web:macpython</citation>. This 12.69 - is easy to do; simply follow the instructions on Lee's 12.70 - site.</para> 12.71 - 12.72 - <para>It's also possible to install Mercurial using Fink or 12.73 - MacPorts, two popular free package managers for Mac OS X. If 12.74 - you have Fink, use <command>sudo apt-get install 12.75 - mercurial-py25</command>. If MacPorts, <command>sudo port 12.76 - install mercurial</command>.</para> 12.77 - 12.78 - </sect2> 12.79 - <sect2> 12.80 - <title>Windows</title> 12.81 - 12.82 - <para>Lee Cantey publishes an installer of Mercurial for Windows 12.83 - at <ulink 12.84 - url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 12.85 - This package has no external dependencies; it <quote>just 12.86 - works</quote>.</para> 12.87 - 12.88 - <note> 12.89 - <para> The Windows version of Mercurial does not 12.90 - automatically convert line endings between Windows and Unix 12.91 - styles. If you want to share work with Unix users, you must 12.92 - do a little additional configuration work. XXX Flesh this 12.93 - out.</para> 12.94 - </note> 12.95 - 12.96 - </sect2> 12.97 - </sect1> 12.98 - <sect1> 12.99 - <title>Getting started</title> 12.100 - 12.101 - <para>To begin, we'll use the <command role="hg-cmd">hg 12.102 - version</command> command to find out whether Mercurial is 12.103 - actually installed properly. The actual version information 12.104 - that it prints isn't so important; it's whether it prints 12.105 - anything at all that we care about.</para> 12.106 - 12.107 - &interaction.tour.version; 12.108 - 12.109 - <sect2> 12.110 - <title>Built-in help</title> 12.111 - 12.112 - <para>Mercurial provides a built-in help system. This is 12.113 - invaluable for those times when you find yourself stuck 12.114 - trying to remember how to run a command. If you are 12.115 - completely stuck, simply run <command role="hg-cmd">hg 12.116 - help</command>; it will print a brief list of commands, 12.117 - along with a description of what each does. If you ask for 12.118 - help on a specific command (as below), it prints more 12.119 - detailed information.</para> 12.120 - 12.121 - &interaction.tour.help; 12.122 - 12.123 - <para>For a more impressive level of detail (which you won't 12.124 - usually need) run <command role="hg-cmd">hg help <option 12.125 - role="hg-opt-global">-v</option></command>. The <option 12.126 - role="hg-opt-global">-v</option> option is short for 12.127 - <option role="hg-opt-global">--verbose</option>, and tells 12.128 - Mercurial to print more information than it usually 12.129 - would.</para> 12.130 - 12.131 - </sect2> 12.132 - </sect1> 12.133 - <sect1> 12.134 - <title>Working with a repository</title> 12.135 - 12.136 - <para>In Mercurial, everything happens inside a 12.137 - <emphasis>repository</emphasis>. The repository for a project 12.138 - contains all of the files that <quote>belong to</quote> that 12.139 - project, along with a historical record of the project's 12.140 - files.</para> 12.141 - 12.142 - <para>There's nothing particularly magical about a repository; it 12.143 - is simply a directory tree in your filesystem that Mercurial 12.144 - treats as special. You can rename or delete a repository any 12.145 - time you like, using either the command line or your file 12.146 - browser.</para> 12.147 - 12.148 - <sect2> 12.149 - <title>Making a local copy of a repository</title> 12.150 - 12.151 - <para><emphasis>Copying</emphasis> a repository is just a little 12.152 - bit special. While you could use a normal file copying 12.153 - command to make a copy of a repository, it's best to use a 12.154 - built-in command that Mercurial provides. This command is 12.155 - called <command role="hg-cmd">hg clone</command>, because it 12.156 - creates an identical copy of an existing repository.</para> 12.157 - 12.158 - &interaction.tour.clone; 12.159 - 12.160 - <para>If our clone succeeded, we should now have a local 12.161 - directory called <filename class="directory">hello</filename>. 12.162 - This directory will contain some files.</para> 12.163 - 12.164 - &interaction.tour.ls; 12.165 - 12.166 - <para>These files have the same contents and history in our 12.167 - repository as they do in the repository we cloned.</para> 12.168 - 12.169 - <para>Every Mercurial repository is complete, self-contained, 12.170 - and independent. It contains its own private copy of a 12.171 - project's files and history. A cloned repository remembers 12.172 - the location of the repository it was cloned from, but it does 12.173 - not communicate with that repository, or any other, unless you 12.174 - tell it to.</para> 12.175 - 12.176 - <para>What this means for now is that we're free to experiment 12.177 - with our repository, safe in the knowledge that it's a private 12.178 - <quote>sandbox</quote> that won't affect anyone else.</para> 12.179 - 12.180 - </sect2> 12.181 - <sect2> 12.182 - <title>What's in a repository?</title> 12.183 - 12.184 - <para>When we take a more detailed look inside a repository, we 12.185 - can see that it contains a directory named <filename 12.186 - class="directory">.hg</filename>. This is where Mercurial 12.187 - keeps all of its metadata for the repository.</para> 12.188 - 12.189 - &interaction.tour.ls-a; 12.190 - 12.191 - <para>The contents of the <filename 12.192 - class="directory">.hg</filename> directory and its 12.193 - subdirectories are private to Mercurial. Every other file and 12.194 - directory in the repository is yours to do with as you 12.195 - please.</para> 12.196 - 12.197 - <para>To introduce a little terminology, the <filename 12.198 - class="directory">.hg</filename> directory is the 12.199 - <quote>real</quote> repository, and all of the files and 12.200 - directories that coexist with it are said to live in the 12.201 - <emphasis>working directory</emphasis>. An easy way to 12.202 - remember the distinction is that the 12.203 - <emphasis>repository</emphasis> contains the 12.204 - <emphasis>history</emphasis> of your project, while the 12.205 - <emphasis>working directory</emphasis> contains a 12.206 - <emphasis>snapshot</emphasis> of your project at a particular 12.207 - point in history.</para> 12.208 - 12.209 - </sect2> 12.210 - </sect1> 12.211 - <sect1> 12.212 - <title>A tour through history</title> 12.213 - 12.214 - <para>One of the first things we might want to do with a new, 12.215 - unfamiliar repository is understand its history. The <command 12.216 - role="hg-cmd">hg log</command> command gives us a view of 12.217 - history.</para> 12.218 - 12.219 - &interaction.tour.log; 12.220 - 12.221 - <para>By default, this command prints a brief paragraph of output 12.222 - for each change to the project that was recorded. In Mercurial 12.223 - terminology, we call each of these recorded events a 12.224 - <emphasis>changeset</emphasis>, because it can contain a record 12.225 - of changes to several files.</para> 12.226 - 12.227 - <para>The fields in a record of output from <command 12.228 - role="hg-cmd">hg log</command> are as follows.</para> 12.229 - <itemizedlist> 12.230 - <listitem><para><literal>changeset</literal>: This field has the 12.231 - format of a number, followed by a colon, followed by a 12.232 - hexadecimal string. These are 12.233 - <emphasis>identifiers</emphasis> for the changeset. There 12.234 - are two identifiers because the number is shorter and easier 12.235 - to type than the hex string.</para></listitem> 12.236 - <listitem><para><literal>user</literal>: The identity of the 12.237 - person who created the changeset. This is a free-form 12.238 - field, but it most often contains a person's name and email 12.239 - address.</para></listitem> 12.240 - <listitem><para><literal>date</literal>: The date and time on 12.241 - which the changeset was created, and the timezone in which 12.242 - it was created. (The date and time are local to that 12.243 - timezone; they display what time and date it was for the 12.244 - person who created the changeset.)</para></listitem> 12.245 - <listitem><para><literal>summary</literal>: The first line of 12.246 - the text message that the creator of the changeset entered 12.247 - to describe the changeset.</para></listitem></itemizedlist> 12.248 - <para>The default output printed by <command role="hg-cmd">hg 12.249 - log</command> is purely a summary; it is missing a lot of 12.250 - detail.</para> 12.251 - 12.252 - <para>Figure <xref endterm="fig.tour-basic.history.caption" 12.253 - linkend="fig.tour-basic.history"/> provides a 12.254 - graphical representation of the history of the <filename 12.255 - class="directory">hello</filename> repository, to make it a 12.256 - little easier to see which direction history is 12.257 - <quote>flowing</quote> in. We'll be returning to this figure 12.258 - several times in this chapter and the chapter that 12.259 - follows.</para> 12.260 - 12.261 - <informalfigure id="fig.tour-basic.history"> 12.262 - <mediaobject> 12.263 - <imageobject><imagedata fileref="images/tour-history.png"/></imageobject> 12.264 - <textobject><phrase>XXX add text</phrase></textobject> 12.265 - <caption><para id="fig.tour-basic.history.caption">Graphical history of 12.266 - the <filename class="directory">hello</filename> repository</para> 12.267 - </caption> 12.268 - </mediaobject> 12.269 - </informalfigure> 12.270 - 12.271 - <sect2> 12.272 - <title>Changesets, revisions, and talking to other 12.273 - people</title> 12.274 - 12.275 - <para>As English is a notoriously sloppy language, and computer 12.276 - science has a hallowed history of terminological confusion 12.277 - (why use one term when four will do?), revision control has a 12.278 - variety of words and phrases that mean the same thing. If you 12.279 - are talking about Mercurial history with other people, you 12.280 - will find that the word <quote>changeset</quote> is often 12.281 - compressed to <quote>change</quote> or (when written) 12.282 - <quote>cset</quote>, and sometimes a changeset is referred to 12.283 - as a <quote>revision</quote> or a <quote>rev</quote>.</para> 12.284 - 12.285 - <para>While it doesn't matter what <emphasis>word</emphasis> you 12.286 - use to refer to the concept of <quote>a changeset</quote>, the 12.287 - <emphasis>identifier</emphasis> that you use to refer to 12.288 - <quote>a <emphasis>specific</emphasis> changeset</quote> is of 12.289 - great importance. Recall that the <literal>changeset</literal> 12.290 - field in the output from <command role="hg-cmd">hg 12.291 - log</command> identifies a changeset using both a number and 12.292 - a hexadecimal string.</para> 12.293 - <itemizedlist> 12.294 - <listitem><para>The revision number is <emphasis>only valid in 12.295 - that repository</emphasis>,</para></listitem> 12.296 - <listitem><para>while the hex string is the 12.297 - <emphasis>permanent, unchanging identifier</emphasis> that 12.298 - will always identify that exact changeset in 12.299 - <emphasis>every</emphasis> copy of the 12.300 - repository.</para></listitem></itemizedlist> 12.301 - <para>This distinction is important. If you send someone an 12.302 - email talking about <quote>revision 33</quote>, there's a high 12.303 - likelihood that their revision 33 will <emphasis>not be the 12.304 - same</emphasis> as yours. The reason for this is that a 12.305 - revision number depends on the order in which changes arrived 12.306 - in a repository, and there is no guarantee that the same 12.307 - changes will happen in the same order in different 12.308 - repositories. Three changes $a,b,c$ can easily appear in one 12.309 - repository as $0,1,2$, while in another as $1,0,2$.</para> 12.310 - 12.311 - <para>Mercurial uses revision numbers purely as a convenient 12.312 - shorthand. If you need to discuss a changeset with someone, 12.313 - or make a record of a changeset for some other reason (for 12.314 - example, in a bug report), use the hexadecimal 12.315 - identifier.</para> 12.316 - 12.317 - </sect2> 12.318 - <sect2> 12.319 - <title>Viewing specific revisions</title> 12.320 - 12.321 - <para>To narrow the output of <command role="hg-cmd">hg 12.322 - log</command> down to a single revision, use the <option 12.323 - role="hg-opt-log">-r</option> (or <option 12.324 - role="hg-opt-log">--rev</option>) option. You can use 12.325 - either a revision number or a long-form changeset identifier, 12.326 - and you can provide as many revisions as you want.</para> 12.327 - 12.328 - &interaction.tour.log-r; 12.329 - 12.330 - <para>If you want to see the history of several revisions 12.331 - without having to list each one, you can use <emphasis>range 12.332 - notation</emphasis>; this lets you express the idea <quote>I 12.333 - want all revisions between <literal>abc</literal> and 12.334 - <literal>def</literal>, inclusive</quote>.</para> 12.335 - 12.336 - &interaction.tour.log.range; 12.337 - 12.338 - <para>Mercurial also honours the order in which you specify 12.339 - revisions, so <command role="hg-cmd">hg log -r 2:4</command> 12.340 - prints 2, 3, and 4. while <command role="hg-cmd">hg log -r 12.341 - 4:2</command> prints 4, 3, and 2.</para> 12.342 - 12.343 - </sect2> 12.344 - <sect2> 12.345 - <title>More detailed information</title> 12.346 - 12.347 - <para>While the summary information printed by <command 12.348 - role="hg-cmd">hg log</command> is useful if you already know 12.349 - what you're looking for, you may need to see a complete 12.350 - description of the change, or a list of the files changed, if 12.351 - you're trying to decide whether a changeset is the one you're 12.352 - looking for. The <command role="hg-cmd">hg log</command> 12.353 - command's <option role="hg-opt-global">-v</option> (or <option 12.354 - role="hg-opt-global">--verbose</option>) option gives you 12.355 - this extra detail.</para> 12.356 - 12.357 - &interaction.tour.log-v; 12.358 - 12.359 - <para>If you want to see both the description and content of a 12.360 - change, add the <option role="hg-opt-log">-p</option> (or 12.361 - <option role="hg-opt-log">--patch</option>) option. This 12.362 - displays the content of a change as a <emphasis>unified 12.363 - diff</emphasis> (if you've never seen a unified diff before, 12.364 - see section <xref linkend="sec.mq.patch"/> for an 12.365 - overview).</para> 12.366 - 12.367 - &interaction.tour.log-vp; 12.368 - 12.369 - </sect2> 12.370 - </sect1> 12.371 - <sect1> 12.372 - <title>All about command options</title> 12.373 - 12.374 - <para>Let's take a brief break from exploring Mercurial commands 12.375 - to discuss a pattern in the way that they work; you may find 12.376 - this useful to keep in mind as we continue our tour.</para> 12.377 - 12.378 - <para>Mercurial has a consistent and straightforward approach to 12.379 - dealing with the options that you can pass to commands. It 12.380 - follows the conventions for options that are common to modern 12.381 - Linux and Unix systems.</para> 12.382 - <itemizedlist> 12.383 - <listitem><para>Every option has a long name. For example, as 12.384 - we've already seen, the <command role="hg-cmd">hg 12.385 - log</command> command accepts a <option 12.386 - role="hg-opt-log">--rev</option> option.</para></listitem> 12.387 - <listitem><para>Most options have short names, too. Instead of 12.388 - <option role="hg-opt-log">--rev</option>, we can use <option 12.389 - role="hg-opt-log">-r</option>. (The reason that some 12.390 - options don't have short names is that the options in 12.391 - question are rarely used.)</para></listitem> 12.392 - <listitem><para>Long options start with two dashes (e.g. <option 12.393 - role="hg-opt-log">--rev</option>), while short options 12.394 - start with one (e.g. <option 12.395 - role="hg-opt-log">-r</option>).</para></listitem> 12.396 - <listitem><para>Option naming and usage is consistent across 12.397 - commands. For example, every command that lets you specify 12.398 - a changeset ID or revision number accepts both <option 12.399 - role="hg-opt-log">-r</option> and <option 12.400 - role="hg-opt-log">--rev</option> 12.401 - arguments.</para></listitem></itemizedlist> 12.402 - <para>In the examples throughout this book, I use short options 12.403 - instead of long. This just reflects my own preference, so don't 12.404 - read anything significant into it.</para> 12.405 - 12.406 - <para>Most commands that print output of some kind will print more 12.407 - output when passed a <option role="hg-opt-global">-v</option> 12.408 - (or <option role="hg-opt-global">--verbose</option>) option, and 12.409 - less when passed <option role="hg-opt-global">-q</option> (or 12.410 - <option role="hg-opt-global">--quiet</option>).</para> 12.411 - 12.412 - </sect1> 12.413 - <sect1> 12.414 - <title>Making and reviewing changes</title> 12.415 - 12.416 - <para>Now that we have a grasp of viewing history in Mercurial, 12.417 - let's take a look at making some changes and examining 12.418 - them.</para> 12.419 - 12.420 - <para>The first thing we'll do is isolate our experiment in a 12.421 - repository of its own. We use the <command role="hg-cmd">hg 12.422 - clone</command> command, but we don't need to clone a copy of 12.423 - the remote repository. Since we already have a copy of it 12.424 - locally, we can just clone that instead. This is much faster 12.425 - than cloning over the network, and cloning a local repository 12.426 - uses less disk space in most cases, too.</para> 12.427 - 12.428 - &interaction.tour.reclone; 12.429 - 12.430 - <para>As an aside, it's often good practice to keep a 12.431 - <quote>pristine</quote> copy of a remote repository around, 12.432 - which you can then make temporary clones of to create sandboxes 12.433 - for each task you want to work on. This lets you work on 12.434 - multiple tasks in parallel, each isolated from the others until 12.435 - it's complete and you're ready to integrate it back. Because 12.436 - local clones are so cheap, there's almost no overhead to cloning 12.437 - and destroying repositories whenever you want.</para> 12.438 - 12.439 - <para>In our <filename class="directory">my-hello</filename> 12.440 - repository, we have a file <filename>hello.c</filename> that 12.441 - contains the classic <quote>hello, world</quote> program. Let's 12.442 - use the ancient and venerable <command>sed</command> command to 12.443 - edit this file so that it prints a second line of output. (I'm 12.444 - only using <command>sed</command> to do this because it's easy 12.445 - to write a scripted example this way. Since you're not under 12.446 - the same constraint, you probably won't want to use 12.447 - <command>sed</command>; simply use your preferred text editor to 12.448 - do the same thing.)</para> 12.449 - 12.450 - &interaction.tour.sed; 12.451 - 12.452 - <para>Mercurial's <command role="hg-cmd">hg status</command> 12.453 - command will tell us what Mercurial knows about the files in the 12.454 - repository.</para> 12.455 - 12.456 - &interaction.tour.status; 12.457 - 12.458 - <para>The <command role="hg-cmd">hg status</command> command 12.459 - prints no output for some files, but a line starting with 12.460 - <quote><literal>M</literal></quote> for 12.461 - <filename>hello.c</filename>. Unless you tell it to, <command 12.462 - role="hg-cmd">hg status</command> will not print any output 12.463 - for files that have not been modified.</para> 12.464 - 12.465 - <para>The <quote><literal>M</literal></quote> indicates that 12.466 - Mercurial has noticed that we modified 12.467 - <filename>hello.c</filename>. We didn't need to 12.468 - <emphasis>inform</emphasis> Mercurial that we were going to 12.469 - modify the file before we started, or that we had modified the 12.470 - file after we were done; it was able to figure this out 12.471 - itself.</para> 12.472 - 12.473 - <para>It's a little bit helpful to know that we've modified 12.474 - <filename>hello.c</filename>, but we might prefer to know 12.475 - exactly <emphasis>what</emphasis> changes we've made to it. To 12.476 - do this, we use the <command role="hg-cmd">hg diff</command> 12.477 - command.</para> 12.478 - 12.479 - &interaction.tour.diff; 12.480 - 12.481 - </sect1> 12.482 - <sect1> 12.483 - <title>Recording changes in a new changeset</title> 12.484 - 12.485 - <para>We can modify files, build and test our changes, and use 12.486 - <command role="hg-cmd">hg status</command> and <command 12.487 - role="hg-cmd">hg diff</command> to review our changes, until 12.488 - we're satisfied with what we've done and arrive at a natural 12.489 - stopping point where we want to record our work in a new 12.490 - changeset.</para> 12.491 - 12.492 - <para>The <command role="hg-cmd">hg commit</command> command lets 12.493 - us create a new changeset; we'll usually refer to this as 12.494 - <quote>making a commit</quote> or 12.495 - <quote>committing</quote>.</para> 12.496 - 12.497 - <sect2> 12.498 - <title>Setting up a username</title> 12.499 - 12.500 - <para>When you try to run <command role="hg-cmd">hg 12.501 - commit</command> for the first time, it is not guaranteed to 12.502 - succeed. Mercurial records your name and address with each 12.503 - change that you commit, so that you and others will later be 12.504 - able to tell who made each change. Mercurial tries to 12.505 - automatically figure out a sensible username to commit the 12.506 - change with. It will attempt each of the following methods, 12.507 - in order:</para> 12.508 - <orderedlist> 12.509 - <listitem><para>If you specify a <option 12.510 - role="hg-opt-commit">-u</option> option to the <command 12.511 - role="hg-cmd">hg commit</command> command on the command 12.512 - line, followed by a username, this is always given the 12.513 - highest precedence.</para></listitem> 12.514 - <listitem><para>If you have set the <envar>HGUSER</envar> 12.515 - environment variable, this is checked 12.516 - next.</para></listitem> 12.517 - <listitem><para>If you create a file in your home directory 12.518 - called <filename role="special">.hgrc</filename>, with a 12.519 - <envar role="rc-item-ui">username</envar> entry, that will 12.520 - be used next. To see what the contents of this file 12.521 - should look like, refer to section <xref 12.522 - linkend="sec.tour-basic.username"/> 12.523 - below.</para></listitem> 12.524 - <listitem><para>If you have set the <envar>EMAIL</envar> 12.525 - environment variable, this will be used 12.526 - next.</para></listitem> 12.527 - <listitem><para>Mercurial will query your system to find out 12.528 - your local user name and host name, and construct a 12.529 - username from these components. Since this often results 12.530 - in a username that is not very useful, it will print a 12.531 - warning if it has to do 12.532 - this.</para></listitem> 12.533 - </orderedlist> 12.534 - <para>If all of these mechanisms fail, Mercurial will 12.535 - fail, printing an error message. In this case, it will not 12.536 - let you commit until you set up a 12.537 - username.</para> 12.538 - <para>You should think of the <envar>HGUSER</envar> environment 12.539 - variable and the <option role="hg-opt-commit">-u</option> 12.540 - option to the <command role="hg-cmd">hg commit</command> 12.541 - command as ways to <emphasis>override</emphasis> Mercurial's 12.542 - default selection of username. For normal use, the simplest 12.543 - and most robust way to set a username for yourself is by 12.544 - creating a <filename role="special">.hgrc</filename> file; see 12.545 - below for details.</para> 12.546 - <sect3 id="sec.tour-basic.username"> 12.547 - <title>Creating a Mercurial configuration file</title> 12.548 - 12.549 - <para>To set a user name, use your favourite editor 12.550 - to create a file called <filename 12.551 - role="special">.hgrc</filename> in your home directory. 12.552 - Mercurial will use this file to look up your personalised 12.553 - configuration settings. The initial contents of your 12.554 - <filename role="special">.hgrc</filename> should look like 12.555 - this.</para> 12.556 - <programlisting># This is a Mercurial configuration file. 12.557 -[ui] 12.558 -username = Firstname Lastname 12.559 -<email.address@domain.net></programlisting> 12.560 - 12.561 - <para>The <quote><literal>[ui]</literal></quote> line begins a 12.562 - <emphasis>section</emphasis> of the config file, so you can 12.563 - read the <quote><literal>username = ...</literal></quote> 12.564 - line as meaning <quote>set the value of the 12.565 - <literal>username</literal> item in the 12.566 - <literal>ui</literal> section</quote>. A section continues 12.567 - until a new section begins, or the end of the file. 12.568 - Mercurial ignores empty lines and treats any text from 12.569 - <quote><literal>#</literal></quote> to the end of a line as 12.570 - a comment.</para> 12.571 - </sect3> 12.572 - 12.573 - <sect3> 12.574 - <title>Choosing a user name</title> 12.575 - 12.576 - <para>You can use any text you like as the value of 12.577 - the <literal>username</literal> config item, since this 12.578 - information is for reading by other people, but for 12.579 - interpreting by Mercurial. The convention that most 12.580 - people follow is to use their name and email address, as 12.581 - in the example above.</para> 12.582 - <note> 12.583 - <para>Mercurial's built-in web server obfuscates 12.584 - email addresses, to make it more difficult for the email 12.585 - harvesting tools that spammers use. This reduces the 12.586 - likelihood that you'll start receiving more junk email 12.587 - if you publish a Mercurial repository on the 12.588 - web.</para></note> 12.589 - 12.590 - </sect3> 12.591 - </sect2> 12.592 - <sect2> 12.593 - <title>Writing a commit message</title> 12.594 - 12.595 - <para>When we commit a change, Mercurial drops us into 12.596 - a text editor, to enter a message that will describe the 12.597 - modifications we've made in this changeset. This is called 12.598 - the <emphasis>commit message</emphasis>. It will be a 12.599 - record for readers of what we did and why, and it will be 12.600 - printed by <command role="hg-cmd">hg log</command> after 12.601 - we've finished committing.</para> 12.602 - 12.603 - &interaction.tour.commit; 12.604 - 12.605 - <para>The editor that the <command role="hg-cmd">hg 12.606 - commit</command> command drops us into will contain an 12.607 - empty line, followed by a number of lines starting with 12.608 - <quote><literal>HG:</literal></quote>.</para> 12.609 - 12.610 - <programlisting>XXX fix this XXX</programlisting> 12.611 - 12.612 - <para>Mercurial ignores the lines that start with 12.613 - <quote><literal>HG:</literal></quote>; it uses them only to 12.614 - tell us which files it's recording changes to. Modifying or 12.615 - deleting these lines has no effect.</para> 12.616 - </sect2> 12.617 - <sect2> 12.618 - <title>Writing a good commit message</title> 12.619 - 12.620 - <para>Since <command role="hg-cmd">hg log</command> 12.621 - only prints the first line of a commit message by default, 12.622 - it's best to write a commit message whose first line stands 12.623 - alone. Here's a real example of a commit message that 12.624 - <emphasis>doesn't</emphasis> follow this guideline, and 12.625 - hence has a summary that is not 12.626 - readable.</para> 12.627 - 12.628 - <programlisting> 12.629 -changeset: 73:584af0e231be 12.630 -user: Censored Person <censored.person@example.org> 12.631 -date: Tue Sep 26 21:37:07 2006 -0700 12.632 -summary: include buildmeister/commondefs. Add exports.</programlisting> 12.633 - 12.634 - <para>As far as the remainder of the contents of the 12.635 - commit message are concerned, there are no hard-and-fast 12.636 - rules. Mercurial itself doesn't interpret or care about the 12.637 - contents of the commit message, though your project may have 12.638 - policies that dictate a certain kind of 12.639 - formatting.</para> 12.640 - <para>My personal preference is for short, but 12.641 - informative, commit messages that tell me something that I 12.642 - can't figure out with a quick glance at the output of 12.643 - <command role="hg-cmd">hg log 12.644 - --patch</command>.</para> 12.645 - </sect2> 12.646 - <sect2> 12.647 - <title>Aborting a commit</title> 12.648 - 12.649 - <para>If you decide that you don't want to commit 12.650 - while in the middle of editing a commit message, simply exit 12.651 - from your editor without saving the file that it's editing. 12.652 - This will cause nothing to happen to either the repository 12.653 - or the working directory.</para> 12.654 - <para>If we run the <command role="hg-cmd">hg 12.655 - commit</command> command without any arguments, it records 12.656 - all of the changes we've made, as reported by <command 12.657 - role="hg-cmd">hg status</command> and <command 12.658 - role="hg-cmd">hg diff</command>.</para> 12.659 - </sect2> 12.660 - <sect2> 12.661 - <title>Admiring our new handiwork</title> 12.662 - 12.663 - <para>Once we've finished the commit, we can use the 12.664 - <command role="hg-cmd">hg tip</command> command to display 12.665 - the changeset we just created. This command produces output 12.666 - that is identical to <command role="hg-cmd">hg 12.667 - log</command>, but it only displays the newest revision in 12.668 - the repository.</para> 12.669 - 12.670 - &interaction.tour.tip; 12.671 - 12.672 - <para>We refer to 12.673 - the newest revision in the repository as the tip revision, 12.674 - or simply the tip.</para> 12.675 - </sect2> 12.676 - </sect1> 12.677 - 12.678 - <sect1> 12.679 - <title>Sharing changes</title> 12.680 - 12.681 - <para>We mentioned earlier that repositories in 12.682 - Mercurial are self-contained. This means that the changeset 12.683 - we just created exists only in our <filename 12.684 - class="directory">my-hello</filename> repository. Let's 12.685 - look at a few ways that we can propagate this change into 12.686 - other repositories.</para> 12.687 - 12.688 - <sect2 id="sec.tour.pull"> 12.689 - <title>Pulling changes from another repository</title> 12.690 - <para>To get started, let's clone our original 12.691 - <filename class="directory">hello</filename> repository, 12.692 - which does not contain the change we just committed. We'll 12.693 - call our temporary repository <filename 12.694 - class="directory">hello-pull</filename>.</para> 12.695 - 12.696 - &interaction.tour.clone-pull; 12.697 - 12.698 - <para>We'll use the <command role="hg-cmd">hg 12.699 - pull</command> command to bring changes from <filename 12.700 - class="directory">my-hello</filename> into <filename 12.701 - class="directory">hello-pull</filename>. However, blindly 12.702 - pulling unknown changes into a repository is a somewhat 12.703 - scary prospect. Mercurial provides the <command 12.704 - role="hg-cmd">hg incoming</command> command to tell us 12.705 - what changes the <command role="hg-cmd">hg pull</command> 12.706 - command <emphasis>would</emphasis> pull into the repository, 12.707 - without actually pulling the changes in.</para> 12.708 - 12.709 - &interaction.tour.incoming; 12.710 - 12.711 - <para>(Of course, someone could 12.712 - cause more changesets to appear in the repository that we 12.713 - ran <command role="hg-cmd">hg incoming</command> in, before 12.714 - we get a chance to <command role="hg-cmd">hg pull</command> 12.715 - the changes, so that we could end up pulling changes that we 12.716 - didn't expect.)</para> 12.717 - 12.718 - <para>Bringing changes into a repository is a simple 12.719 - matter of running the <command role="hg-cmd">hg 12.720 - pull</command> command, and telling it which repository to 12.721 - pull from.</para> 12.722 - 12.723 - &interaction.tour.pull; 12.724 - 12.725 - <para>As you can see 12.726 - from the before-and-after output of <command 12.727 - role="hg-cmd">hg tip</command>, we have successfully 12.728 - pulled changes into our repository. There remains one step 12.729 - before we can see these changes in the working 12.730 - directory.</para> 12.731 - </sect2> 12.732 - <sect2> 12.733 - <title>Updating the working directory</title> 12.734 - 12.735 - <para>We have so far glossed over the relationship between a 12.736 - repository and its working directory. The <command 12.737 - role="hg-cmd">hg pull</command> command that we ran in 12.738 - section <xref linkend="sec.tour.pull"/> brought changes 12.739 - into the repository, but if we check, there's no sign of those 12.740 - changes in the working directory. This is because <command 12.741 - role="hg-cmd">hg pull</command> does not (by default) touch 12.742 - the working directory. Instead, we use the <command 12.743 - role="hg-cmd">hg update</command> command to do this.</para> 12.744 - 12.745 - &interaction.tour.update; 12.746 - 12.747 - <para>It might seem a bit strange that <command role="hg-cmd">hg 12.748 - pull</command> doesn't update the working directory 12.749 - automatically. There's actually a good reason for this: you 12.750 - can use <command role="hg-cmd">hg update</command> to update 12.751 - the working directory to the state it was in at <emphasis>any 12.752 - revision</emphasis> in the history of the repository. If 12.753 - you had the working directory updated to an old revision---to 12.754 - hunt down the origin of a bug, say---and ran a <command 12.755 - role="hg-cmd">hg pull</command> which automatically updated 12.756 - the working directory to a new revision, you might not be 12.757 - terribly happy.</para> 12.758 - <para>However, since pull-then-update is such a common thing to 12.759 - do, Mercurial lets you combine the two by passing the <option 12.760 - role="hg-opt-pull">-u</option> option to <command 12.761 - role="hg-cmd">hg pull</command>.</para> 12.762 - 12.763 - <para>If you look back at the output of <command 12.764 - role="hg-cmd">hg pull</command> in section <xref 12.765 - linkend="sec.tour.pull"/> when we ran it without <option 12.766 - role="hg-opt-pull">-u</option>, you can see that it printed 12.767 - a helpful reminder that we'd have to take an explicit step to 12.768 - update the working directory:</para> 12.769 - 12.770 - <!-- &interaction.xxx.fixme; --> 12.771 - 12.772 - <para>To find out what revision the working directory is at, use 12.773 - the <command role="hg-cmd">hg parents</command> 12.774 - command.</para> 12.775 - 12.776 - &interaction.tour.parents; 12.777 - 12.778 - <para>If you look back at figure <xref 12.779 - endterm="fig.tour-basic.history.caption" 12.780 - linkend="fig.tour-basic.history"/>, 12.781 - you'll see arrows connecting each changeset. The node that 12.782 - the arrow leads <emphasis>from</emphasis> in each case is a 12.783 - parent, and the node that the arrow leads 12.784 - <emphasis>to</emphasis> is its child. The working directory 12.785 - has a parent in just the same way; this is the changeset that 12.786 - the working directory currently contains.</para> 12.787 - 12.788 - <para>To update the working directory to a particular revision, 12.789 - 12.790 - give a revision number or changeset ID to the <command 12.791 - role="hg-cmd">hg update</command> command.</para> 12.792 - 12.793 - &interaction.tour.older; 12.794 - 12.795 - <para>If you omit an explicit revision, <command 12.796 - role="hg-cmd">hg update</command> will update to the tip 12.797 - revision, as shown by the second call to <command 12.798 - role="hg-cmd">hg update</command> in the example 12.799 - above.</para> 12.800 - </sect2> 12.801 - 12.802 - <sect2> 12.803 - <title>Pushing changes to another repository</title> 12.804 - 12.805 - <para>Mercurial lets us push changes to another 12.806 - repository, from the repository we're currently visiting. 12.807 - As with the example of <command role="hg-cmd">hg 12.808 - pull</command> above, we'll create a temporary repository 12.809 - to push our changes into.</para> 12.810 - 12.811 - &interaction.tour.clone-push; 12.812 - 12.813 - <para>The <command role="hg-cmd">hg outgoing</command> command 12.814 - tells us what changes would be pushed into another 12.815 - repository.</para> 12.816 - 12.817 - &interaction.tour.outgoing; 12.818 - 12.819 - <para>And the 12.820 - <command role="hg-cmd">hg push</command> command does the 12.821 - actual push.</para> 12.822 - 12.823 - &interaction.tour.push; 12.824 - 12.825 - <para>As with 12.826 - <command role="hg-cmd">hg pull</command>, the <command 12.827 - role="hg-cmd">hg push</command> command does not update 12.828 - the working directory in the repository that it's pushing 12.829 - changes into. (Unlike <command role="hg-cmd">hg 12.830 - pull</command>, <command role="hg-cmd">hg push</command> 12.831 - does not provide a <literal>-u</literal> option that updates 12.832 - the other repository's working directory.)</para> 12.833 - 12.834 - <para>What happens if we try to pull or push changes 12.835 - and the receiving repository already has those changes? 12.836 - Nothing too exciting.</para> 12.837 - 12.838 - &interaction.tour.push.nothing; 12.839 - </sect2> 12.840 - <sect2> 12.841 - <title>Sharing changes over a network</title> 12.842 - 12.843 - <para>The commands we have covered in the previous few 12.844 - sections are not limited to working with local repositories. 12.845 - Each works in exactly the same fashion over a network 12.846 - connection; simply pass in a URL instead of a local 12.847 - path.</para> 12.848 - 12.849 - &interaction.tour.outgoing.net; 12.850 - 12.851 - <para>In this example, we 12.852 - can see what changes we could push to the remote repository, 12.853 - but the repository is understandably not set up to let 12.854 - anonymous users push to it.</para> 12.855 - 12.856 - &interaction.tour.push.net; 12.857 - </sect2> 12.858 - </sect1> 12.859 -</chapter> 12.860 - 12.861 -<!-- 12.862 -local variables: 12.863 -sgml-parent-document: ("00book.xml" "book" "chapter") 12.864 -end: 12.865 --->
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/en/ch02-tour-merge.xml Fri Mar 20 16:43:35 2009 +0800 13.3 @@ -0,0 +1,401 @@ 13.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 13.5 + 13.6 +<chapter id="chap.tour-merge"> 13.7 + <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?> 13.8 + <title>A tour of Mercurial: merging work</title> 13.9 + 13.10 + <para>We've now covered cloning a repository, making changes in a 13.11 + repository, and pulling or pushing changes from one repository 13.12 + into another. Our next step is <emphasis>merging</emphasis> 13.13 + changes from separate repositories.</para> 13.14 + 13.15 + <sect1> 13.16 + <title>Merging streams of work</title> 13.17 + 13.18 + <para>Merging is a fundamental part of working with a distributed 13.19 + revision control tool.</para> 13.20 + <itemizedlist> 13.21 + <listitem><para>Alice and Bob each have a personal copy of a 13.22 + repository for a project they're collaborating on. Alice 13.23 + fixes a bug in her repository; Bob adds a new feature in 13.24 + his. They want the shared repository to contain both the 13.25 + bug fix and the new feature.</para> 13.26 + </listitem> 13.27 + <listitem><para>I frequently work on several different tasks for 13.28 + a single project at once, each safely isolated in its own 13.29 + repository. Working this way means that I often need to 13.30 + merge one piece of my own work with another.</para> 13.31 + </listitem></itemizedlist> 13.32 + 13.33 + <para>Because merging is such a common thing to need to do, 13.34 + Mercurial makes it easy. Let's walk through the process. We'll 13.35 + begin by cloning yet another repository (see how often they 13.36 + spring up?) and making a change in it.</para> 13.37 + 13.38 + &interaction.tour.merge.clone; 13.39 + 13.40 + <para>We should now have two copies of 13.41 + <filename>hello.c</filename> with different contents. The 13.42 + histories of the two repositories have also diverged, as 13.43 + illustrated in figure <xref endterm="fig.tour-merge.sep-repos.caption" 13.44 + linkend="fig.tour-merge.sep-repos"/>.</para> 13.45 + 13.46 + &interaction.tour.merge.cat; 13.47 + 13.48 + <informalfigure id="fig.tour-merge.sep-repos"> 13.49 + <mediaobject> 13.50 + <imageobject><imagedata fileref="images/tour-merge-sep-repos.png"/></imageobject> 13.51 + <textobject><phrase>XXX add text</phrase></textobject> 13.52 + <caption><para id="fig.tour-merge.sep-repos.caption">Divergent recent 13.53 + histories of the <filename 13.54 + class="directory">my-hello</filename> and <filename 13.55 + class="directory">my-new-hello</filename> 13.56 + repositories</para></caption> 13.57 + </mediaobject> 13.58 + </informalfigure> 13.59 + 13.60 + <para>We already know that pulling changes from our <filename 13.61 + class="directory">my-hello</filename> repository will have no 13.62 + effect on the working directory.</para> 13.63 + 13.64 + &interaction.tour.merge.pull; 13.65 + 13.66 + <para>However, the <command role="hg-cmd">hg pull</command> 13.67 + command says something about <quote>heads</quote>.</para> 13.68 + 13.69 + <sect2> 13.70 + <title>Head changesets</title> 13.71 + 13.72 + <para>A head is a change that has no descendants, or children, 13.73 + as they're also known. The tip revision is thus a head, 13.74 + because the newest revision in a repository doesn't have any 13.75 + children, but a repository can contain more than one 13.76 + head.</para> 13.77 + 13.78 + <informalfigure id="fig.tour-merge.pull"> 13.79 + <mediaobject> 13.80 + <imageobject><imagedata fileref="images/tour-merge-pull.png"/></imageobject> 13.81 + <textobject><phrase>XXX add text</phrase></textobject> 13.82 + <caption><para id="fig.tour-merge.pull.caption">Repository contents after 13.83 + pulling from <filename class="directory">my-hello</filename> into 13.84 + <filename class="directory">my-new-hello</filename></para></caption> 13.85 + </mediaobject> 13.86 + </informalfigure> 13.87 + 13.88 + <para>In figure <xref endterm="fig.tour-merge.pull.caption" 13.89 + linkend="fig.tour-merge.pull"/>, you can 13.90 + see the effect of the pull from <filename 13.91 + class="directory">my-hello</filename> into <filename 13.92 + class="directory">my-new-hello</filename>. The history that 13.93 + was already present in <filename 13.94 + class="directory">my-new-hello</filename> is untouched, but 13.95 + a new revision has been added. By referring to figure <xref 13.96 + endterm="fig.tour-merge.sep-repos.caption" 13.97 + linkend="fig.tour-merge.sep-repos"/>, we can see that the 13.98 + <emphasis>changeset ID</emphasis> remains the same in the new 13.99 + repository, but the <emphasis>revision number</emphasis> has 13.100 + changed. (This, incidentally, is a fine example of why it's 13.101 + not safe to use revision numbers when discussing changesets.) 13.102 + We can view the heads in a repository using the <command 13.103 + role="hg-cmd">hg heads</command> command.</para> 13.104 + 13.105 + &interaction.tour.merge.heads; 13.106 + 13.107 + </sect2> 13.108 + <sect2> 13.109 + <title>Performing the merge</title> 13.110 + 13.111 + <para>What happens if we try to use the normal <command 13.112 + role="hg-cmd">hg update</command> command to update to the 13.113 + new tip?</para> 13.114 + 13.115 + &interaction.tour.merge.update; 13.116 + 13.117 + <para>Mercurial is telling us that the <command role="hg-cmd">hg 13.118 + update</command> command won't do a merge; it won't update 13.119 + the working directory when it thinks we might be wanting to do 13.120 + a merge, unless we force it to do so. Instead, we use the 13.121 + <command role="hg-cmd">hg merge</command> command to merge the 13.122 + two heads.</para> 13.123 + 13.124 + &interaction.tour.merge.merge; 13.125 + 13.126 + <informalfigure id="fig.tour-merge.merge"> 13.127 + <mediaobject> 13.128 + <imageobject><imagedata fileref="images/tour-merge-merge.png"/></imageobject> 13.129 + <textobject><phrase>XXX add text</phrase></textobject> 13.130 + <caption><para id="fig.tour-merge.merge.caption">Working directory and 13.131 + repository during merge, and following commit</para></caption> 13.132 + </mediaobject> 13.133 + </informalfigure> 13.134 + 13.135 + <para>This updates the working directory so that it contains 13.136 + changes from <emphasis>both</emphasis> heads, which is 13.137 + reflected in both the output of <command role="hg-cmd">hg 13.138 + parents</command> and the contents of 13.139 + <filename>hello.c</filename>.</para> 13.140 + 13.141 + &interaction.tour.merge.parents; 13.142 + 13.143 + </sect2> 13.144 + <sect2> 13.145 + <title>Committing the results of the merge</title> 13.146 + 13.147 + <para>Whenever we've done a merge, <command role="hg-cmd">hg 13.148 + parents</command> will display two parents until we <command 13.149 + role="hg-cmd">hg commit</command> the results of the 13.150 + merge.</para> 13.151 + 13.152 + &interaction.tour.merge.commit; 13.153 + 13.154 + <para>We now have a new tip revision; notice that it has 13.155 + <emphasis>both</emphasis> of our former heads as its parents. 13.156 + These are the same revisions that were previously displayed by 13.157 + <command role="hg-cmd">hg parents</command>.</para> 13.158 + 13.159 + &interaction.tour.merge.tip; 13.160 + 13.161 + <para>In figure <xref endterm="fig.tour-merge.merge.caption" 13.162 + linkend="fig.tour-merge.merge"/>, you can see a 13.163 + representation of what happens to the working directory during 13.164 + the merge, and how this affects the repository when the commit 13.165 + happens. During the merge, the working directory has two 13.166 + parent changesets, and these become the parents of the new 13.167 + changeset.</para> 13.168 + 13.169 + </sect2> 13.170 + </sect1> 13.171 + <sect1> 13.172 + <title>Merging conflicting changes</title> 13.173 + 13.174 + <para>Most merges are simple affairs, but sometimes you'll find 13.175 + yourself merging changes where each modifies the same portions 13.176 + of the same files. Unless both modifications are identical, 13.177 + this results in a <emphasis>conflict</emphasis>, where you have 13.178 + to decide how to reconcile the different changes into something 13.179 + coherent.</para> 13.180 + 13.181 + <informalfigure id="fig.tour-merge.conflict"> 13.182 + <mediaobject> 13.183 + <imageobject><imagedata fileref="images/tour-merge-conflict.png"/> 13.184 + </imageobject> 13.185 + <textobject><phrase>XXX add text</phrase></textobject> 13.186 + <caption><para id="fig.tour-merge.conflict.caption">Conflicting 13.187 + changes to a document</para></caption> 13.188 + </mediaobject> 13.189 + </informalfigure> 13.190 + 13.191 + <para>Figure <xref endterm="fig.tour-merge.conflict.caption" 13.192 + linkend="fig.tour-merge.conflict"/> illustrates 13.193 + an instance of two conflicting changes to a document. We 13.194 + started with a single version of the file; then we made some 13.195 + changes; while someone else made different changes to the same 13.196 + text. Our task in resolving the conflicting changes is to 13.197 + decide what the file should look like.</para> 13.198 + 13.199 + <para>Mercurial doesn't have a built-in facility for handling 13.200 + conflicts. Instead, it runs an external program called 13.201 + <command>hgmerge</command>. This is a shell script that is 13.202 + bundled with Mercurial; you can change it to behave however you 13.203 + please. What it does by default is try to find one of several 13.204 + different merging tools that are likely to be installed on your 13.205 + system. It first tries a few fully automatic merging tools; if 13.206 + these don't succeed (because the resolution process requires 13.207 + human guidance) or aren't present, the script tries a few 13.208 + different graphical merging tools.</para> 13.209 + 13.210 + <para>It's also possible to get Mercurial to run another program 13.211 + or script instead of <command>hgmerge</command>, by setting the 13.212 + <envar>HGMERGE</envar> environment variable to the name of your 13.213 + preferred program.</para> 13.214 + 13.215 + <sect2> 13.216 + <title>Using a graphical merge tool</title> 13.217 + 13.218 + <para>My preferred graphical merge tool is 13.219 + <command>kdiff3</command>, which I'll use to describe the 13.220 + features that are common to graphical file merging tools. You 13.221 + can see a screenshot of <command>kdiff3</command> in action in 13.222 + figure <xref endterm="fig.tour-merge.kdiff3.caption" 13.223 + linkend="fig.tour-merge.kdiff3"/>. The kind of 13.224 + merge it is performing is called a <emphasis>three-way 13.225 + merge</emphasis>, because there are three different versions 13.226 + of the file of interest to us. The tool thus splits the upper 13.227 + portion of the window into three panes:</para> 13.228 + <itemizedlist> 13.229 + <listitem><para>At the left is the <emphasis>base</emphasis> 13.230 + version of the file, i.e. the most recent version from 13.231 + which the two versions we're trying to merge are 13.232 + descended.</para> 13.233 + </listitem> 13.234 + <listitem><para>In the middle is <quote>our</quote> version of 13.235 + the file, with the contents that we modified.</para> 13.236 + </listitem> 13.237 + <listitem><para>On the right is <quote>their</quote> version 13.238 + of the file, the one that from the changeset that we're 13.239 + trying to merge with.</para> 13.240 + </listitem></itemizedlist> 13.241 + <para>In the pane below these is the current 13.242 + <emphasis>result</emphasis> of the merge. Our task is to 13.243 + replace all of the red text, which indicates unresolved 13.244 + conflicts, with some sensible merger of the 13.245 + <quote>ours</quote> and <quote>theirs</quote> versions of the 13.246 + file.</para> 13.247 + 13.248 + <para>All four of these panes are <emphasis>locked 13.249 + together</emphasis>; if we scroll vertically or horizontally 13.250 + in any of them, the others are updated to display the 13.251 + corresponding sections of their respective files.</para> 13.252 + 13.253 + <informalfigure id="fig.tour-merge.kdiff3"> 13.254 + <mediaobject> 13.255 + <imageobject><imagedata width="100%" fileref="images/kdiff3.png"/> 13.256 + </imageobject> 13.257 + <textobject><phrase>XXX add text</phrase></textobject> 13.258 + <caption><para id="fig.tour-merge.kdiff3.caption">Using 13.259 + <command>kdiff3</command> to merge versions of a file</para> 13.260 + </caption> 13.261 + </mediaobject> 13.262 + </informalfigure> 13.263 + 13.264 + <para>For each conflicting portion of the file, we can choose to 13.265 + resolve the conflict using some combination of text from the 13.266 + base version, ours, or theirs. We can also manually edit the 13.267 + merged file at any time, in case we need to make further 13.268 + modifications.</para> 13.269 + 13.270 + <para>There are <emphasis>many</emphasis> file merging tools 13.271 + available, too many to cover here. They vary in which 13.272 + platforms they are available for, and in their particular 13.273 + strengths and weaknesses. Most are tuned for merging files 13.274 + containing plain text, while a few are aimed at specialised 13.275 + file formats (generally XML).</para> 13.276 + 13.277 + </sect2> 13.278 + <sect2> 13.279 + <title>A worked example</title> 13.280 + 13.281 + <para>In this example, we will reproduce the file modification 13.282 + history of figure <xref endterm="fig.tour-merge.conflict.caption" 13.283 + linkend="fig.tour-merge.conflict"/> 13.284 + above. Let's begin by creating a repository with a base 13.285 + version of our document.</para> 13.286 + 13.287 + &interaction.tour-merge-conflict.wife; 13.288 + 13.289 + <para>We'll clone the repository and make a change to the 13.290 + file.</para> 13.291 + 13.292 + &interaction.tour-merge-conflict.cousin; 13.293 + 13.294 + <para>And another clone, to simulate someone else making a 13.295 + change to the file. (This hints at the idea that it's not all 13.296 + that unusual to merge with yourself when you isolate tasks in 13.297 + separate repositories, and indeed to find and resolve 13.298 + conflicts while doing so.)</para> 13.299 + 13.300 + &interaction.tour-merge-conflict.son; 13.301 + 13.302 + <para>Having created two 13.303 + different versions of the file, we'll set up an environment 13.304 + suitable for running our merge.</para> 13.305 + 13.306 + &interaction.tour-merge-conflict.pull; 13.307 + 13.308 + <para>In this example, I won't use Mercurial's normal 13.309 + <command>hgmerge</command> program to do the merge, because it 13.310 + would drop my nice automated example-running tool into a 13.311 + graphical user interface. Instead, I'll set 13.312 + <envar>HGMERGE</envar> to tell Mercurial to use the 13.313 + non-interactive <command>merge</command> command. This is 13.314 + bundled with many Unix-like systems. If you're following this 13.315 + example on your computer, don't bother setting 13.316 + <envar>HGMERGE</envar>.</para> 13.317 + 13.318 + <para><emphasis role="bold">XXX FIX THIS 13.319 + EXAMPLE.</emphasis></para> 13.320 + 13.321 + &interaction.tour-merge-conflict.merge; 13.322 + 13.323 + <para>Because <command>merge</command> can't resolve the 13.324 + conflicting changes, it leaves <emphasis>merge 13.325 + markers</emphasis> inside the file that has conflicts, 13.326 + indicating which lines have conflicts, and whether they came 13.327 + from our version of the file or theirs.</para> 13.328 + 13.329 + <para>Mercurial can tell from the way <command>merge</command> 13.330 + exits that it wasn't able to merge successfully, so it tells 13.331 + us what commands we'll need to run if we want to redo the 13.332 + merging operation. This could be useful if, for example, we 13.333 + were running a graphical merge tool and quit because we were 13.334 + confused or realised we had made a mistake.</para> 13.335 + 13.336 + <para>If automatic or manual merges fail, there's nothing to 13.337 + prevent us from <quote>fixing up</quote> the affected files 13.338 + ourselves, and committing the results of our merge:</para> 13.339 + 13.340 + &interaction.tour-merge-conflict.commit; 13.341 + 13.342 + </sect2> 13.343 + </sect1> 13.344 + <sect1 id="sec.tour-merge.fetch"> 13.345 + <title>Simplifying the pull-merge-commit sequence</title> 13.346 + 13.347 + <para>The process of merging changes as outlined above is 13.348 + straightforward, but requires running three commands in 13.349 + sequence.</para> 13.350 + <programlisting>hg pull 13.351 +hg merge 13.352 +hg commit -m 'Merged remote changes'</programlisting> 13.353 + <para>In the case of the final commit, you also need to enter a 13.354 + commit message, which is almost always going to be a piece of 13.355 + uninteresting <quote>boilerplate</quote> text.</para> 13.356 + 13.357 + <para>It would be nice to reduce the number of steps needed, if 13.358 + this were possible. Indeed, Mercurial is distributed with an 13.359 + extension called <literal role="hg-ext">fetch</literal> that 13.360 + does just this.</para> 13.361 + 13.362 + <para>Mercurial provides a flexible extension mechanism that lets 13.363 + people extend its functionality, while keeping the core of 13.364 + Mercurial small and easy to deal with. Some extensions add new 13.365 + commands that you can use from the command line, while others 13.366 + work <quote>behind the scenes,</quote> for example adding 13.367 + capabilities to the server.</para> 13.368 + 13.369 + <para>The <literal role="hg-ext">fetch</literal> extension adds a 13.370 + new command called, not surprisingly, <command role="hg-cmd">hg 13.371 + fetch</command>. This extension acts as a combination of 13.372 + <command role="hg-cmd">hg pull</command>, <command 13.373 + role="hg-cmd">hg update</command> and <command 13.374 + role="hg-cmd">hg merge</command>. It begins by pulling 13.375 + changes from another repository into the current repository. If 13.376 + it finds that the changes added a new head to the repository, it 13.377 + begins a merge, then commits the result of the merge with an 13.378 + automatically-generated commit message. If no new heads were 13.379 + added, it updates the working directory to the new tip 13.380 + changeset.</para> 13.381 + 13.382 + <para>Enabling the <literal role="hg-ext">fetch</literal> 13.383 + extension is easy. Edit your <filename 13.384 + role="special">.hgrc</filename>, and either go to the <literal 13.385 + role="rc-extensions">extensions</literal> section or create an 13.386 + <literal role="rc-extensions">extensions</literal> section. Then 13.387 + add a line that simply reads <quote><literal>fetch 13.388 + </literal></quote>.</para> 13.389 + <programlisting>[extensions] 13.390 +fetch =</programlisting> 13.391 + <para>(Normally, on the right-hand side of the 13.392 + <quote><literal>=</literal></quote> would appear the location of 13.393 + the extension, but since the <literal 13.394 + role="hg-ext">fetch</literal> extension is in the standard 13.395 + distribution, Mercurial knows where to search for it.)</para> 13.396 + 13.397 + </sect1> 13.398 +</chapter> 13.399 + 13.400 +<!-- 13.401 +local variables: 13.402 +sgml-parent-document: ("00book.xml" "book" "chapter") 13.403 +end: 13.404 +-->
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/en/ch03-concepts.xml Fri Mar 20 16:43:35 2009 +0800 14.3 @@ -0,0 +1,751 @@ 14.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 14.5 + 14.6 +<chapter id="chap.concepts"> 14.7 + <?dbhtml filename="behind-the-scenes.html"?> 14.8 + <title>Behind the scenes</title> 14.9 + 14.10 + <para>Unlike many revision control systems, the concepts upon which 14.11 + Mercurial is built are simple enough that it's easy to understand 14.12 + how the software really works. Knowing this certainly isn't 14.13 + necessary, but I find it useful to have a <quote>mental 14.14 + model</quote> of what's going on.</para> 14.15 + 14.16 + <para>This understanding gives me confidence that Mercurial has been 14.17 + carefully designed to be both <emphasis>safe</emphasis> and 14.18 + <emphasis>efficient</emphasis>. And just as importantly, if it's 14.19 + easy for me to retain a good idea of what the software is doing 14.20 + when I perform a revision control task, I'm less likely to be 14.21 + surprised by its behaviour.</para> 14.22 + 14.23 + <para>In this chapter, we'll initially cover the core concepts 14.24 + behind Mercurial's design, then continue to discuss some of the 14.25 + interesting details of its implementation.</para> 14.26 + 14.27 + <sect1> 14.28 + <title>Mercurial's historical record</title> 14.29 + 14.30 + <sect2> 14.31 + <title>Tracking the history of a single file</title> 14.32 + 14.33 + <para>When Mercurial tracks modifications to a file, it stores 14.34 + the history of that file in a metadata object called a 14.35 + <emphasis>filelog</emphasis>. Each entry in the filelog 14.36 + contains enough information to reconstruct one revision of the 14.37 + file that is being tracked. Filelogs are stored as files in 14.38 + the <filename role="special" 14.39 + class="directory">.hg/store/data</filename> directory. A 14.40 + filelog contains two kinds of information: revision data, and 14.41 + an index to help Mercurial to find a revision 14.42 + efficiently.</para> 14.43 + 14.44 + <para>A file that is large, or has a lot of history, has its 14.45 + filelog stored in separate data 14.46 + (<quote><literal>.d</literal></quote> suffix) and index 14.47 + (<quote><literal>.i</literal></quote> suffix) files. For 14.48 + small files without much history, the revision data and index 14.49 + are combined in a single <quote><literal>.i</literal></quote> 14.50 + file. The correspondence between a file in the working 14.51 + directory and the filelog that tracks its history in the 14.52 + repository is illustrated in figure <xref 14.53 + endterm="fig.concepts.filelog.caption" 14.54 + linkend="fig.concepts.filelog"/>.</para> 14.55 + 14.56 + <informalfigure id="fig.concepts.filelog"> 14.57 + <mediaobject> 14.58 + <imageobject><imagedata fileref="images/filelog.png"/></imageobject> 14.59 + <textobject><phrase>XXX add text</phrase></textobject> 14.60 + <caption><para id="fig.concepts.filelog.caption">Relationships between 14.61 + files in working directory and filelogs in repository</para> 14.62 + </caption> 14.63 + </mediaobject> 14.64 + </informalfigure> 14.65 + 14.66 + </sect2> 14.67 + <sect2> 14.68 + <title>Managing tracked files</title> 14.69 + 14.70 + <para>Mercurial uses a structure called a 14.71 + <emphasis>manifest</emphasis> to collect together information 14.72 + about the files that it tracks. Each entry in the manifest 14.73 + contains information about the files present in a single 14.74 + changeset. An entry records which files are present in the 14.75 + changeset, the revision of each file, and a few other pieces 14.76 + of file metadata.</para> 14.77 + 14.78 + </sect2> 14.79 + <sect2> 14.80 + <title>Recording changeset information</title> 14.81 + 14.82 + <para>The <emphasis>changelog</emphasis> contains information 14.83 + about each changeset. Each revision records who committed a 14.84 + change, the changeset comment, other pieces of 14.85 + changeset-related information, and the revision of the 14.86 + manifest to use.</para> 14.87 + 14.88 + </sect2> 14.89 + <sect2> 14.90 + <title>Relationships between revisions</title> 14.91 + 14.92 + <para>Within a changelog, a manifest, or a filelog, each 14.93 + revision stores a pointer to its immediate parent (or to its 14.94 + two parents, if it's a merge revision). As I mentioned above, 14.95 + there are also relationships between revisions 14.96 + <emphasis>across</emphasis> these structures, and they are 14.97 + hierarchical in nature.</para> 14.98 + 14.99 + <para>For every changeset in a repository, there is exactly one 14.100 + revision stored in the changelog. Each revision of the 14.101 + changelog contains a pointer to a single revision of the 14.102 + manifest. A revision of the manifest stores a pointer to a 14.103 + single revision of each filelog tracked when that changeset 14.104 + was created. These relationships are illustrated in figure 14.105 + <xref endterm="fig.concepts.metadata.caption" 14.106 + linkend="fig.concepts.metadata"/>.</para> 14.107 + 14.108 + <informalfigure id="fig.concepts.metadata"> 14.109 + <mediaobject> 14.110 + <imageobject><imagedata fileref="images/metadata.png"/></imageobject> 14.111 + <textobject><phrase>XXX add text</phrase></textobject> 14.112 + <caption><para id="fig.concepts.metadata.caption">Metadata 14.113 + relationships</para></caption> 14.114 + </mediaobject> 14.115 + </informalfigure> 14.116 + 14.117 + <para>As the illustration shows, there is 14.118 + <emphasis>not</emphasis> a <quote>one to one</quote> 14.119 + relationship between revisions in the changelog, manifest, or 14.120 + filelog. If the manifest hasn't changed between two 14.121 + changesets, the changelog entries for those changesets will 14.122 + point to the same revision of the manifest. If a file that 14.123 + Mercurial tracks hasn't changed between two changesets, the 14.124 + entry for that file in the two revisions of the manifest will 14.125 + point to the same revision of its filelog.</para> 14.126 + 14.127 + </sect2> 14.128 + </sect1> 14.129 + <sect1> 14.130 + <title>Safe, efficient storage</title> 14.131 + 14.132 + <para>The underpinnings of changelogs, manifests, and filelogs are 14.133 + provided by a single structure called the 14.134 + <emphasis>revlog</emphasis>.</para> 14.135 + 14.136 + <sect2> 14.137 + <title>Efficient storage</title> 14.138 + 14.139 + <para>The revlog provides efficient storage of revisions using a 14.140 + <emphasis>delta</emphasis> mechanism. Instead of storing a 14.141 + complete copy of a file for each revision, it stores the 14.142 + changes needed to transform an older revision into the new 14.143 + revision. For many kinds of file data, these deltas are 14.144 + typically a fraction of a percent of the size of a full copy 14.145 + of a file.</para> 14.146 + 14.147 + <para>Some obsolete revision control systems can only work with 14.148 + deltas of text files. They must either store binary files as 14.149 + complete snapshots or encoded into a text representation, both 14.150 + of which are wasteful approaches. Mercurial can efficiently 14.151 + handle deltas of files with arbitrary binary contents; it 14.152 + doesn't need to treat text as special.</para> 14.153 + 14.154 + </sect2> 14.155 + <sect2 id="sec.concepts.txn"> 14.156 + <title>Safe operation</title> 14.157 + 14.158 + <para>Mercurial only ever <emphasis>appends</emphasis> data to 14.159 + the end of a revlog file. It never modifies a section of a 14.160 + file after it has written it. This is both more robust and 14.161 + efficient than schemes that need to modify or rewrite 14.162 + data.</para> 14.163 + 14.164 + <para>In addition, Mercurial treats every write as part of a 14.165 + <emphasis>transaction</emphasis> that can span a number of 14.166 + files. A transaction is <emphasis>atomic</emphasis>: either 14.167 + the entire transaction succeeds and its effects are all 14.168 + visible to readers in one go, or the whole thing is undone. 14.169 + This guarantee of atomicity means that if you're running two 14.170 + copies of Mercurial, where one is reading data and one is 14.171 + writing it, the reader will never see a partially written 14.172 + result that might confuse it.</para> 14.173 + 14.174 + <para>The fact that Mercurial only appends to files makes it 14.175 + easier to provide this transactional guarantee. The easier it 14.176 + is to do stuff like this, the more confident you should be 14.177 + that it's done correctly.</para> 14.178 + 14.179 + </sect2> 14.180 + <sect2> 14.181 + <title>Fast retrieval</title> 14.182 + 14.183 + <para>Mercurial cleverly avoids a pitfall common to all earlier 14.184 + revision control systems: the problem of <emphasis>inefficient 14.185 + retrieval</emphasis>. Most revision control systems store 14.186 + the contents of a revision as an incremental series of 14.187 + modifications against a <quote>snapshot</quote>. To 14.188 + reconstruct a specific revision, you must first read the 14.189 + snapshot, and then every one of the revisions between the 14.190 + snapshot and your target revision. The more history that a 14.191 + file accumulates, the more revisions you must read, hence the 14.192 + longer it takes to reconstruct a particular revision.</para> 14.193 + 14.194 + <informalfigure id="fig.concepts.snapshot"> 14.195 + <mediaobject> 14.196 + <imageobject><imagedata fileref="images/snapshot.png"/></imageobject> 14.197 + <textobject><phrase>XXX add text</phrase></textobject> 14.198 + <caption><para id="fig.concepts.snapshot.caption">Snapshot of 14.199 + a revlog, with incremental deltas</para></caption> 14.200 + </mediaobject> 14.201 + </informalfigure> 14.202 + 14.203 + <para>The innovation that Mercurial applies to this problem is 14.204 + simple but effective. Once the cumulative amount of delta 14.205 + information stored since the last snapshot exceeds a fixed 14.206 + threshold, it stores a new snapshot (compressed, of course), 14.207 + instead of another delta. This makes it possible to 14.208 + reconstruct <emphasis>any</emphasis> revision of a file 14.209 + quickly. This approach works so well that it has since been 14.210 + copied by several other revision control systems.</para> 14.211 + 14.212 + <para>Figure <xref endterm="fig.concepts.snapshot.caption" 14.213 + linkend="fig.concepts.snapshot"/> illustrates 14.214 + the idea. In an entry in a revlog's index file, Mercurial 14.215 + stores the range of entries from the data file that it must 14.216 + read to reconstruct a particular revision.</para> 14.217 + 14.218 + <sect3> 14.219 + <title>Aside: the influence of video compression</title> 14.220 + 14.221 + <para>If you're familiar with video compression or have ever 14.222 + watched a TV feed through a digital cable or satellite 14.223 + service, you may know that most video compression schemes 14.224 + store each frame of video as a delta against its predecessor 14.225 + frame. In addition, these schemes use <quote>lossy</quote> 14.226 + compression techniques to increase the compression ratio, so 14.227 + visual errors accumulate over the course of a number of 14.228 + inter-frame deltas.</para> 14.229 + 14.230 + <para>Because it's possible for a video stream to <quote>drop 14.231 + out</quote> occasionally due to signal glitches, and to 14.232 + limit the accumulation of artefacts introduced by the lossy 14.233 + compression process, video encoders periodically insert a 14.234 + complete frame (called a <quote>key frame</quote>) into the 14.235 + video stream; the next delta is generated against that 14.236 + frame. This means that if the video signal gets 14.237 + interrupted, it will resume once the next key frame is 14.238 + received. Also, the accumulation of encoding errors 14.239 + restarts anew with each key frame.</para> 14.240 + 14.241 + </sect3> 14.242 + </sect2> 14.243 + <sect2> 14.244 + <title>Identification and strong integrity</title> 14.245 + 14.246 + <para>Along with delta or snapshot information, a revlog entry 14.247 + contains a cryptographic hash of the data that it represents. 14.248 + This makes it difficult to forge the contents of a revision, 14.249 + and easy to detect accidental corruption.</para> 14.250 + 14.251 + <para>Hashes provide more than a mere check against corruption; 14.252 + they are used as the identifiers for revisions. The changeset 14.253 + identification hashes that you see as an end user are from 14.254 + revisions of the changelog. Although filelogs and the 14.255 + manifest also use hashes, Mercurial only uses these behind the 14.256 + scenes.</para> 14.257 + 14.258 + <para>Mercurial verifies that hashes are correct when it 14.259 + retrieves file revisions and when it pulls changes from 14.260 + another repository. If it encounters an integrity problem, it 14.261 + will complain and stop whatever it's doing.</para> 14.262 + 14.263 + <para>In addition to the effect it has on retrieval efficiency, 14.264 + Mercurial's use of periodic snapshots makes it more robust 14.265 + against partial data corruption. If a revlog becomes partly 14.266 + corrupted due to a hardware error or system bug, it's often 14.267 + possible to reconstruct some or most revisions from the 14.268 + uncorrupted sections of the revlog, both before and after the 14.269 + corrupted section. This would not be possible with a 14.270 + delta-only storage model.</para> 14.271 + 14.272 + </sect2> 14.273 + </sect1> 14.274 + <sect1> 14.275 + <title>Revision history, branching, and merging</title> 14.276 + 14.277 + <para>Every entry in a Mercurial revlog knows the identity of its 14.278 + immediate ancestor revision, usually referred to as its 14.279 + <emphasis>parent</emphasis>. In fact, a revision contains room 14.280 + for not one parent, but two. Mercurial uses a special hash, 14.281 + called the <quote>null ID</quote>, to represent the idea 14.282 + <quote>there is no parent here</quote>. This hash is simply a 14.283 + string of zeroes.</para> 14.284 + 14.285 + <para>In figure <xref endterm="fig.concepts.revlog.caption" 14.286 + linkend="fig.concepts.revlog"/>, you can see 14.287 + an example of the conceptual structure of a revlog. Filelogs, 14.288 + manifests, and changelogs all have this same structure; they 14.289 + differ only in the kind of data stored in each delta or 14.290 + snapshot.</para> 14.291 + 14.292 + <para>The first revision in a revlog (at the bottom of the image) 14.293 + has the null ID in both of its parent slots. For a 14.294 + <quote>normal</quote> revision, its first parent slot contains 14.295 + the ID of its parent revision, and its second contains the null 14.296 + ID, indicating that the revision has only one real parent. Any 14.297 + two revisions that have the same parent ID are branches. A 14.298 + revision that represents a merge between branches has two normal 14.299 + revision IDs in its parent slots.</para> 14.300 + 14.301 + <informalfigure id="fig.concepts.revlog"> 14.302 + <mediaobject> 14.303 + <imageobject><imagedata fileref="images/revlog.png"/></imageobject> 14.304 + <textobject><phrase>XXX add text</phrase></textobject> 14.305 + <caption><para id="fig.concepts.revlog.caption">Revision in revlog</para> 14.306 + </caption> 14.307 + </mediaobject> 14.308 + </informalfigure> 14.309 + 14.310 + </sect1> 14.311 + <sect1> 14.312 + <title>The working directory</title> 14.313 + 14.314 + <para>In the working directory, Mercurial stores a snapshot of the 14.315 + files from the repository as of a particular changeset.</para> 14.316 + 14.317 + <para>The working directory <quote>knows</quote> which changeset 14.318 + it contains. When you update the working directory to contain a 14.319 + particular changeset, Mercurial looks up the appropriate 14.320 + revision of the manifest to find out which files it was tracking 14.321 + at the time that changeset was committed, and which revision of 14.322 + each file was then current. It then recreates a copy of each of 14.323 + those files, with the same contents it had when the changeset 14.324 + was committed.</para> 14.325 + 14.326 + <para>The <emphasis>dirstate</emphasis> contains Mercurial's 14.327 + knowledge of the working directory. This details which 14.328 + changeset the working directory is updated to, and all of the 14.329 + files that Mercurial is tracking in the working 14.330 + directory.</para> 14.331 + 14.332 + <para>Just as a revision of a revlog has room for two parents, so 14.333 + that it can represent either a normal revision (with one parent) 14.334 + or a merge of two earlier revisions, the dirstate has slots for 14.335 + two parents. When you use the <command role="hg-cmd">hg 14.336 + update</command> command, the changeset that you update to is 14.337 + stored in the <quote>first parent</quote> slot, and the null ID 14.338 + in the second. When you <command role="hg-cmd">hg 14.339 + merge</command> with another changeset, the first parent 14.340 + remains unchanged, and the second parent is filled in with the 14.341 + changeset you're merging with. The <command role="hg-cmd">hg 14.342 + parents</command> command tells you what the parents of the 14.343 + dirstate are.</para> 14.344 + 14.345 + <sect2> 14.346 + <title>What happens when you commit</title> 14.347 + 14.348 + <para>The dirstate stores parent information for more than just 14.349 + book-keeping purposes. Mercurial uses the parents of the 14.350 + dirstate as <emphasis>the parents of a new 14.351 + changeset</emphasis> when you perform a commit.</para> 14.352 + 14.353 + <informalfigure id="fig.concepts.wdir"> 14.354 + <mediaobject> 14.355 + <imageobject><imagedata fileref="images/wdir.png"/></imageobject> 14.356 + <textobject><phrase>XXX add text</phrase></textobject> 14.357 + <caption><para id="fig.concepts.wdir.caption">The working 14.358 + directory can have two parents</para></caption> 14.359 + </mediaobject> 14.360 + </informalfigure> 14.361 + 14.362 + <para>Figure <xref endterm="fig.concepts.wdir.caption" 14.363 + linkend="fig.concepts.wdir"/> shows the 14.364 + normal state of the working directory, where it has a single 14.365 + changeset as parent. That changeset is the 14.366 + <emphasis>tip</emphasis>, the newest changeset in the 14.367 + repository that has no children.</para> 14.368 + 14.369 + <informalfigure id="fig.concepts.wdir-after-commit"> 14.370 + <mediaobject> 14.371 + <imageobject><imagedata fileref="images/wdir-after-commit.png"/> 14.372 + </imageobject> 14.373 + <textobject><phrase>XXX add text</phrase></textobject> 14.374 + <caption><para id="fig.concepts.wdir-after-commit.caption">The working 14.375 + directory gains new parents after a commit</para></caption> 14.376 + </mediaobject> 14.377 + </informalfigure> 14.378 + 14.379 + <para>It's useful to think of the working directory as 14.380 + <quote>the changeset I'm about to commit</quote>. Any files 14.381 + that you tell Mercurial that you've added, removed, renamed, 14.382 + or copied will be reflected in that changeset, as will 14.383 + modifications to any files that Mercurial is already tracking; 14.384 + the new changeset will have the parents of the working 14.385 + directory as its parents.</para> 14.386 + 14.387 + <para>After a commit, Mercurial will update the parents of the 14.388 + working directory, so that the first parent is the ID of the 14.389 + new changeset, and the second is the null ID. This is shown 14.390 + in figure <xref endterm="fig.concepts.wdir-after-commit.caption" 14.391 + linkend="fig.concepts.wdir-after-commit"/>. 14.392 + Mercurial 14.393 + doesn't touch any of the files in the working directory when 14.394 + you commit; it just modifies the dirstate to note its new 14.395 + parents.</para> 14.396 + 14.397 + </sect2> 14.398 + <sect2> 14.399 + <title>Creating a new head</title> 14.400 + 14.401 + <para>It's perfectly normal to update the working directory to a 14.402 + changeset other than the current tip. For example, you might 14.403 + want to know what your project looked like last Tuesday, or 14.404 + you could be looking through changesets to see which one 14.405 + introduced a bug. In cases like this, the natural thing to do 14.406 + is update the working directory to the changeset you're 14.407 + interested in, and then examine the files in the working 14.408 + directory directly to see their contents as they were when you 14.409 + committed that changeset. The effect of this is shown in 14.410 + figure <xref endterm="fig.concepts.wdir-pre-branch.caption" 14.411 + linkend="fig.concepts.wdir-pre-branch"/>.</para> 14.412 + 14.413 + <informalfigure id="fig.concepts.wdir-pre-branch"> 14.414 + <mediaobject> 14.415 + <imageobject><imagedata fileref="images/wdir-pre-branch.png"/> 14.416 + </imageobject> 14.417 + <textobject><phrase>XXX add text</phrase></textobject> 14.418 + <caption><para id="fig.concepts.wdir-pre-branch.caption">The working 14.419 + directory, updated to an older changeset</para></caption> 14.420 + </mediaobject> 14.421 + </informalfigure> 14.422 + 14.423 + <para>Having updated the working directory to an older 14.424 + changeset, what happens if you make some changes, and then 14.425 + commit? Mercurial behaves in the same way as I outlined 14.426 + above. The parents of the working directory become the 14.427 + parents of the new changeset. This new changeset has no 14.428 + children, so it becomes the new tip. And the repository now 14.429 + contains two changesets that have no children; we call these 14.430 + <emphasis>heads</emphasis>. You can see the structure that 14.431 + this creates in figure <xref 14.432 + endterm="fig.concepts.wdir-branch.caption" 14.433 + linkend="fig.concepts.wdir-branch"/>.</para> 14.434 + 14.435 + <informalfigure id="fig.concepts.wdir-branch"> 14.436 + <mediaobject> 14.437 + <imageobject><imagedata fileref="images/wdir-branch.png"/> 14.438 + </imageobject> 14.439 + <textobject><phrase>XXX add text</phrase></textobject> 14.440 + <caption><para id="fig.concepts.wdir-branch.caption">After a 14.441 + commit made while synced to an older changeset</para></caption> 14.442 + </mediaobject> 14.443 + </informalfigure> 14.444 + 14.445 + <note> 14.446 + <para> If you're new to Mercurial, you should keep in mind a 14.447 + common <quote>error</quote>, which is to use the <command 14.448 + role="hg-cmd">hg pull</command> command without any 14.449 + options. By default, the <command role="hg-cmd">hg 14.450 + pull</command> command <emphasis>does not</emphasis> 14.451 + update the working directory, so you'll bring new changesets 14.452 + into your repository, but the working directory will stay 14.453 + synced at the same changeset as before the pull. If you 14.454 + make some changes and commit afterwards, you'll thus create 14.455 + a new head, because your working directory isn't synced to 14.456 + whatever the current tip is.</para> 14.457 + 14.458 + <para> I put the word <quote>error</quote> in quotes because 14.459 + all that you need to do to rectify this situation is 14.460 + <command role="hg-cmd">hg merge</command>, then <command 14.461 + role="hg-cmd">hg commit</command>. In other words, this 14.462 + almost never has negative consequences; it just surprises 14.463 + people. I'll discuss other ways to avoid this behaviour, 14.464 + and why Mercurial behaves in this initially surprising way, 14.465 + later on.</para> 14.466 + </note> 14.467 + 14.468 + </sect2> 14.469 + <sect2> 14.470 + <title>Merging heads</title> 14.471 + 14.472 + <para>When you run the <command role="hg-cmd">hg merge</command> 14.473 + command, Mercurial leaves the first parent of the working 14.474 + directory unchanged, and sets the second parent to the 14.475 + changeset you're merging with, as shown in figure <xref 14.476 + endterm="fig.concepts.wdir-merge.caption" 14.477 + linkend="fig.concepts.wdir-merge"/>.</para> 14.478 + 14.479 + <informalfigure id="fig.concepts.wdir-merge"> 14.480 + <mediaobject> 14.481 + <imageobject><imagedata fileref="images/wdir-merge.png"/> 14.482 + </imageobject> 14.483 + <textobject><phrase>XXX add text</phrase></textobject> 14.484 + <caption><para id="fig.concepts.wdir-merge.caption">Merging two 14.485 + heads</para></caption> 14.486 + </mediaobject> 14.487 + </informalfigure> 14.488 + 14.489 + <para>Mercurial also has to modify the working directory, to 14.490 + merge the files managed in the two changesets. Simplified a 14.491 + little, the merging process goes like this, for every file in 14.492 + the manifests of both changesets.</para> 14.493 + <itemizedlist> 14.494 + <listitem><para>If neither changeset has modified a file, do 14.495 + nothing with that file.</para> 14.496 + </listitem> 14.497 + <listitem><para>If one changeset has modified a file, and the 14.498 + other hasn't, create the modified copy of the file in the 14.499 + working directory.</para> 14.500 + </listitem> 14.501 + <listitem><para>If one changeset has removed a file, and the 14.502 + other hasn't (or has also deleted it), delete the file 14.503 + from the working directory.</para> 14.504 + </listitem> 14.505 + <listitem><para>If one changeset has removed a file, but the 14.506 + other has modified the file, ask the user what to do: keep 14.507 + the modified file, or remove it?</para> 14.508 + </listitem> 14.509 + <listitem><para>If both changesets have modified a file, 14.510 + invoke an external merge program to choose the new 14.511 + contents for the merged file. This may require input from 14.512 + the user.</para> 14.513 + </listitem> 14.514 + <listitem><para>If one changeset has modified a file, and the 14.515 + other has renamed or copied the file, make sure that the 14.516 + changes follow the new name of the file.</para> 14.517 + </listitem></itemizedlist> 14.518 + <para>There are more details&emdash;merging has plenty of corner 14.519 + cases&emdash;but these are the most common choices that are 14.520 + involved in a merge. As you can see, most cases are 14.521 + completely automatic, and indeed most merges finish 14.522 + automatically, without requiring your input to resolve any 14.523 + conflicts.</para> 14.524 + 14.525 + <para>When you're thinking about what happens when you commit 14.526 + after a merge, once again the working directory is <quote>the 14.527 + changeset I'm about to commit</quote>. After the <command 14.528 + role="hg-cmd">hg merge</command> command completes, the 14.529 + working directory has two parents; these will become the 14.530 + parents of the new changeset.</para> 14.531 + 14.532 + <para>Mercurial lets you perform multiple merges, but you must 14.533 + commit the results of each individual merge as you go. This 14.534 + is necessary because Mercurial only tracks two parents for 14.535 + both revisions and the working directory. While it would be 14.536 + technically possible to merge multiple changesets at once, the 14.537 + prospect of user confusion and making a terrible mess of a 14.538 + merge immediately becomes overwhelming.</para> 14.539 + 14.540 + </sect2> 14.541 + </sect1> 14.542 + <sect1> 14.543 + <title>Other interesting design features</title> 14.544 + 14.545 + <para>In the sections above, I've tried to highlight some of the 14.546 + most important aspects of Mercurial's design, to illustrate that 14.547 + it pays careful attention to reliability and performance. 14.548 + However, the attention to detail doesn't stop there. There are 14.549 + a number of other aspects of Mercurial's construction that I 14.550 + personally find interesting. I'll detail a few of them here, 14.551 + separate from the <quote>big ticket</quote> items above, so that 14.552 + if you're interested, you can gain a better idea of the amount 14.553 + of thinking that goes into a well-designed system.</para> 14.554 + 14.555 + <sect2> 14.556 + <title>Clever compression</title> 14.557 + 14.558 + <para>When appropriate, Mercurial will store both snapshots and 14.559 + deltas in compressed form. It does this by always 14.560 + <emphasis>trying to</emphasis> compress a snapshot or delta, 14.561 + but only storing the compressed version if it's smaller than 14.562 + the uncompressed version.</para> 14.563 + 14.564 + <para>This means that Mercurial does <quote>the right 14.565 + thing</quote> when storing a file whose native form is 14.566 + compressed, such as a <literal>zip</literal> archive or a JPEG 14.567 + image. When these types of files are compressed a second 14.568 + time, the resulting file is usually bigger than the 14.569 + once-compressed form, and so Mercurial will store the plain 14.570 + <literal>zip</literal> or JPEG.</para> 14.571 + 14.572 + <para>Deltas between revisions of a compressed file are usually 14.573 + larger than snapshots of the file, and Mercurial again does 14.574 + <quote>the right thing</quote> in these cases. It finds that 14.575 + such a delta exceeds the threshold at which it should store a 14.576 + complete snapshot of the file, so it stores the snapshot, 14.577 + again saving space compared to a naive delta-only 14.578 + approach.</para> 14.579 + 14.580 + <sect3> 14.581 + <title>Network recompression</title> 14.582 + 14.583 + <para>When storing revisions on disk, Mercurial uses the 14.584 + <quote>deflate</quote> compression algorithm (the same one 14.585 + used by the popular <literal>zip</literal> archive format), 14.586 + which balances good speed with a respectable compression 14.587 + ratio. However, when transmitting revision data over a 14.588 + network connection, Mercurial uncompresses the compressed 14.589 + revision data.</para> 14.590 + 14.591 + <para>If the connection is over HTTP, Mercurial recompresses 14.592 + the entire stream of data using a compression algorithm that 14.593 + gives a better compression ratio (the Burrows-Wheeler 14.594 + algorithm from the widely used <literal>bzip2</literal> 14.595 + compression package). This combination of algorithm and 14.596 + compression of the entire stream (instead of a revision at a 14.597 + time) substantially reduces the number of bytes to be 14.598 + transferred, yielding better network performance over almost 14.599 + all kinds of network.</para> 14.600 + 14.601 + <para>(If the connection is over <command>ssh</command>, 14.602 + Mercurial <emphasis>doesn't</emphasis> recompress the 14.603 + stream, because <command>ssh</command> can already do this 14.604 + itself.)</para> 14.605 + 14.606 + </sect3> 14.607 + </sect2> 14.608 + <sect2> 14.609 + <title>Read/write ordering and atomicity</title> 14.610 + 14.611 + <para>Appending to files isn't the whole story when it comes to 14.612 + guaranteeing that a reader won't see a partial write. If you 14.613 + recall figure <xref endterm="fig.concepts.metadata.caption" 14.614 + linkend="fig.concepts.metadata"/>, revisions in the 14.615 + changelog point to revisions in the manifest, and revisions in 14.616 + the manifest point to revisions in filelogs. This hierarchy 14.617 + is deliberate.</para> 14.618 + 14.619 + <para>A writer starts a transaction by writing filelog and 14.620 + manifest data, and doesn't write any changelog data until 14.621 + those are finished. A reader starts by reading changelog 14.622 + data, then manifest data, followed by filelog data.</para> 14.623 + 14.624 + <para>Since the writer has always finished writing filelog and 14.625 + manifest data before it writes to the changelog, a reader will 14.626 + never read a pointer to a partially written manifest revision 14.627 + from the changelog, and it will never read a pointer to a 14.628 + partially written filelog revision from the manifest.</para> 14.629 + 14.630 + </sect2> 14.631 + <sect2> 14.632 + <title>Concurrent access</title> 14.633 + 14.634 + <para>The read/write ordering and atomicity guarantees mean that 14.635 + Mercurial never needs to <emphasis>lock</emphasis> a 14.636 + repository when it's reading data, even if the repository is 14.637 + being written to while the read is occurring. This has a big 14.638 + effect on scalability; you can have an arbitrary number of 14.639 + Mercurial processes safely reading data from a repository 14.640 + safely all at once, no matter whether it's being written to or 14.641 + not.</para> 14.642 + 14.643 + <para>The lockless nature of reading means that if you're 14.644 + sharing a repository on a multi-user system, you don't need to 14.645 + grant other local users permission to 14.646 + <emphasis>write</emphasis> to your repository in order for 14.647 + them to be able to clone it or pull changes from it; they only 14.648 + need <emphasis>read</emphasis> permission. (This is 14.649 + <emphasis>not</emphasis> a common feature among revision 14.650 + control systems, so don't take it for granted! Most require 14.651 + readers to be able to lock a repository to access it safely, 14.652 + and this requires write permission on at least one directory, 14.653 + which of course makes for all kinds of nasty and annoying 14.654 + security and administrative problems.)</para> 14.655 + 14.656 + <para>Mercurial uses locks to ensure that only one process can 14.657 + write to a repository at a time (the locking mechanism is safe 14.658 + even over filesystems that are notoriously hostile to locking, 14.659 + such as NFS). If a repository is locked, a writer will wait 14.660 + for a while to retry if the repository becomes unlocked, but 14.661 + if the repository remains locked for too long, the process 14.662 + attempting to write will time out after a while. This means 14.663 + that your daily automated scripts won't get stuck forever and 14.664 + pile up if a system crashes unnoticed, for example. (Yes, the 14.665 + timeout is configurable, from zero to infinity.)</para> 14.666 + 14.667 + <sect3> 14.668 + <title>Safe dirstate access</title> 14.669 + 14.670 + <para>As with revision data, Mercurial doesn't take a lock to 14.671 + read the dirstate file; it does acquire a lock to write it. 14.672 + To avoid the possibility of reading a partially written copy 14.673 + of the dirstate file, Mercurial writes to a file with a 14.674 + unique name in the same directory as the dirstate file, then 14.675 + renames the temporary file atomically to 14.676 + <filename>dirstate</filename>. The file named 14.677 + <filename>dirstate</filename> is thus guaranteed to be 14.678 + complete, not partially written.</para> 14.679 + 14.680 + </sect3> 14.681 + </sect2> 14.682 + <sect2> 14.683 + <title>Avoiding seeks</title> 14.684 + 14.685 + <para>Critical to Mercurial's performance is the avoidance of 14.686 + seeks of the disk head, since any seek is far more expensive 14.687 + than even a comparatively large read operation.</para> 14.688 + 14.689 + <para>This is why, for example, the dirstate is stored in a 14.690 + single file. If there were a dirstate file per directory that 14.691 + Mercurial tracked, the disk would seek once per directory. 14.692 + Instead, Mercurial reads the entire single dirstate file in 14.693 + one step.</para> 14.694 + 14.695 + <para>Mercurial also uses a <quote>copy on write</quote> scheme 14.696 + when cloning a repository on local storage. Instead of 14.697 + copying every revlog file from the old repository into the new 14.698 + repository, it makes a <quote>hard link</quote>, which is a 14.699 + shorthand way to say <quote>these two names point to the same 14.700 + file</quote>. When Mercurial is about to write to one of a 14.701 + revlog's files, it checks to see if the number of names 14.702 + pointing at the file is greater than one. If it is, more than 14.703 + one repository is using the file, so Mercurial makes a new 14.704 + copy of the file that is private to this repository.</para> 14.705 + 14.706 + <para>A few revision control developers have pointed out that 14.707 + this idea of making a complete private copy of a file is not 14.708 + very efficient in its use of storage. While this is true, 14.709 + storage is cheap, and this method gives the highest 14.710 + performance while deferring most book-keeping to the operating 14.711 + system. An alternative scheme would most likely reduce 14.712 + performance and increase the complexity of the software, each 14.713 + of which is much more important to the <quote>feel</quote> of 14.714 + day-to-day use.</para> 14.715 + 14.716 + </sect2> 14.717 + <sect2> 14.718 + <title>Other contents of the dirstate</title> 14.719 + 14.720 + <para>Because Mercurial doesn't force you to tell it when you're 14.721 + modifying a file, it uses the dirstate to store some extra 14.722 + information so it can determine efficiently whether you have 14.723 + modified a file. For each file in the working directory, it 14.724 + stores the time that it last modified the file itself, and the 14.725 + size of the file at that time.</para> 14.726 + 14.727 + <para>When you explicitly <command role="hg-cmd">hg 14.728 + add</command>, <command role="hg-cmd">hg remove</command>, 14.729 + <command role="hg-cmd">hg rename</command> or <command 14.730 + role="hg-cmd">hg copy</command> files, Mercurial updates the 14.731 + dirstate so that it knows what to do with those files when you 14.732 + commit.</para> 14.733 + 14.734 + <para>When Mercurial is checking the states of files in the 14.735 + working directory, it first checks a file's modification time. 14.736 + If that has not changed, the file must not have been modified. 14.737 + If the file's size has changed, the file must have been 14.738 + modified. If the modification time has changed, but the size 14.739 + has not, only then does Mercurial need to read the actual 14.740 + contents of the file to see if they've changed. Storing these 14.741 + few extra pieces of information dramatically reduces the 14.742 + amount of data that Mercurial needs to read, which yields 14.743 + large performance improvements compared to other revision 14.744 + control systems.</para> 14.745 + 14.746 + </sect2> 14.747 + </sect1> 14.748 +</chapter> 14.749 + 14.750 +<!-- 14.751 +local variables: 14.752 +sgml-parent-document: ("00book.xml" "book" "chapter") 14.753 +end: 14.754 +-->
15.1 --- a/en/ch03-tour-merge.xml Fri Mar 20 15:40:06 2009 +0800 15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 15.3 @@ -1,401 +0,0 @@ 15.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 15.5 - 15.6 -<chapter id="chap.tour-merge"> 15.7 - <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?> 15.8 - <title>A tour of Mercurial: merging work</title> 15.9 - 15.10 - <para>We've now covered cloning a repository, making changes in a 15.11 - repository, and pulling or pushing changes from one repository 15.12 - into another. Our next step is <emphasis>merging</emphasis> 15.13 - changes from separate repositories.</para> 15.14 - 15.15 - <sect1> 15.16 - <title>Merging streams of work</title> 15.17 - 15.18 - <para>Merging is a fundamental part of working with a distributed 15.19 - revision control tool.</para> 15.20 - <itemizedlist> 15.21 - <listitem><para>Alice and Bob each have a personal copy of a 15.22 - repository for a project they're collaborating on. Alice 15.23 - fixes a bug in her repository; Bob adds a new feature in 15.24 - his. They want the shared repository to contain both the 15.25 - bug fix and the new feature.</para> 15.26 - </listitem> 15.27 - <listitem><para>I frequently work on several different tasks for 15.28 - a single project at once, each safely isolated in its own 15.29 - repository. Working this way means that I often need to 15.30 - merge one piece of my own work with another.</para> 15.31 - </listitem></itemizedlist> 15.32 - 15.33 - <para>Because merging is such a common thing to need to do, 15.34 - Mercurial makes it easy. Let's walk through the process. We'll 15.35 - begin by cloning yet another repository (see how often they 15.36 - spring up?) and making a change in it.</para> 15.37 - 15.38 - &interaction.tour.merge.clone; 15.39 - 15.40 - <para>We should now have two copies of 15.41 - <filename>hello.c</filename> with different contents. The 15.42 - histories of the two repositories have also diverged, as 15.43 - illustrated in figure <xref endterm="fig.tour-merge.sep-repos.caption" 15.44 - linkend="fig.tour-merge.sep-repos"/>.</para> 15.45 - 15.46 - &interaction.tour.merge.cat; 15.47 - 15.48 - <informalfigure id="fig.tour-merge.sep-repos"> 15.49 - <mediaobject> 15.50 - <imageobject><imagedata fileref="images/tour-merge-sep-repos.png"/></imageobject> 15.51 - <textobject><phrase>XXX add text</phrase></textobject> 15.52 - <caption><para id="fig.tour-merge.sep-repos.caption">Divergent recent 15.53 - histories of the <filename 15.54 - class="directory">my-hello</filename> and <filename 15.55 - class="directory">my-new-hello</filename> 15.56 - repositories</para></caption> 15.57 - </mediaobject> 15.58 - </informalfigure> 15.59 - 15.60 - <para>We already know that pulling changes from our <filename 15.61 - class="directory">my-hello</filename> repository will have no 15.62 - effect on the working directory.</para> 15.63 - 15.64 - &interaction.tour.merge.pull; 15.65 - 15.66 - <para>However, the <command role="hg-cmd">hg pull</command> 15.67 - command says something about <quote>heads</quote>.</para> 15.68 - 15.69 - <sect2> 15.70 - <title>Head changesets</title> 15.71 - 15.72 - <para>A head is a change that has no descendants, or children, 15.73 - as they're also known. The tip revision is thus a head, 15.74 - because the newest revision in a repository doesn't have any 15.75 - children, but a repository can contain more than one 15.76 - head.</para> 15.77 - 15.78 - <informalfigure id="fig.tour-merge.pull"> 15.79 - <mediaobject> 15.80 - <imageobject><imagedata fileref="images/tour-merge-pull.png"/></imageobject> 15.81 - <textobject><phrase>XXX add text</phrase></textobject> 15.82 - <caption><para id="fig.tour-merge.pull.caption">Repository contents after 15.83 - pulling from <filename class="directory">my-hello</filename> into 15.84 - <filename class="directory">my-new-hello</filename></para></caption> 15.85 - </mediaobject> 15.86 - </informalfigure> 15.87 - 15.88 - <para>In figure <xref endterm="fig.tour-merge.pull.caption" 15.89 - linkend="fig.tour-merge.pull"/>, you can 15.90 - see the effect of the pull from <filename 15.91 - class="directory">my-hello</filename> into <filename 15.92 - class="directory">my-new-hello</filename>. The history that 15.93 - was already present in <filename 15.94 - class="directory">my-new-hello</filename> is untouched, but 15.95 - a new revision has been added. By referring to figure <xref 15.96 - endterm="fig.tour-merge.sep-repos.caption" 15.97 - linkend="fig.tour-merge.sep-repos"/>, we can see that the 15.98 - <emphasis>changeset ID</emphasis> remains the same in the new 15.99 - repository, but the <emphasis>revision number</emphasis> has 15.100 - changed. (This, incidentally, is a fine example of why it's 15.101 - not safe to use revision numbers when discussing changesets.) 15.102 - We can view the heads in a repository using the <command 15.103 - role="hg-cmd">hg heads</command> command.</para> 15.104 - 15.105 - &interaction.tour.merge.heads; 15.106 - 15.107 - </sect2> 15.108 - <sect2> 15.109 - <title>Performing the merge</title> 15.110 - 15.111 - <para>What happens if we try to use the normal <command 15.112 - role="hg-cmd">hg update</command> command to update to the 15.113 - new tip?</para> 15.114 - 15.115 - &interaction.tour.merge.update; 15.116 - 15.117 - <para>Mercurial is telling us that the <command role="hg-cmd">hg 15.118 - update</command> command won't do a merge; it won't update 15.119 - the working directory when it thinks we might be wanting to do 15.120 - a merge, unless we force it to do so. Instead, we use the 15.121 - <command role="hg-cmd">hg merge</command> command to merge the 15.122 - two heads.</para> 15.123 - 15.124 - &interaction.tour.merge.merge; 15.125 - 15.126 - <informalfigure id="fig.tour-merge.merge"> 15.127 - <mediaobject> 15.128 - <imageobject><imagedata fileref="images/tour-merge-merge.png"/></imageobject> 15.129 - <textobject><phrase>XXX add text</phrase></textobject> 15.130 - <caption><para id="fig.tour-merge.merge.caption">Working directory and 15.131 - repository during merge, and following commit</para></caption> 15.132 - </mediaobject> 15.133 - </informalfigure> 15.134 - 15.135 - <para>This updates the working directory so that it contains 15.136 - changes from <emphasis>both</emphasis> heads, which is 15.137 - reflected in both the output of <command role="hg-cmd">hg 15.138 - parents</command> and the contents of 15.139 - <filename>hello.c</filename>.</para> 15.140 - 15.141 - &interaction.tour.merge.parents; 15.142 - 15.143 - </sect2> 15.144 - <sect2> 15.145 - <title>Committing the results of the merge</title> 15.146 - 15.147 - <para>Whenever we've done a merge, <command role="hg-cmd">hg 15.148 - parents</command> will display two parents until we <command 15.149 - role="hg-cmd">hg commit</command> the results of the 15.150 - merge.</para> 15.151 - 15.152 - &interaction.tour.merge.commit; 15.153 - 15.154 - <para>We now have a new tip revision; notice that it has 15.155 - <emphasis>both</emphasis> of our former heads as its parents. 15.156 - These are the same revisions that were previously displayed by 15.157 - <command role="hg-cmd">hg parents</command>.</para> 15.158 - 15.159 - &interaction.tour.merge.tip; 15.160 - 15.161 - <para>In figure <xref endterm="fig.tour-merge.merge.caption" 15.162 - linkend="fig.tour-merge.merge"/>, you can see a 15.163 - representation of what happens to the working directory during 15.164 - the merge, and how this affects the repository when the commit 15.165 - happens. During the merge, the working directory has two 15.166 - parent changesets, and these become the parents of the new 15.167 - changeset.</para> 15.168 - 15.169 - </sect2> 15.170 - </sect1> 15.171 - <sect1> 15.172 - <title>Merging conflicting changes</title> 15.173 - 15.174 - <para>Most merges are simple affairs, but sometimes you'll find 15.175 - yourself merging changes where each modifies the same portions 15.176 - of the same files. Unless both modifications are identical, 15.177 - this results in a <emphasis>conflict</emphasis>, where you have 15.178 - to decide how to reconcile the different changes into something 15.179 - coherent.</para> 15.180 - 15.181 - <informalfigure id="fig.tour-merge.conflict"> 15.182 - <mediaobject> 15.183 - <imageobject><imagedata fileref="images/tour-merge-conflict.png"/> 15.184 - </imageobject> 15.185 - <textobject><phrase>XXX add text</phrase></textobject> 15.186 - <caption><para id="fig.tour-merge.conflict.caption">Conflicting 15.187 - changes to a document</para></caption> 15.188 - </mediaobject> 15.189 - </informalfigure> 15.190 - 15.191 - <para>Figure <xref endterm="fig.tour-merge.conflict.caption" 15.192 - linkend="fig.tour-merge.conflict"/> illustrates 15.193 - an instance of two conflicting changes to a document. We 15.194 - started with a single version of the file; then we made some 15.195 - changes; while someone else made different changes to the same 15.196 - text. Our task in resolving the conflicting changes is to 15.197 - decide what the file should look like.</para> 15.198 - 15.199 - <para>Mercurial doesn't have a built-in facility for handling 15.200 - conflicts. Instead, it runs an external program called 15.201 - <command>hgmerge</command>. This is a shell script that is 15.202 - bundled with Mercurial; you can change it to behave however you 15.203 - please. What it does by default is try to find one of several 15.204 - different merging tools that are likely to be installed on your 15.205 - system. It first tries a few fully automatic merging tools; if 15.206 - these don't succeed (because the resolution process requires 15.207 - human guidance) or aren't present, the script tries a few 15.208 - different graphical merging tools.</para> 15.209 - 15.210 - <para>It's also possible to get Mercurial to run another program 15.211 - or script instead of <command>hgmerge</command>, by setting the 15.212 - <envar>HGMERGE</envar> environment variable to the name of your 15.213 - preferred program.</para> 15.214 - 15.215 - <sect2> 15.216 - <title>Using a graphical merge tool</title> 15.217 - 15.218 - <para>My preferred graphical merge tool is 15.219 - <command>kdiff3</command>, which I'll use to describe the 15.220 - features that are common to graphical file merging tools. You 15.221 - can see a screenshot of <command>kdiff3</command> in action in 15.222 - figure <xref endterm="fig.tour-merge.kdiff3.caption" 15.223 - linkend="fig.tour-merge.kdiff3"/>. The kind of 15.224 - merge it is performing is called a <emphasis>three-way 15.225 - merge</emphasis>, because there are three different versions 15.226 - of the file of interest to us. The tool thus splits the upper 15.227 - portion of the window into three panes:</para> 15.228 - <itemizedlist> 15.229 - <listitem><para>At the left is the <emphasis>base</emphasis> 15.230 - version of the file, i.e. the most recent version from 15.231 - which the two versions we're trying to merge are 15.232 - descended.</para> 15.233 - </listitem> 15.234 - <listitem><para>In the middle is <quote>our</quote> version of 15.235 - the file, with the contents that we modified.</para> 15.236 - </listitem> 15.237 - <listitem><para>On the right is <quote>their</quote> version 15.238 - of the file, the one that from the changeset that we're 15.239 - trying to merge with.</para> 15.240 - </listitem></itemizedlist> 15.241 - <para>In the pane below these is the current 15.242 - <emphasis>result</emphasis> of the merge. Our task is to 15.243 - replace all of the red text, which indicates unresolved 15.244 - conflicts, with some sensible merger of the 15.245 - <quote>ours</quote> and <quote>theirs</quote> versions of the 15.246 - file.</para> 15.247 - 15.248 - <para>All four of these panes are <emphasis>locked 15.249 - together</emphasis>; if we scroll vertically or horizontally 15.250 - in any of them, the others are updated to display the 15.251 - corresponding sections of their respective files.</para> 15.252 - 15.253 - <informalfigure id="fig.tour-merge.kdiff3"> 15.254 - <mediaobject> 15.255 - <imageobject><imagedata width="100%" fileref="images/kdiff3.png"/> 15.256 - </imageobject> 15.257 - <textobject><phrase>XXX add text</phrase></textobject> 15.258 - <caption><para id="fig.tour-merge.kdiff3.caption">Using 15.259 - <command>kdiff3</command> to merge versions of a file</para> 15.260 - </caption> 15.261 - </mediaobject> 15.262 - </informalfigure> 15.263 - 15.264 - <para>For each conflicting portion of the file, we can choose to 15.265 - resolve the conflict using some combination of text from the 15.266 - base version, ours, or theirs. We can also manually edit the 15.267 - merged file at any time, in case we need to make further 15.268 - modifications.</para> 15.269 - 15.270 - <para>There are <emphasis>many</emphasis> file merging tools 15.271 - available, too many to cover here. They vary in which 15.272 - platforms they are available for, and in their particular 15.273 - strengths and weaknesses. Most are tuned for merging files 15.274 - containing plain text, while a few are aimed at specialised 15.275 - file formats (generally XML).</para> 15.276 - 15.277 - </sect2> 15.278 - <sect2> 15.279 - <title>A worked example</title> 15.280 - 15.281 - <para>In this example, we will reproduce the file modification 15.282 - history of figure <xref endterm="fig.tour-merge.conflict.caption" 15.283 - linkend="fig.tour-merge.conflict"/> 15.284 - above. Let's begin by creating a repository with a base 15.285 - version of our document.</para> 15.286 - 15.287 - &interaction.tour-merge-conflict.wife; 15.288 - 15.289 - <para>We'll clone the repository and make a change to the 15.290 - file.</para> 15.291 - 15.292 - &interaction.tour-merge-conflict.cousin; 15.293 - 15.294 - <para>And another clone, to simulate someone else making a 15.295 - change to the file. (This hints at the idea that it's not all 15.296 - that unusual to merge with yourself when you isolate tasks in 15.297 - separate repositories, and indeed to find and resolve 15.298 - conflicts while doing so.)</para> 15.299 - 15.300 - &interaction.tour-merge-conflict.son; 15.301 - 15.302 - <para>Having created two 15.303 - different versions of the file, we'll set up an environment 15.304 - suitable for running our merge.</para> 15.305 - 15.306 - &interaction.tour-merge-conflict.pull; 15.307 - 15.308 - <para>In this example, I won't use Mercurial's normal 15.309 - <command>hgmerge</command> program to do the merge, because it 15.310 - would drop my nice automated example-running tool into a 15.311 - graphical user interface. Instead, I'll set 15.312 - <envar>HGMERGE</envar> to tell Mercurial to use the 15.313 - non-interactive <command>merge</command> command. This is 15.314 - bundled with many Unix-like systems. If you're following this 15.315 - example on your computer, don't bother setting 15.316 - <envar>HGMERGE</envar>.</para> 15.317 - 15.318 - <para><emphasis role="bold">XXX FIX THIS 15.319 - EXAMPLE.</emphasis></para> 15.320 - 15.321 - &interaction.tour-merge-conflict.merge; 15.322 - 15.323 - <para>Because <command>merge</command> can't resolve the 15.324 - conflicting changes, it leaves <emphasis>merge 15.325 - markers</emphasis> inside the file that has conflicts, 15.326 - indicating which lines have conflicts, and whether they came 15.327 - from our version of the file or theirs.</para> 15.328 - 15.329 - <para>Mercurial can tell from the way <command>merge</command> 15.330 - exits that it wasn't able to merge successfully, so it tells 15.331 - us what commands we'll need to run if we want to redo the 15.332 - merging operation. This could be useful if, for example, we 15.333 - were running a graphical merge tool and quit because we were 15.334 - confused or realised we had made a mistake.</para> 15.335 - 15.336 - <para>If automatic or manual merges fail, there's nothing to 15.337 - prevent us from <quote>fixing up</quote> the affected files 15.338 - ourselves, and committing the results of our merge:</para> 15.339 - 15.340 - &interaction.tour-merge-conflict.commit; 15.341 - 15.342 - </sect2> 15.343 - </sect1> 15.344 - <sect1 id="sec.tour-merge.fetch"> 15.345 - <title>Simplifying the pull-merge-commit sequence</title> 15.346 - 15.347 - <para>The process of merging changes as outlined above is 15.348 - straightforward, but requires running three commands in 15.349 - sequence.</para> 15.350 - <programlisting>hg pull 15.351 -hg merge 15.352 -hg commit -m 'Merged remote changes'</programlisting> 15.353 - <para>In the case of the final commit, you also need to enter a 15.354 - commit message, which is almost always going to be a piece of 15.355 - uninteresting <quote>boilerplate</quote> text.</para> 15.356 - 15.357 - <para>It would be nice to reduce the number of steps needed, if 15.358 - this were possible. Indeed, Mercurial is distributed with an 15.359 - extension called <literal role="hg-ext">fetch</literal> that 15.360 - does just this.</para> 15.361 - 15.362 - <para>Mercurial provides a flexible extension mechanism that lets 15.363 - people extend its functionality, while keeping the core of 15.364 - Mercurial small and easy to deal with. Some extensions add new 15.365 - commands that you can use from the command line, while others 15.366 - work <quote>behind the scenes,</quote> for example adding 15.367 - capabilities to the server.</para> 15.368 - 15.369 - <para>The <literal role="hg-ext">fetch</literal> extension adds a 15.370 - new command called, not surprisingly, <command role="hg-cmd">hg 15.371 - fetch</command>. This extension acts as a combination of 15.372 - <command role="hg-cmd">hg pull</command>, <command 15.373 - role="hg-cmd">hg update</command> and <command 15.374 - role="hg-cmd">hg merge</command>. It begins by pulling 15.375 - changes from another repository into the current repository. If 15.376 - it finds that the changes added a new head to the repository, it 15.377 - begins a merge, then commits the result of the merge with an 15.378 - automatically-generated commit message. If no new heads were 15.379 - added, it updates the working directory to the new tip 15.380 - changeset.</para> 15.381 - 15.382 - <para>Enabling the <literal role="hg-ext">fetch</literal> 15.383 - extension is easy. Edit your <filename 15.384 - role="special">.hgrc</filename>, and either go to the <literal 15.385 - role="rc-extensions">extensions</literal> section or create an 15.386 - <literal role="rc-extensions">extensions</literal> section. Then 15.387 - add a line that simply reads <quote><literal>fetch 15.388 - </literal></quote>.</para> 15.389 - <programlisting>[extensions] 15.390 -fetch =</programlisting> 15.391 - <para>(Normally, on the right-hand side of the 15.392 - <quote><literal>=</literal></quote> would appear the location of 15.393 - the extension, but since the <literal 15.394 - role="hg-ext">fetch</literal> extension is in the standard 15.395 - distribution, Mercurial knows where to search for it.)</para> 15.396 - 15.397 - </sect1> 15.398 -</chapter> 15.399 - 15.400 -<!-- 15.401 -local variables: 15.402 -sgml-parent-document: ("00book.xml" "book" "chapter") 15.403 -end: 15.404 --->
16.1 --- a/en/ch04-concepts.xml Fri Mar 20 15:40:06 2009 +0800 16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 16.3 @@ -1,751 +0,0 @@ 16.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 16.5 - 16.6 -<chapter id="chap.concepts"> 16.7 - <?dbhtml filename="behind-the-scenes.html"?> 16.8 - <title>Behind the scenes</title> 16.9 - 16.10 - <para>Unlike many revision control systems, the concepts upon which 16.11 - Mercurial is built are simple enough that it's easy to understand 16.12 - how the software really works. Knowing this certainly isn't 16.13 - necessary, but I find it useful to have a <quote>mental 16.14 - model</quote> of what's going on.</para> 16.15 - 16.16 - <para>This understanding gives me confidence that Mercurial has been 16.17 - carefully designed to be both <emphasis>safe</emphasis> and 16.18 - <emphasis>efficient</emphasis>. And just as importantly, if it's 16.19 - easy for me to retain a good idea of what the software is doing 16.20 - when I perform a revision control task, I'm less likely to be 16.21 - surprised by its behaviour.</para> 16.22 - 16.23 - <para>In this chapter, we'll initially cover the core concepts 16.24 - behind Mercurial's design, then continue to discuss some of the 16.25 - interesting details of its implementation.</para> 16.26 - 16.27 - <sect1> 16.28 - <title>Mercurial's historical record</title> 16.29 - 16.30 - <sect2> 16.31 - <title>Tracking the history of a single file</title> 16.32 - 16.33 - <para>When Mercurial tracks modifications to a file, it stores 16.34 - the history of that file in a metadata object called a 16.35 - <emphasis>filelog</emphasis>. Each entry in the filelog 16.36 - contains enough information to reconstruct one revision of the 16.37 - file that is being tracked. Filelogs are stored as files in 16.38 - the <filename role="special" 16.39 - class="directory">.hg/store/data</filename> directory. A 16.40 - filelog contains two kinds of information: revision data, and 16.41 - an index to help Mercurial to find a revision 16.42 - efficiently.</para> 16.43 - 16.44 - <para>A file that is large, or has a lot of history, has its 16.45 - filelog stored in separate data 16.46 - (<quote><literal>.d</literal></quote> suffix) and index 16.47 - (<quote><literal>.i</literal></quote> suffix) files. For 16.48 - small files without much history, the revision data and index 16.49 - are combined in a single <quote><literal>.i</literal></quote> 16.50 - file. The correspondence between a file in the working 16.51 - directory and the filelog that tracks its history in the 16.52 - repository is illustrated in figure <xref 16.53 - endterm="fig.concepts.filelog.caption" 16.54 - linkend="fig.concepts.filelog"/>.</para> 16.55 - 16.56 - <informalfigure id="fig.concepts.filelog"> 16.57 - <mediaobject> 16.58 - <imageobject><imagedata fileref="images/filelog.png"/></imageobject> 16.59 - <textobject><phrase>XXX add text</phrase></textobject> 16.60 - <caption><para id="fig.concepts.filelog.caption">Relationships between 16.61 - files in working directory and filelogs in repository</para> 16.62 - </caption> 16.63 - </mediaobject> 16.64 - </informalfigure> 16.65 - 16.66 - </sect2> 16.67 - <sect2> 16.68 - <title>Managing tracked files</title> 16.69 - 16.70 - <para>Mercurial uses a structure called a 16.71 - <emphasis>manifest</emphasis> to collect together information 16.72 - about the files that it tracks. Each entry in the manifest 16.73 - contains information about the files present in a single 16.74 - changeset. An entry records which files are present in the 16.75 - changeset, the revision of each file, and a few other pieces 16.76 - of file metadata.</para> 16.77 - 16.78 - </sect2> 16.79 - <sect2> 16.80 - <title>Recording changeset information</title> 16.81 - 16.82 - <para>The <emphasis>changelog</emphasis> contains information 16.83 - about each changeset. Each revision records who committed a 16.84 - change, the changeset comment, other pieces of 16.85 - changeset-related information, and the revision of the 16.86 - manifest to use.</para> 16.87 - 16.88 - </sect2> 16.89 - <sect2> 16.90 - <title>Relationships between revisions</title> 16.91 - 16.92 - <para>Within a changelog, a manifest, or a filelog, each 16.93 - revision stores a pointer to its immediate parent (or to its 16.94 - two parents, if it's a merge revision). As I mentioned above, 16.95 - there are also relationships between revisions 16.96 - <emphasis>across</emphasis> these structures, and they are 16.97 - hierarchical in nature.</para> 16.98 - 16.99 - <para>For every changeset in a repository, there is exactly one 16.100 - revision stored in the changelog. Each revision of the 16.101 - changelog contains a pointer to a single revision of the 16.102 - manifest. A revision of the manifest stores a pointer to a 16.103 - single revision of each filelog tracked when that changeset 16.104 - was created. These relationships are illustrated in figure 16.105 - <xref endterm="fig.concepts.metadata.caption" 16.106 - linkend="fig.concepts.metadata"/>.</para> 16.107 - 16.108 - <informalfigure id="fig.concepts.metadata"> 16.109 - <mediaobject> 16.110 - <imageobject><imagedata fileref="images/metadata.png"/></imageobject> 16.111 - <textobject><phrase>XXX add text</phrase></textobject> 16.112 - <caption><para id="fig.concepts.metadata.caption">Metadata 16.113 - relationships</para></caption> 16.114 - </mediaobject> 16.115 - </informalfigure> 16.116 - 16.117 - <para>As the illustration shows, there is 16.118 - <emphasis>not</emphasis> a <quote>one to one</quote> 16.119 - relationship between revisions in the changelog, manifest, or 16.120 - filelog. If the manifest hasn't changed between two 16.121 - changesets, the changelog entries for those changesets will 16.122 - point to the same revision of the manifest. If a file that 16.123 - Mercurial tracks hasn't changed between two changesets, the 16.124 - entry for that file in the two revisions of the manifest will 16.125 - point to the same revision of its filelog.</para> 16.126 - 16.127 - </sect2> 16.128 - </sect1> 16.129 - <sect1> 16.130 - <title>Safe, efficient storage</title> 16.131 - 16.132 - <para>The underpinnings of changelogs, manifests, and filelogs are 16.133 - provided by a single structure called the 16.134 - <emphasis>revlog</emphasis>.</para> 16.135 - 16.136 - <sect2> 16.137 - <title>Efficient storage</title> 16.138 - 16.139 - <para>The revlog provides efficient storage of revisions using a 16.140 - <emphasis>delta</emphasis> mechanism. Instead of storing a 16.141 - complete copy of a file for each revision, it stores the 16.142 - changes needed to transform an older revision into the new 16.143 - revision. For many kinds of file data, these deltas are 16.144 - typically a fraction of a percent of the size of a full copy 16.145 - of a file.</para> 16.146 - 16.147 - <para>Some obsolete revision control systems can only work with 16.148 - deltas of text files. They must either store binary files as 16.149 - complete snapshots or encoded into a text representation, both 16.150 - of which are wasteful approaches. Mercurial can efficiently 16.151 - handle deltas of files with arbitrary binary contents; it 16.152 - doesn't need to treat text as special.</para> 16.153 - 16.154 - </sect2> 16.155 - <sect2 id="sec.concepts.txn"> 16.156 - <title>Safe operation</title> 16.157 - 16.158 - <para>Mercurial only ever <emphasis>appends</emphasis> data to 16.159 - the end of a revlog file. It never modifies a section of a 16.160 - file after it has written it. This is both more robust and 16.161 - efficient than schemes that need to modify or rewrite 16.162 - data.</para> 16.163 - 16.164 - <para>In addition, Mercurial treats every write as part of a 16.165 - <emphasis>transaction</emphasis> that can span a number of 16.166 - files. A transaction is <emphasis>atomic</emphasis>: either 16.167 - the entire transaction succeeds and its effects are all 16.168 - visible to readers in one go, or the whole thing is undone. 16.169 - This guarantee of atomicity means that if you're running two 16.170 - copies of Mercurial, where one is reading data and one is 16.171 - writing it, the reader will never see a partially written 16.172 - result that might confuse it.</para> 16.173 - 16.174 - <para>The fact that Mercurial only appends to files makes it 16.175 - easier to provide this transactional guarantee. The easier it 16.176 - is to do stuff like this, the more confident you should be 16.177 - that it's done correctly.</para> 16.178 - 16.179 - </sect2> 16.180 - <sect2> 16.181 - <title>Fast retrieval</title> 16.182 - 16.183 - <para>Mercurial cleverly avoids a pitfall common to all earlier 16.184 - revision control systems: the problem of <emphasis>inefficient 16.185 - retrieval</emphasis>. Most revision control systems store 16.186 - the contents of a revision as an incremental series of 16.187 - modifications against a <quote>snapshot</quote>. To 16.188 - reconstruct a specific revision, you must first read the 16.189 - snapshot, and then every one of the revisions between the 16.190 - snapshot and your target revision. The more history that a 16.191 - file accumulates, the more revisions you must read, hence the 16.192 - longer it takes to reconstruct a particular revision.</para> 16.193 - 16.194 - <informalfigure id="fig.concepts.snapshot"> 16.195 - <mediaobject> 16.196 - <imageobject><imagedata fileref="images/snapshot.png"/></imageobject> 16.197 - <textobject><phrase>XXX add text</phrase></textobject> 16.198 - <caption><para id="fig.concepts.snapshot.caption">Snapshot of 16.199 - a revlog, with incremental deltas</para></caption> 16.200 - </mediaobject> 16.201 - </informalfigure> 16.202 - 16.203 - <para>The innovation that Mercurial applies to this problem is 16.204 - simple but effective. Once the cumulative amount of delta 16.205 - information stored since the last snapshot exceeds a fixed 16.206 - threshold, it stores a new snapshot (compressed, of course), 16.207 - instead of another delta. This makes it possible to 16.208 - reconstruct <emphasis>any</emphasis> revision of a file 16.209 - quickly. This approach works so well that it has since been 16.210 - copied by several other revision control systems.</para> 16.211 - 16.212 - <para>Figure <xref endterm="fig.concepts.snapshot.caption" 16.213 - linkend="fig.concepts.snapshot"/> illustrates 16.214 - the idea. In an entry in a revlog's index file, Mercurial 16.215 - stores the range of entries from the data file that it must 16.216 - read to reconstruct a particular revision.</para> 16.217 - 16.218 - <sect3> 16.219 - <title>Aside: the influence of video compression</title> 16.220 - 16.221 - <para>If you're familiar with video compression or have ever 16.222 - watched a TV feed through a digital cable or satellite 16.223 - service, you may know that most video compression schemes 16.224 - store each frame of video as a delta against its predecessor 16.225 - frame. In addition, these schemes use <quote>lossy</quote> 16.226 - compression techniques to increase the compression ratio, so 16.227 - visual errors accumulate over the course of a number of 16.228 - inter-frame deltas.</para> 16.229 - 16.230 - <para>Because it's possible for a video stream to <quote>drop 16.231 - out</quote> occasionally due to signal glitches, and to 16.232 - limit the accumulation of artefacts introduced by the lossy 16.233 - compression process, video encoders periodically insert a 16.234 - complete frame (called a <quote>key frame</quote>) into the 16.235 - video stream; the next delta is generated against that 16.236 - frame. This means that if the video signal gets 16.237 - interrupted, it will resume once the next key frame is 16.238 - received. Also, the accumulation of encoding errors 16.239 - restarts anew with each key frame.</para> 16.240 - 16.241 - </sect3> 16.242 - </sect2> 16.243 - <sect2> 16.244 - <title>Identification and strong integrity</title> 16.245 - 16.246 - <para>Along with delta or snapshot information, a revlog entry 16.247 - contains a cryptographic hash of the data that it represents. 16.248 - This makes it difficult to forge the contents of a revision, 16.249 - and easy to detect accidental corruption.</para> 16.250 - 16.251 - <para>Hashes provide more than a mere check against corruption; 16.252 - they are used as the identifiers for revisions. The changeset 16.253 - identification hashes that you see as an end user are from 16.254 - revisions of the changelog. Although filelogs and the 16.255 - manifest also use hashes, Mercurial only uses these behind the 16.256 - scenes.</para> 16.257 - 16.258 - <para>Mercurial verifies that hashes are correct when it 16.259 - retrieves file revisions and when it pulls changes from 16.260 - another repository. If it encounters an integrity problem, it 16.261 - will complain and stop whatever it's doing.</para> 16.262 - 16.263 - <para>In addition to the effect it has on retrieval efficiency, 16.264 - Mercurial's use of periodic snapshots makes it more robust 16.265 - against partial data corruption. If a revlog becomes partly 16.266 - corrupted due to a hardware error or system bug, it's often 16.267 - possible to reconstruct some or most revisions from the 16.268 - uncorrupted sections of the revlog, both before and after the 16.269 - corrupted section. This would not be possible with a 16.270 - delta-only storage model.</para> 16.271 - 16.272 - </sect2> 16.273 - </sect1> 16.274 - <sect1> 16.275 - <title>Revision history, branching, and merging</title> 16.276 - 16.277 - <para>Every entry in a Mercurial revlog knows the identity of its 16.278 - immediate ancestor revision, usually referred to as its 16.279 - <emphasis>parent</emphasis>. In fact, a revision contains room 16.280 - for not one parent, but two. Mercurial uses a special hash, 16.281 - called the <quote>null ID</quote>, to represent the idea 16.282 - <quote>there is no parent here</quote>. This hash is simply a 16.283 - string of zeroes.</para> 16.284 - 16.285 - <para>In figure <xref endterm="fig.concepts.revlog.caption" 16.286 - linkend="fig.concepts.revlog"/>, you can see 16.287 - an example of the conceptual structure of a revlog. Filelogs, 16.288 - manifests, and changelogs all have this same structure; they 16.289 - differ only in the kind of data stored in each delta or 16.290 - snapshot.</para> 16.291 - 16.292 - <para>The first revision in a revlog (at the bottom of the image) 16.293 - has the null ID in both of its parent slots. For a 16.294 - <quote>normal</quote> revision, its first parent slot contains 16.295 - the ID of its parent revision, and its second contains the null 16.296 - ID, indicating that the revision has only one real parent. Any 16.297 - two revisions that have the same parent ID are branches. A 16.298 - revision that represents a merge between branches has two normal 16.299 - revision IDs in its parent slots.</para> 16.300 - 16.301 - <informalfigure id="fig.concepts.revlog"> 16.302 - <mediaobject> 16.303 - <imageobject><imagedata fileref="images/revlog.png"/></imageobject> 16.304 - <textobject><phrase>XXX add text</phrase></textobject> 16.305 - <caption><para id="fig.concepts.revlog.caption">Revision in revlog</para> 16.306 - </caption> 16.307 - </mediaobject> 16.308 - </informalfigure> 16.309 - 16.310 - </sect1> 16.311 - <sect1> 16.312 - <title>The working directory</title> 16.313 - 16.314 - <para>In the working directory, Mercurial stores a snapshot of the 16.315 - files from the repository as of a particular changeset.</para> 16.316 - 16.317 - <para>The working directory <quote>knows</quote> which changeset 16.318 - it contains. When you update the working directory to contain a 16.319 - particular changeset, Mercurial looks up the appropriate 16.320 - revision of the manifest to find out which files it was tracking 16.321 - at the time that changeset was committed, and which revision of 16.322 - each file was then current. It then recreates a copy of each of 16.323 - those files, with the same contents it had when the changeset 16.324 - was committed.</para> 16.325 - 16.326 - <para>The <emphasis>dirstate</emphasis> contains Mercurial's 16.327 - knowledge of the working directory. This details which 16.328 - changeset the working directory is updated to, and all of the 16.329 - files that Mercurial is tracking in the working 16.330 - directory.</para> 16.331 - 16.332 - <para>Just as a revision of a revlog has room for two parents, so 16.333 - that it can represent either a normal revision (with one parent) 16.334 - or a merge of two earlier revisions, the dirstate has slots for 16.335 - two parents. When you use the <command role="hg-cmd">hg 16.336 - update</command> command, the changeset that you update to is 16.337 - stored in the <quote>first parent</quote> slot, and the null ID 16.338 - in the second. When you <command role="hg-cmd">hg 16.339 - merge</command> with another changeset, the first parent 16.340 - remains unchanged, and the second parent is filled in with the 16.341 - changeset you're merging with. The <command role="hg-cmd">hg 16.342 - parents</command> command tells you what the parents of the 16.343 - dirstate are.</para> 16.344 - 16.345 - <sect2> 16.346 - <title>What happens when you commit</title> 16.347 - 16.348 - <para>The dirstate stores parent information for more than just 16.349 - book-keeping purposes. Mercurial uses the parents of the 16.350 - dirstate as <emphasis>the parents of a new 16.351 - changeset</emphasis> when you perform a commit.</para> 16.352 - 16.353 - <informalfigure id="fig.concepts.wdir"> 16.354 - <mediaobject> 16.355 - <imageobject><imagedata fileref="images/wdir.png"/></imageobject> 16.356 - <textobject><phrase>XXX add text</phrase></textobject> 16.357 - <caption><para id="fig.concepts.wdir.caption">The working 16.358 - directory can have two parents</para></caption> 16.359 - </mediaobject> 16.360 - </informalfigure> 16.361 - 16.362 - <para>Figure <xref endterm="fig.concepts.wdir.caption" 16.363 - linkend="fig.concepts.wdir"/> shows the 16.364 - normal state of the working directory, where it has a single 16.365 - changeset as parent. That changeset is the 16.366 - <emphasis>tip</emphasis>, the newest changeset in the 16.367 - repository that has no children.</para> 16.368 - 16.369 - <informalfigure id="fig.concepts.wdir-after-commit"> 16.370 - <mediaobject> 16.371 - <imageobject><imagedata fileref="images/wdir-after-commit.png"/> 16.372 - </imageobject> 16.373 - <textobject><phrase>XXX add text</phrase></textobject> 16.374 - <caption><para id="fig.concepts.wdir-after-commit.caption">The working 16.375 - directory gains new parents after a commit</para></caption> 16.376 - </mediaobject> 16.377 - </informalfigure> 16.378 - 16.379 - <para>It's useful to think of the working directory as 16.380 - <quote>the changeset I'm about to commit</quote>. Any files 16.381 - that you tell Mercurial that you've added, removed, renamed, 16.382 - or copied will be reflected in that changeset, as will 16.383 - modifications to any files that Mercurial is already tracking; 16.384 - the new changeset will have the parents of the working 16.385 - directory as its parents.</para> 16.386 - 16.387 - <para>After a commit, Mercurial will update the parents of the 16.388 - working directory, so that the first parent is the ID of the 16.389 - new changeset, and the second is the null ID. This is shown 16.390 - in figure <xref endterm="fig.concepts.wdir-after-commit.caption" 16.391 - linkend="fig.concepts.wdir-after-commit"/>. 16.392 - Mercurial 16.393 - doesn't touch any of the files in the working directory when 16.394 - you commit; it just modifies the dirstate to note its new 16.395 - parents.</para> 16.396 - 16.397 - </sect2> 16.398 - <sect2> 16.399 - <title>Creating a new head</title> 16.400 - 16.401 - <para>It's perfectly normal to update the working directory to a 16.402 - changeset other than the current tip. For example, you might 16.403 - want to know what your project looked like last Tuesday, or 16.404 - you could be looking through changesets to see which one 16.405 - introduced a bug. In cases like this, the natural thing to do 16.406 - is update the working directory to the changeset you're 16.407 - interested in, and then examine the files in the working 16.408 - directory directly to see their contents as they were when you 16.409 - committed that changeset. The effect of this is shown in 16.410 - figure <xref endterm="fig.concepts.wdir-pre-branch.caption" 16.411 - linkend="fig.concepts.wdir-pre-branch"/>.</para> 16.412 - 16.413 - <informalfigure id="fig.concepts.wdir-pre-branch"> 16.414 - <mediaobject> 16.415 - <imageobject><imagedata fileref="images/wdir-pre-branch.png"/> 16.416 - </imageobject> 16.417 - <textobject><phrase>XXX add text</phrase></textobject> 16.418 - <caption><para id="fig.concepts.wdir-pre-branch.caption">The working 16.419 - directory, updated to an older changeset</para></caption> 16.420 - </mediaobject> 16.421 - </informalfigure> 16.422 - 16.423 - <para>Having updated the working directory to an older 16.424 - changeset, what happens if you make some changes, and then 16.425 - commit? Mercurial behaves in the same way as I outlined 16.426 - above. The parents of the working directory become the 16.427 - parents of the new changeset. This new changeset has no 16.428 - children, so it becomes the new tip. And the repository now 16.429 - contains two changesets that have no children; we call these 16.430 - <emphasis>heads</emphasis>. You can see the structure that 16.431 - this creates in figure <xref 16.432 - endterm="fig.concepts.wdir-branch.caption" 16.433 - linkend="fig.concepts.wdir-branch"/>.</para> 16.434 - 16.435 - <informalfigure id="fig.concepts.wdir-branch"> 16.436 - <mediaobject> 16.437 - <imageobject><imagedata fileref="images/wdir-branch.png"/> 16.438 - </imageobject> 16.439 - <textobject><phrase>XXX add text</phrase></textobject> 16.440 - <caption><para id="fig.concepts.wdir-branch.caption">After a 16.441 - commit made while synced to an older changeset</para></caption> 16.442 - </mediaobject> 16.443 - </informalfigure> 16.444 - 16.445 - <note> 16.446 - <para> If you're new to Mercurial, you should keep in mind a 16.447 - common <quote>error</quote>, which is to use the <command 16.448 - role="hg-cmd">hg pull</command> command without any 16.449 - options. By default, the <command role="hg-cmd">hg 16.450 - pull</command> command <emphasis>does not</emphasis> 16.451 - update the working directory, so you'll bring new changesets 16.452 - into your repository, but the working directory will stay 16.453 - synced at the same changeset as before the pull. If you 16.454 - make some changes and commit afterwards, you'll thus create 16.455 - a new head, because your working directory isn't synced to 16.456 - whatever the current tip is.</para> 16.457 - 16.458 - <para> I put the word <quote>error</quote> in quotes because 16.459 - all that you need to do to rectify this situation is 16.460 - <command role="hg-cmd">hg merge</command>, then <command 16.461 - role="hg-cmd">hg commit</command>. In other words, this 16.462 - almost never has negative consequences; it just surprises 16.463 - people. I'll discuss other ways to avoid this behaviour, 16.464 - and why Mercurial behaves in this initially surprising way, 16.465 - later on.</para> 16.466 - </note> 16.467 - 16.468 - </sect2> 16.469 - <sect2> 16.470 - <title>Merging heads</title> 16.471 - 16.472 - <para>When you run the <command role="hg-cmd">hg merge</command> 16.473 - command, Mercurial leaves the first parent of the working 16.474 - directory unchanged, and sets the second parent to the 16.475 - changeset you're merging with, as shown in figure <xref 16.476 - endterm="fig.concepts.wdir-merge.caption" 16.477 - linkend="fig.concepts.wdir-merge"/>.</para> 16.478 - 16.479 - <informalfigure id="fig.concepts.wdir-merge"> 16.480 - <mediaobject> 16.481 - <imageobject><imagedata fileref="images/wdir-merge.png"/> 16.482 - </imageobject> 16.483 - <textobject><phrase>XXX add text</phrase></textobject> 16.484 - <caption><para id="fig.concepts.wdir-merge.caption">Merging two 16.485 - heads</para></caption> 16.486 - </mediaobject> 16.487 - </informalfigure> 16.488 - 16.489 - <para>Mercurial also has to modify the working directory, to 16.490 - merge the files managed in the two changesets. Simplified a 16.491 - little, the merging process goes like this, for every file in 16.492 - the manifests of both changesets.</para> 16.493 - <itemizedlist> 16.494 - <listitem><para>If neither changeset has modified a file, do 16.495 - nothing with that file.</para> 16.496 - </listitem> 16.497 - <listitem><para>If one changeset has modified a file, and the 16.498 - other hasn't, create the modified copy of the file in the 16.499 - working directory.</para> 16.500 - </listitem> 16.501 - <listitem><para>If one changeset has removed a file, and the 16.502 - other hasn't (or has also deleted it), delete the file 16.503 - from the working directory.</para> 16.504 - </listitem> 16.505 - <listitem><para>If one changeset has removed a file, but the 16.506 - other has modified the file, ask the user what to do: keep 16.507 - the modified file, or remove it?</para> 16.508 - </listitem> 16.509 - <listitem><para>If both changesets have modified a file, 16.510 - invoke an external merge program to choose the new 16.511 - contents for the merged file. This may require input from 16.512 - the user.</para> 16.513 - </listitem> 16.514 - <listitem><para>If one changeset has modified a file, and the 16.515 - other has renamed or copied the file, make sure that the 16.516 - changes follow the new name of the file.</para> 16.517 - </listitem></itemizedlist> 16.518 - <para>There are more details&emdash;merging has plenty of corner 16.519 - cases&emdash;but these are the most common choices that are 16.520 - involved in a merge. As you can see, most cases are 16.521 - completely automatic, and indeed most merges finish 16.522 - automatically, without requiring your input to resolve any 16.523 - conflicts.</para> 16.524 - 16.525 - <para>When you're thinking about what happens when you commit 16.526 - after a merge, once again the working directory is <quote>the 16.527 - changeset I'm about to commit</quote>. After the <command 16.528 - role="hg-cmd">hg merge</command> command completes, the 16.529 - working directory has two parents; these will become the 16.530 - parents of the new changeset.</para> 16.531 - 16.532 - <para>Mercurial lets you perform multiple merges, but you must 16.533 - commit the results of each individual merge as you go. This 16.534 - is necessary because Mercurial only tracks two parents for 16.535 - both revisions and the working directory. While it would be 16.536 - technically possible to merge multiple changesets at once, the 16.537 - prospect of user confusion and making a terrible mess of a 16.538 - merge immediately becomes overwhelming.</para> 16.539 - 16.540 - </sect2> 16.541 - </sect1> 16.542 - <sect1> 16.543 - <title>Other interesting design features</title> 16.544 - 16.545 - <para>In the sections above, I've tried to highlight some of the 16.546 - most important aspects of Mercurial's design, to illustrate that 16.547 - it pays careful attention to reliability and performance. 16.548 - However, the attention to detail doesn't stop there. There are 16.549 - a number of other aspects of Mercurial's construction that I 16.550 - personally find interesting. I'll detail a few of them here, 16.551 - separate from the <quote>big ticket</quote> items above, so that 16.552 - if you're interested, you can gain a better idea of the amount 16.553 - of thinking that goes into a well-designed system.</para> 16.554 - 16.555 - <sect2> 16.556 - <title>Clever compression</title> 16.557 - 16.558 - <para>When appropriate, Mercurial will store both snapshots and 16.559 - deltas in compressed form. It does this by always 16.560 - <emphasis>trying to</emphasis> compress a snapshot or delta, 16.561 - but only storing the compressed version if it's smaller than 16.562 - the uncompressed version.</para> 16.563 - 16.564 - <para>This means that Mercurial does <quote>the right 16.565 - thing</quote> when storing a file whose native form is 16.566 - compressed, such as a <literal>zip</literal> archive or a JPEG 16.567 - image. When these types of files are compressed a second 16.568 - time, the resulting file is usually bigger than the 16.569 - once-compressed form, and so Mercurial will store the plain 16.570 - <literal>zip</literal> or JPEG.</para> 16.571 - 16.572 - <para>Deltas between revisions of a compressed file are usually 16.573 - larger than snapshots of the file, and Mercurial again does 16.574 - <quote>the right thing</quote> in these cases. It finds that 16.575 - such a delta exceeds the threshold at which it should store a 16.576 - complete snapshot of the file, so it stores the snapshot, 16.577 - again saving space compared to a naive delta-only 16.578 - approach.</para> 16.579 - 16.580 - <sect3> 16.581 - <title>Network recompression</title> 16.582 - 16.583 - <para>When storing revisions on disk, Mercurial uses the 16.584 - <quote>deflate</quote> compression algorithm (the same one 16.585 - used by the popular <literal>zip</literal> archive format), 16.586 - which balances good speed with a respectable compression 16.587 - ratio. However, when transmitting revision data over a 16.588 - network connection, Mercurial uncompresses the compressed 16.589 - revision data.</para> 16.590 - 16.591 - <para>If the connection is over HTTP, Mercurial recompresses 16.592 - the entire stream of data using a compression algorithm that 16.593 - gives a better compression ratio (the Burrows-Wheeler 16.594 - algorithm from the widely used <literal>bzip2</literal> 16.595 - compression package). This combination of algorithm and 16.596 - compression of the entire stream (instead of a revision at a 16.597 - time) substantially reduces the number of bytes to be 16.598 - transferred, yielding better network performance over almost 16.599 - all kinds of network.</para> 16.600 - 16.601 - <para>(If the connection is over <command>ssh</command>, 16.602 - Mercurial <emphasis>doesn't</emphasis> recompress the 16.603 - stream, because <command>ssh</command> can already do this 16.604 - itself.)</para> 16.605 - 16.606 - </sect3> 16.607 - </sect2> 16.608 - <sect2> 16.609 - <title>Read/write ordering and atomicity</title> 16.610 - 16.611 - <para>Appending to files isn't the whole story when it comes to 16.612 - guaranteeing that a reader won't see a partial write. If you 16.613 - recall figure <xref endterm="fig.concepts.metadata.caption" 16.614 - linkend="fig.concepts.metadata"/>, revisions in the 16.615 - changelog point to revisions in the manifest, and revisions in 16.616 - the manifest point to revisions in filelogs. This hierarchy 16.617 - is deliberate.</para> 16.618 - 16.619 - <para>A writer starts a transaction by writing filelog and 16.620 - manifest data, and doesn't write any changelog data until 16.621 - those are finished. A reader starts by reading changelog 16.622 - data, then manifest data, followed by filelog data.</para> 16.623 - 16.624 - <para>Since the writer has always finished writing filelog and 16.625 - manifest data before it writes to the changelog, a reader will 16.626 - never read a pointer to a partially written manifest revision 16.627 - from the changelog, and it will never read a pointer to a 16.628 - partially written filelog revision from the manifest.</para> 16.629 - 16.630 - </sect2> 16.631 - <sect2> 16.632 - <title>Concurrent access</title> 16.633 - 16.634 - <para>The read/write ordering and atomicity guarantees mean that 16.635 - Mercurial never needs to <emphasis>lock</emphasis> a 16.636 - repository when it's reading data, even if the repository is 16.637 - being written to while the read is occurring. This has a big 16.638 - effect on scalability; you can have an arbitrary number of 16.639 - Mercurial processes safely reading data from a repository 16.640 - safely all at once, no matter whether it's being written to or 16.641 - not.</para> 16.642 - 16.643 - <para>The lockless nature of reading means that if you're 16.644 - sharing a repository on a multi-user system, you don't need to 16.645 - grant other local users permission to 16.646 - <emphasis>write</emphasis> to your repository in order for 16.647 - them to be able to clone it or pull changes from it; they only 16.648 - need <emphasis>read</emphasis> permission. (This is 16.649 - <emphasis>not</emphasis> a common feature among revision 16.650 - control systems, so don't take it for granted! Most require 16.651 - readers to be able to lock a repository to access it safely, 16.652 - and this requires write permission on at least one directory, 16.653 - which of course makes for all kinds of nasty and annoying 16.654 - security and administrative problems.)</para> 16.655 - 16.656 - <para>Mercurial uses locks to ensure that only one process can 16.657 - write to a repository at a time (the locking mechanism is safe 16.658 - even over filesystems that are notoriously hostile to locking, 16.659 - such as NFS). If a repository is locked, a writer will wait 16.660 - for a while to retry if the repository becomes unlocked, but 16.661 - if the repository remains locked for too long, the process 16.662 - attempting to write will time out after a while. This means 16.663 - that your daily automated scripts won't get stuck forever and 16.664 - pile up if a system crashes unnoticed, for example. (Yes, the 16.665 - timeout is configurable, from zero to infinity.)</para> 16.666 - 16.667 - <sect3> 16.668 - <title>Safe dirstate access</title> 16.669 - 16.670 - <para>As with revision data, Mercurial doesn't take a lock to 16.671 - read the dirstate file; it does acquire a lock to write it. 16.672 - To avoid the possibility of reading a partially written copy 16.673 - of the dirstate file, Mercurial writes to a file with a 16.674 - unique name in the same directory as the dirstate file, then 16.675 - renames the temporary file atomically to 16.676 - <filename>dirstate</filename>. The file named 16.677 - <filename>dirstate</filename> is thus guaranteed to be 16.678 - complete, not partially written.</para> 16.679 - 16.680 - </sect3> 16.681 - </sect2> 16.682 - <sect2> 16.683 - <title>Avoiding seeks</title> 16.684 - 16.685 - <para>Critical to Mercurial's performance is the avoidance of 16.686 - seeks of the disk head, since any seek is far more expensive 16.687 - than even a comparatively large read operation.</para> 16.688 - 16.689 - <para>This is why, for example, the dirstate is stored in a 16.690 - single file. If there were a dirstate file per directory that 16.691 - Mercurial tracked, the disk would seek once per directory. 16.692 - Instead, Mercurial reads the entire single dirstate file in 16.693 - one step.</para> 16.694 - 16.695 - <para>Mercurial also uses a <quote>copy on write</quote> scheme 16.696 - when cloning a repository on local storage. Instead of 16.697 - copying every revlog file from the old repository into the new 16.698 - repository, it makes a <quote>hard link</quote>, which is a 16.699 - shorthand way to say <quote>these two names point to the same 16.700 - file</quote>. When Mercurial is about to write to one of a 16.701 - revlog's files, it checks to see if the number of names 16.702 - pointing at the file is greater than one. If it is, more than 16.703 - one repository is using the file, so Mercurial makes a new 16.704 - copy of the file that is private to this repository.</para> 16.705 - 16.706 - <para>A few revision control developers have pointed out that 16.707 - this idea of making a complete private copy of a file is not 16.708 - very efficient in its use of storage. While this is true, 16.709 - storage is cheap, and this method gives the highest 16.710 - performance while deferring most book-keeping to the operating 16.711 - system. An alternative scheme would most likely reduce 16.712 - performance and increase the complexity of the software, each 16.713 - of which is much more important to the <quote>feel</quote> of 16.714 - day-to-day use.</para> 16.715 - 16.716 - </sect2> 16.717 - <sect2> 16.718 - <title>Other contents of the dirstate</title> 16.719 - 16.720 - <para>Because Mercurial doesn't force you to tell it when you're 16.721 - modifying a file, it uses the dirstate to store some extra 16.722 - information so it can determine efficiently whether you have 16.723 - modified a file. For each file in the working directory, it 16.724 - stores the time that it last modified the file itself, and the 16.725 - size of the file at that time.</para> 16.726 - 16.727 - <para>When you explicitly <command role="hg-cmd">hg 16.728 - add</command>, <command role="hg-cmd">hg remove</command>, 16.729 - <command role="hg-cmd">hg rename</command> or <command 16.730 - role="hg-cmd">hg copy</command> files, Mercurial updates the 16.731 - dirstate so that it knows what to do with those files when you 16.732 - commit.</para> 16.733 - 16.734 - <para>When Mercurial is checking the states of files in the 16.735 - working directory, it first checks a file's modification time. 16.736 - If that has not changed, the file must not have been modified. 16.737 - If the file's size has changed, the file must have been 16.738 - modified. If the modification time has changed, but the size 16.739 - has not, only then does Mercurial need to read the actual 16.740 - contents of the file to see if they've changed. Storing these 16.741 - few extra pieces of information dramatically reduces the 16.742 - amount of data that Mercurial needs to read, which yields 16.743 - large performance improvements compared to other revision 16.744 - control systems.</para> 16.745 - 16.746 - </sect2> 16.747 - </sect1> 16.748 -</chapter> 16.749 - 16.750 -<!-- 16.751 -local variables: 16.752 -sgml-parent-document: ("00book.xml" "book" "chapter") 16.753 -end: 16.754 --->
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/en/ch04-daily.xml Fri Mar 20 16:43:35 2009 +0800 17.3 @@ -0,0 +1,544 @@ 17.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 17.5 + 17.6 +<chapter id="chap.daily"> 17.7 + <?dbhtml filename="mercurial-in-daily-use.html"?> 17.8 + <title>Mercurial in daily use</title> 17.9 + 17.10 + <sect1> 17.11 + <title>Telling Mercurial which files to track</title> 17.12 + 17.13 + <para id="x_1a3">Mercurial does not work with files in your repository unless 17.14 + you tell it to manage them. The <command role="hg-cmd">hg 17.15 + status</command> command will tell you which files Mercurial 17.16 + doesn't know about; it uses a 17.17 + <quote><literal>?</literal></quote> to display such 17.18 + files.</para> 17.19 + 17.20 + <para id="x_1a4">To tell Mercurial to track a file, use the <command 17.21 + role="hg-cmd">hg add</command> command. Once you have added a 17.22 + file, the entry in the output of <command role="hg-cmd">hg 17.23 + status</command> for that file changes from 17.24 + <quote><literal>?</literal></quote> to 17.25 + <quote><literal>A</literal></quote>.</para> 17.26 + 17.27 + &interaction.daily.files.add; 17.28 + 17.29 + <para id="x_1a5">After you run a <command role="hg-cmd">hg commit</command>, 17.30 + the files that you added before the commit will no longer be 17.31 + listed in the output of <command role="hg-cmd">hg 17.32 + status</command>. The reason for this is that <command 17.33 + role="hg-cmd">hg status</command> only tells you about 17.34 + <quote>interesting</quote> files&emdash;those that you have 17.35 + modified or told Mercurial to do something with&emdash;by 17.36 + default. If you have a repository that contains thousands of 17.37 + files, you will rarely want to know about files that Mercurial 17.38 + is tracking, but that have not changed. (You can still get this 17.39 + information; we'll return to this later.)</para> 17.40 + 17.41 + <para id="x_1a6">Once you add a file, Mercurial doesn't do anything with it 17.42 + immediately. Instead, it will take a snapshot of the file's 17.43 + state the next time you perform a commit. It will then continue 17.44 + to track the changes you make to the file every time you commit, 17.45 + until you remove the file.</para> 17.46 + 17.47 + <sect2> 17.48 + <title>Explicit versus implicit file naming</title> 17.49 + 17.50 + <para id="x_1a7">A useful behaviour that Mercurial has is that if you pass 17.51 + the name of a directory to a command, every Mercurial command 17.52 + will treat this as <quote>I want to operate on every file in 17.53 + this directory and its subdirectories</quote>.</para> 17.54 + 17.55 + &interaction.daily.files.add-dir; 17.56 + 17.57 + <para id="x_1a8">Notice in this example that Mercurial printed the names of 17.58 + the files it added, whereas it didn't do so when we added the 17.59 + file named <filename>a</filename> in the earlier 17.60 + example.</para> 17.61 + 17.62 + <para id="x_1a9">What's going on is that in the former case, we explicitly 17.63 + named the file to add on the command line, so the assumption 17.64 + that Mercurial makes in such cases is that you know what you 17.65 + were doing, and it doesn't print any output.</para> 17.66 + 17.67 + <para id="x_1aa">However, when we <emphasis>imply</emphasis> the names of 17.68 + files by giving the name of a directory, Mercurial takes the 17.69 + extra step of printing the name of each file that it does 17.70 + something with. This makes it more clear what is happening, 17.71 + and reduces the likelihood of a silent and nasty surprise. 17.72 + This behaviour is common to most Mercurial commands.</para> 17.73 + 17.74 + </sect2> 17.75 + <sect2> 17.76 + <title>Aside: Mercurial tracks files, not directories</title> 17.77 + 17.78 + <para id="x_1ab">Mercurial does not track directory information. Instead, 17.79 + it tracks the path to a file. Before creating a file, it 17.80 + first creates any missing directory components of the path. 17.81 + After it deletes a file, it then deletes any empty directories 17.82 + that were in the deleted file's path. This sounds like a 17.83 + trivial distinction, but it has one minor practical 17.84 + consequence: it is not possible to represent a completely 17.85 + empty directory in Mercurial.</para> 17.86 + 17.87 + <para id="x_1ac">Empty directories are rarely useful, and there are 17.88 + unintrusive workarounds that you can use to achieve an 17.89 + appropriate effect. The developers of Mercurial thus felt 17.90 + that the complexity that would be required to manage empty 17.91 + directories was not worth the limited benefit this feature 17.92 + would bring.</para> 17.93 + 17.94 + <para id="x_1ad">If you need an empty directory in your repository, there 17.95 + are a few ways to achieve this. One is to create a directory, 17.96 + then <command role="hg-cmd">hg add</command> a 17.97 + <quote>hidden</quote> file to that directory. On Unix-like 17.98 + systems, any file name that begins with a period 17.99 + (<quote><literal>.</literal></quote>) is treated as hidden by 17.100 + most commands and GUI tools. This approach is illustrated 17.101 + below.</para> 17.102 + 17.103 +&interaction.daily.files.hidden; 17.104 + 17.105 + <para id="x_1ae">Another way to tackle a need for an empty directory is to 17.106 + simply create one in your automated build scripts before they 17.107 + will need it.</para> 17.108 + 17.109 + </sect2> 17.110 + </sect1> 17.111 + <sect1> 17.112 + <title>How to stop tracking a file</title> 17.113 + 17.114 + <para id="x_1af">Once you decide that a file no longer belongs in your 17.115 + repository, use the <command role="hg-cmd">hg remove</command> 17.116 + command; this deletes the file, and tells Mercurial to stop 17.117 + tracking it. A removed file is represented in the output of 17.118 + <command role="hg-cmd">hg status</command> with a 17.119 + <quote><literal>R</literal></quote>.</para> 17.120 + 17.121 + &interaction.daily.files.remove; 17.122 + 17.123 + <para id="x_1b0">After you <command role="hg-cmd">hg remove</command> a file, 17.124 + Mercurial will no longer track changes to that file, even if you 17.125 + recreate a file with the same name in your working directory. 17.126 + If you do recreate a file with the same name and want Mercurial 17.127 + to track the new file, simply <command role="hg-cmd">hg 17.128 + add</command> it. Mercurial will know that the newly added 17.129 + file is not related to the old file of the same name.</para> 17.130 + 17.131 + <sect2> 17.132 + <title>Removing a file does not affect its history</title> 17.133 + 17.134 + <para id="x_1b1">It is important to understand that removing a file has 17.135 + only two effects.</para> 17.136 + <itemizedlist> 17.137 + <listitem><para id="x_1b2">It removes the current version of the file 17.138 + from the working directory.</para> 17.139 + </listitem> 17.140 + <listitem><para id="x_1b3">It stops Mercurial from tracking changes to 17.141 + the file, from the time of the next commit.</para> 17.142 + </listitem></itemizedlist> 17.143 + <para id="x_1b4">Removing a file <emphasis>does not</emphasis> in any way 17.144 + alter the <emphasis>history</emphasis> of the file.</para> 17.145 + 17.146 + <para id="x_1b5">If you update the working directory to a changeset in 17.147 + which a file that you have removed was still tracked, it will 17.148 + reappear in the working directory, with the contents it had 17.149 + when you committed that changeset. If you then update the 17.150 + working directory to a later changeset, in which the file had 17.151 + been removed, Mercurial will once again remove the file from 17.152 + the working directory.</para> 17.153 + 17.154 + </sect2> 17.155 + <sect2> 17.156 + <title>Missing files</title> 17.157 + 17.158 + <para id="x_1b6">Mercurial considers a file that you have deleted, but not 17.159 + used <command role="hg-cmd">hg remove</command> to delete, to 17.160 + be <emphasis>missing</emphasis>. A missing file is 17.161 + represented with <quote><literal>!</literal></quote> in the 17.162 + output of <command role="hg-cmd">hg status</command>. 17.163 + Mercurial commands will not generally do anything with missing 17.164 + files.</para> 17.165 + 17.166 + &interaction.daily.files.missing; 17.167 + 17.168 + <para id="x_1b7">If your repository contains a file that <command 17.169 + role="hg-cmd">hg status</command> reports as missing, and 17.170 + you want the file to stay gone, you can run <command 17.171 + role="hg-cmd">hg remove <option 17.172 + role="hg-opt-remove">--after</option></command> at any 17.173 + time later on, to tell Mercurial that you really did mean to 17.174 + remove the file.</para> 17.175 + 17.176 + &interaction.daily.files.remove-after; 17.177 + 17.178 + <para id="x_1b8">On the other hand, if you deleted the missing file by 17.179 + accident, give <command role="hg-cmd">hg revert</command> the 17.180 + name of the file to recover. It will reappear, in unmodified 17.181 + form.</para> 17.182 + 17.183 +&interaction.daily.files.recover-missing; 17.184 + 17.185 + </sect2> 17.186 + <sect2> 17.187 + <title>Aside: why tell Mercurial explicitly to remove a 17.188 + file?</title> 17.189 + 17.190 + <para id="x_1b9">You might wonder why Mercurial requires you to explicitly 17.191 + tell it that you are deleting a file. Early during the 17.192 + development of Mercurial, it let you delete a file however you 17.193 + pleased; Mercurial would notice the absence of the file 17.194 + automatically when you next ran a <command role="hg-cmd">hg 17.195 + commit</command>, and stop tracking the file. In practice, 17.196 + this made it too easy to accidentally remove a file without 17.197 + noticing.</para> 17.198 + 17.199 + </sect2> 17.200 + <sect2> 17.201 + <title>Useful shorthand&emdash;adding and removing files in one 17.202 + step</title> 17.203 + 17.204 + <para id="x_1ba">Mercurial offers a combination command, <command 17.205 + role="hg-cmd">hg addremove</command>, that adds untracked 17.206 + files and marks missing files as removed.</para> 17.207 + 17.208 + &interaction.daily.files.addremove; 17.209 + 17.210 + <para id="x_1bb">The <command role="hg-cmd">hg commit</command> command 17.211 + also provides a <option role="hg-opt-commit">-A</option> 17.212 + option that performs this same add-and-remove, immediately 17.213 + followed by a commit.</para> 17.214 + 17.215 + &interaction.daily.files.commit-addremove; 17.216 + 17.217 + </sect2> 17.218 + </sect1> 17.219 + <sect1> 17.220 + <title>Copying files</title> 17.221 + 17.222 + <para id="x_1bc">Mercurial provides a <command role="hg-cmd">hg 17.223 + copy</command> command that lets you make a new copy of a 17.224 + file. When you copy a file using this command, Mercurial makes 17.225 + a record of the fact that the new file is a copy of the original 17.226 + file. It treats these copied files specially when you merge 17.227 + your work with someone else's.</para> 17.228 + 17.229 + <sect2> 17.230 + <title>The results of copying during a merge</title> 17.231 + 17.232 + <para id="x_1bd">What happens during a merge is that changes 17.233 + <quote>follow</quote> a copy. To best illustrate what this 17.234 + means, let's create an example. We'll start with the usual 17.235 + tiny repository that contains a single file.</para> 17.236 + 17.237 + &interaction.daily.copy.init; 17.238 + 17.239 + <para id="x_1be">We need to do some work in 17.240 + parallel, so that we'll have something to merge. So let's 17.241 + clone our repository.</para> 17.242 + 17.243 + &interaction.daily.copy.clone; 17.244 + 17.245 + <para id="x_1bf">Back in our initial repository, let's use the <command 17.246 + role="hg-cmd">hg copy</command> command to make a copy of 17.247 + the first file we created.</para> 17.248 + 17.249 + &interaction.daily.copy.copy; 17.250 + 17.251 + <para id="x_1c0">If we look at the output of the <command role="hg-cmd">hg 17.252 + status</command> command afterwards, the copied file looks 17.253 + just like a normal added file.</para> 17.254 + 17.255 + &interaction.daily.copy.status; 17.256 + 17.257 + <para id="x_1c1">But if we pass the <option 17.258 + role="hg-opt-status">-C</option> option to <command 17.259 + role="hg-cmd">hg status</command>, it prints another line of 17.260 + output: this is the file that our newly-added file was copied 17.261 + <emphasis>from</emphasis>.</para> 17.262 + 17.263 + &interaction.daily.copy.status-copy; 17.264 + 17.265 + <para id="x_1c2">Now, back in the repository we cloned, let's make a change 17.266 + in parallel. We'll add a line of content to the original file 17.267 + that we created.</para> 17.268 + 17.269 + &interaction.daily.copy.other; 17.270 + 17.271 + <para id="x_1c3">Now we have a modified <filename>file</filename> in this 17.272 + repository. When we pull the changes from the first 17.273 + repository, and merge the two heads, Mercurial will propagate 17.274 + the changes that we made locally to <filename>file</filename> 17.275 + into its copy, <filename>new-file</filename>.</para> 17.276 + 17.277 + &interaction.daily.copy.merge; 17.278 + 17.279 + </sect2> 17.280 + <sect2 id="sec.daily.why-copy"> 17.281 + <title>Why should changes follow copies?</title> 17.282 + 17.283 + <para id="x_1c4">This behaviour, of changes to a file propagating out to 17.284 + copies of the file, might seem esoteric, but in most cases 17.285 + it's highly desirable.</para> 17.286 + 17.287 + <para id="x_1c5">First of all, remember that this propagation 17.288 + <emphasis>only</emphasis> happens when you merge. So if you 17.289 + <command role="hg-cmd">hg copy</command> a file, and 17.290 + subsequently modify the original file during the normal course 17.291 + of your work, nothing will happen.</para> 17.292 + 17.293 + <para id="x_1c6">The second thing to know is that modifications will only 17.294 + propagate across a copy as long as the repository that you're 17.295 + pulling changes from <emphasis>doesn't know</emphasis> about 17.296 + the copy.</para> 17.297 + 17.298 + <para id="x_1c7">The reason that Mercurial does this is as follows. Let's 17.299 + say I make an important bug fix in a source file, and commit 17.300 + my changes. Meanwhile, you've decided to <command 17.301 + role="hg-cmd">hg copy</command> the file in your repository, 17.302 + without knowing about the bug or having seen the fix, and you 17.303 + have started hacking on your copy of the file.</para> 17.304 + 17.305 + <para id="x_1c8">If you pulled and merged my changes, and Mercurial 17.306 + <emphasis>didn't</emphasis> propagate changes across copies, 17.307 + your source file would now contain the bug, and unless you 17.308 + remembered to propagate the bug fix by hand, the bug would 17.309 + <emphasis>remain</emphasis> in your copy of the file.</para> 17.310 + 17.311 + <para id="x_1c9">By automatically propagating the change that fixed the bug 17.312 + from the original file to the copy, Mercurial prevents this 17.313 + class of problem. To my knowledge, Mercurial is the 17.314 + <emphasis>only</emphasis> revision control system that 17.315 + propagates changes across copies like this.</para> 17.316 + 17.317 + <para id="x_1ca">Once your change history has a record that the copy and 17.318 + subsequent merge occurred, there's usually no further need to 17.319 + propagate changes from the original file to the copied file, 17.320 + and that's why Mercurial only propagates changes across copies 17.321 + until this point, and no further.</para> 17.322 + 17.323 + </sect2> 17.324 + <sect2> 17.325 + <title>How to make changes <emphasis>not</emphasis> follow a 17.326 + copy</title> 17.327 + 17.328 + <para id="x_1cb">If, for some reason, you decide that this business of 17.329 + automatically propagating changes across copies is not for 17.330 + you, simply use your system's normal file copy command (on 17.331 + Unix-like systems, that's <command>cp</command>) to make a 17.332 + copy of a file, then <command role="hg-cmd">hg add</command> 17.333 + the new copy by hand. Before you do so, though, please do 17.334 + reread section <xref linkend="sec.daily.why-copy"/>, and make 17.335 + an informed 17.336 + decision that this behaviour is not appropriate to your 17.337 + specific case.</para> 17.338 + 17.339 + </sect2> 17.340 + <sect2> 17.341 + <title>Behaviour of the <command role="hg-cmd">hg copy</command> 17.342 + command</title> 17.343 + 17.344 + <para id="x_1cc">When you use the <command role="hg-cmd">hg copy</command> 17.345 + command, Mercurial makes a copy of each source file as it 17.346 + currently stands in the working directory. This means that if 17.347 + you make some modifications to a file, then <command 17.348 + role="hg-cmd">hg copy</command> it without first having 17.349 + committed those changes, the new copy will also contain the 17.350 + modifications you have made up until that point. (I find this 17.351 + behaviour a little counterintuitive, which is why I mention it 17.352 + here.)</para> 17.353 + 17.354 + <para id="x_1cd">The <command role="hg-cmd">hg copy</command> command acts 17.355 + similarly to the Unix <command>cp</command> command (you can 17.356 + use the <command role="hg-cmd">hg cp</command> alias if you 17.357 + prefer). The last argument is the 17.358 + <emphasis>destination</emphasis>, and all prior arguments are 17.359 + <emphasis>sources</emphasis>. If you pass it a single file as 17.360 + the source, and the destination does not exist, it creates a 17.361 + new file with that name.</para> 17.362 + 17.363 + &interaction.daily.copy.simple; 17.364 + 17.365 + <para id="x_1ce">If the destination is a directory, Mercurial copies its 17.366 + sources into that directory.</para> 17.367 + 17.368 + &interaction.daily.copy.dir-dest; 17.369 + 17.370 + <para id="x_1cf">Copying a directory is 17.371 + recursive, and preserves the directory structure of the 17.372 + source.</para> 17.373 + 17.374 + &interaction.daily.copy.dir-src; 17.375 + 17.376 + <para id="x_1d0">If the source and destination are both directories, the 17.377 + source tree is recreated in the destination directory.</para> 17.378 + 17.379 + &interaction.daily.copy.dir-src-dest; 17.380 + 17.381 + <para id="x_1d1">As with the <command role="hg-cmd">hg rename</command> 17.382 + command, if you copy a file manually and then want Mercurial 17.383 + to know that you've copied the file, simply use the <option 17.384 + role="hg-opt-copy">--after</option> option to <command 17.385 + role="hg-cmd">hg copy</command>.</para> 17.386 + 17.387 + &interaction.daily.copy.after; 17.388 + 17.389 + </sect2> 17.390 + </sect1> 17.391 + <sect1> 17.392 + <title>Renaming files</title> 17.393 + 17.394 + <para id="x_1d2">It's rather more common to need to rename a file than to 17.395 + make a copy of it. The reason I discussed the <command 17.396 + role="hg-cmd">hg copy</command> command before talking about 17.397 + renaming files is that Mercurial treats a rename in essentially 17.398 + the same way as a copy. Therefore, knowing what Mercurial does 17.399 + when you copy a file tells you what to expect when you rename a 17.400 + file.</para> 17.401 + 17.402 + <para id="x_1d3">When you use the <command role="hg-cmd">hg rename</command> 17.403 + command, Mercurial makes a copy of each source file, then 17.404 + deletes it and marks the file as removed.</para> 17.405 + 17.406 + &interaction.daily.rename.rename; 17.407 + 17.408 + <para id="x_1d4">The <command role="hg-cmd">hg status</command> command shows 17.409 + the newly copied file as added, and the copied-from file as 17.410 + removed.</para> 17.411 + 17.412 + &interaction.daily.rename.status; 17.413 + 17.414 + <para id="x_1d5">As with the results of a <command role="hg-cmd">hg 17.415 + copy</command>, we must use the <option 17.416 + role="hg-opt-status">-C</option> option to <command 17.417 + role="hg-cmd">hg status</command> to see that the added file 17.418 + is really being tracked by Mercurial as a copy of the original, 17.419 + now removed, file.</para> 17.420 + 17.421 + &interaction.daily.rename.status-copy; 17.422 + 17.423 + <para id="x_1d6">As with <command role="hg-cmd">hg remove</command> and 17.424 + <command role="hg-cmd">hg copy</command>, you can tell Mercurial 17.425 + about a rename after the fact using the <option 17.426 + role="hg-opt-rename">--after</option> option. In most other 17.427 + respects, the behaviour of the <command role="hg-cmd">hg 17.428 + rename</command> command, and the options it accepts, are 17.429 + similar to the <command role="hg-cmd">hg copy</command> 17.430 + command.</para> 17.431 + 17.432 + <sect2> 17.433 + <title>Renaming files and merging changes</title> 17.434 + 17.435 + <para id="x_1d7">Since Mercurial's rename is implemented as 17.436 + copy-and-remove, the same propagation of changes happens when 17.437 + you merge after a rename as after a copy.</para> 17.438 + 17.439 + <para id="x_1d8">If I modify a file, and you rename it to a new name, and 17.440 + then we merge our respective changes, my modifications to the 17.441 + file under its original name will be propagated into the file 17.442 + under its new name. (This is something you might expect to 17.443 + <quote>simply work,</quote> but not all revision control 17.444 + systems actually do this.)</para> 17.445 + 17.446 + <para id="x_1d9">Whereas having changes follow a copy is a feature where 17.447 + you can perhaps nod and say <quote>yes, that might be 17.448 + useful,</quote> it should be clear that having them follow a 17.449 + rename is definitely important. Without this facility, it 17.450 + would simply be too easy for changes to become orphaned when 17.451 + files are renamed.</para> 17.452 + 17.453 + </sect2> 17.454 + <sect2> 17.455 + <title>Divergent renames and merging</title> 17.456 + 17.457 + <para id="x_1da">The case of diverging names occurs when two developers 17.458 + start with a file&emdash;let's call it 17.459 + <filename>foo</filename>&emdash;in their respective 17.460 + repositories.</para> 17.461 + 17.462 + &interaction.rename.divergent.clone; 17.463 + 17.464 + <para id="x_1db">Anne renames the file to <filename>bar</filename>.</para> 17.465 + 17.466 + &interaction.rename.divergent.rename.anne; 17.467 + 17.468 + <para id="x_1dc">Meanwhile, Bob renames it to 17.469 + <filename>quux</filename>.</para> 17.470 + 17.471 + &interaction.rename.divergent.rename.bob; 17.472 + 17.473 + <para id="x_1dd">I like to think of this as a conflict because each 17.474 + developer has expressed different intentions about what the 17.475 + file ought to be named.</para> 17.476 + 17.477 + <para id="x_1de">What do you think should happen when they merge their 17.478 + work? Mercurial's actual behaviour is that it always preserves 17.479 + <emphasis>both</emphasis> names when it merges changesets that 17.480 + contain divergent renames.</para> 17.481 + 17.482 + &interaction.rename.divergent.merge; 17.483 + 17.484 + <para id="x_1df">Notice that Mercurial does warn about the divergent 17.485 + renames, but it leaves it up to you to do something about the 17.486 + divergence after the merge.</para> 17.487 + 17.488 + </sect2> 17.489 + <sect2> 17.490 + <title>Convergent renames and merging</title> 17.491 + 17.492 + <para id="x_1e0">Another kind of rename conflict occurs when two people 17.493 + choose to rename different <emphasis>source</emphasis> files 17.494 + to the same <emphasis>destination</emphasis>. In this case, 17.495 + Mercurial runs its normal merge machinery, and lets you guide 17.496 + it to a suitable resolution.</para> 17.497 + 17.498 + </sect2> 17.499 + <sect2> 17.500 + <title>Other name-related corner cases</title> 17.501 + 17.502 + <para id="x_1e1">Mercurial has a longstanding bug in which it fails to 17.503 + handle a merge where one side has a file with a given name, 17.504 + while another has a directory with the same name. This is 17.505 + documented as <ulink role="hg-bug" 17.506 + url="http://www.selenic.com/mercurial/bts/issue29">issue 17.507 + 29</ulink>.</para> 17.508 + 17.509 + &interaction.issue29.go; 17.510 + 17.511 + </sect2> 17.512 + </sect1> 17.513 + <sect1> 17.514 + <title>Recovering from mistakes</title> 17.515 + 17.516 + <para id="x_1e2">Mercurial has some useful commands that will help you to 17.517 + recover from some common mistakes.</para> 17.518 + 17.519 + <para id="x_1e3">The <command role="hg-cmd">hg revert</command> command lets 17.520 + you undo changes that you have made to your working directory. 17.521 + For example, if you <command role="hg-cmd">hg add</command> a 17.522 + file by accident, just run <command role="hg-cmd">hg 17.523 + revert</command> with the name of the file you added, and 17.524 + while the file won't be touched in any way, it won't be tracked 17.525 + for adding by Mercurial any longer, either. You can also use 17.526 + <command role="hg-cmd">hg revert</command> to get rid of 17.527 + erroneous changes to a file.</para> 17.528 + 17.529 + <para id="x_1e4">It's useful to remember that the <command role="hg-cmd">hg 17.530 + revert</command> command is useful for changes that you have 17.531 + not yet committed. Once you've committed a change, if you 17.532 + decide it was a mistake, you can still do something about it, 17.533 + though your options may be more limited.</para> 17.534 + 17.535 + <para id="x_1e5">For more information about the <command role="hg-cmd">hg 17.536 + revert</command> command, and details about how to deal with 17.537 + changes you have already committed, see chapter <xref 17.538 + linkend="chap.undo"/>.</para> 17.539 + 17.540 + </sect1> 17.541 +</chapter> 17.542 + 17.543 +<!-- 17.544 +local variables: 17.545 +sgml-parent-document: ("00book.xml" "book" "chapter") 17.546 +end: 17.547 +-->
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/en/ch05-collab.xml Fri Mar 20 16:43:35 2009 +0800 18.3 @@ -0,0 +1,1437 @@ 18.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 18.5 + 18.6 +<chapter id="cha.collab"> 18.7 + <?dbhtml filename="collaborating-with-other-people.html"?> 18.8 + <title>Collaborating with other people</title> 18.9 + 18.10 + <para>As a completely decentralised tool, Mercurial doesn't impose 18.11 + any policy on how people ought to work with each other. However, 18.12 + if you're new to distributed revision control, it helps to have 18.13 + some tools and examples in mind when you're thinking about 18.14 + possible workflow models.</para> 18.15 + 18.16 + <sect1> 18.17 + <title>Mercurial's web interface</title> 18.18 + 18.19 + <para>Mercurial has a powerful web interface that provides several 18.20 + useful capabilities.</para> 18.21 + 18.22 + <para>For interactive use, the web interface lets you browse a 18.23 + single repository or a collection of repositories. You can view 18.24 + the history of a repository, examine each change (comments and 18.25 + diffs), and view the contents of each directory and file.</para> 18.26 + 18.27 + <para>Also for human consumption, the web interface provides an 18.28 + RSS feed of the changes in a repository. This lets you 18.29 + <quote>subscribe</quote> to a repository using your favourite 18.30 + feed reader, and be automatically notified of activity in that 18.31 + repository as soon as it happens. I find this capability much 18.32 + more convenient than the model of subscribing to a mailing list 18.33 + to which notifications are sent, as it requires no additional 18.34 + configuration on the part of whoever is serving the 18.35 + repository.</para> 18.36 + 18.37 + <para>The web interface also lets remote users clone a repository, 18.38 + pull changes from it, and (when the server is configured to 18.39 + permit it) push changes back to it. Mercurial's HTTP tunneling 18.40 + protocol aggressively compresses data, so that it works 18.41 + efficiently even over low-bandwidth network connections.</para> 18.42 + 18.43 + <para>The easiest way to get started with the web interface is to 18.44 + use your web browser to visit an existing repository, such as 18.45 + the master Mercurial repository at <ulink 18.46 + url="http://www.selenic.com/repo/hg?style=gitweb">http://www.selenic.com/repo/hg?style=gitweb</ulink>.</para> 18.47 + 18.48 + <para>If you're interested in providing a web interface to your 18.49 + own repositories, Mercurial provides two ways to do this. The 18.50 + first is using the <command role="hg-cmd">hg serve</command> 18.51 + command, which is best suited to short-term 18.52 + <quote>lightweight</quote> serving. See section <xref 18.53 + linkend="sec.collab.serve"/> below for details of how to use 18.54 + this command. If you have a long-lived repository that you'd 18.55 + like to make permanently available, Mercurial has built-in 18.56 + support for the CGI (Common Gateway Interface) standard, which 18.57 + all common web servers support. See section <xref 18.58 + linkend="sec.collab.cgi"/> for details of CGI 18.59 + configuration.</para> 18.60 + 18.61 + </sect1> 18.62 + <sect1> 18.63 + <title>Collaboration models</title> 18.64 + 18.65 + <para>With a suitably flexible tool, making decisions about 18.66 + workflow is much more of a social engineering challenge than a 18.67 + technical one. Mercurial imposes few limitations on how you can 18.68 + structure the flow of work in a project, so it's up to you and 18.69 + your group to set up and live with a model that matches your own 18.70 + particular needs.</para> 18.71 + 18.72 + <sect2> 18.73 + <title>Factors to keep in mind</title> 18.74 + 18.75 + <para>The most important aspect of any model that you must keep 18.76 + in mind is how well it matches the needs and capabilities of 18.77 + the people who will be using it. This might seem 18.78 + self-evident; even so, you still can't afford to forget it for 18.79 + a moment.</para> 18.80 + 18.81 + <para>I once put together a workflow model that seemed to make 18.82 + perfect sense to me, but that caused a considerable amount of 18.83 + consternation and strife within my development team. In spite 18.84 + of my attempts to explain why we needed a complex set of 18.85 + branches, and how changes ought to flow between them, a few 18.86 + team members revolted. Even though they were smart people, 18.87 + they didn't want to pay attention to the constraints we were 18.88 + operating under, or face the consequences of those constraints 18.89 + in the details of the model that I was advocating.</para> 18.90 + 18.91 + <para>Don't sweep foreseeable social or technical problems under 18.92 + the rug. Whatever scheme you put into effect, you should plan 18.93 + for mistakes and problem scenarios. Consider adding automated 18.94 + machinery to prevent, or quickly recover from, trouble that 18.95 + you can anticipate. As an example, if you intend to have a 18.96 + branch with not-for-release changes in it, you'd do well to 18.97 + think early about the possibility that someone might 18.98 + accidentally merge those changes into a release branch. You 18.99 + could avoid this particular problem by writing a hook that 18.100 + prevents changes from being merged from an inappropriate 18.101 + branch.</para> 18.102 + 18.103 + </sect2> 18.104 + <sect2> 18.105 + <title>Informal anarchy</title> 18.106 + 18.107 + <para>I wouldn't suggest an <quote>anything goes</quote> 18.108 + approach as something sustainable, but it's a model that's 18.109 + easy to grasp, and it works perfectly well in a few unusual 18.110 + situations.</para> 18.111 + 18.112 + <para>As one example, many projects have a loose-knit group of 18.113 + collaborators who rarely physically meet each other. Some 18.114 + groups like to overcome the isolation of working at a distance 18.115 + by organising occasional <quote>sprints</quote>. In a sprint, 18.116 + a number of people get together in a single location (a 18.117 + company's conference room, a hotel meeting room, that kind of 18.118 + place) and spend several days more or less locked in there, 18.119 + hacking intensely on a handful of projects.</para> 18.120 + 18.121 + <para>A sprint is the perfect place to use the <command 18.122 + role="hg-cmd">hg serve</command> command, since <command 18.123 + role="hg-cmd">hg serve</command> does not require any fancy 18.124 + server infrastructure. You can get started with <command 18.125 + role="hg-cmd">hg serve</command> in moments, by reading 18.126 + section <xref linkend="sec.collab.serve"/> below. Then simply 18.127 + tell 18.128 + the person next to you that you're running a server, send the 18.129 + URL to them in an instant message, and you immediately have a 18.130 + quick-turnaround way to work together. They can type your URL 18.131 + into their web browser and quickly review your changes; or 18.132 + they can pull a bugfix from you and verify it; or they can 18.133 + clone a branch containing a new feature and try it out.</para> 18.134 + 18.135 + <para>The charm, and the problem, with doing things in an ad hoc 18.136 + fashion like this is that only people who know about your 18.137 + changes, and where they are, can see them. Such an informal 18.138 + approach simply doesn't scale beyond a handful people, because 18.139 + each individual needs to know about $n$ different repositories 18.140 + to pull from.</para> 18.141 + 18.142 + </sect2> 18.143 + <sect2> 18.144 + <title>A single central repository</title> 18.145 + 18.146 + <para>For smaller projects migrating from a centralised revision 18.147 + control tool, perhaps the easiest way to get started is to 18.148 + have changes flow through a single shared central repository. 18.149 + This is also the most common <quote>building block</quote> for 18.150 + more ambitious workflow schemes.</para> 18.151 + 18.152 + <para>Contributors start by cloning a copy of this repository. 18.153 + They can pull changes from it whenever they need to, and some 18.154 + (perhaps all) developers have permission to push a change back 18.155 + when they're ready for other people to see it.</para> 18.156 + 18.157 + <para>Under this model, it can still often make sense for people 18.158 + to pull changes directly from each other, without going 18.159 + through the central repository. Consider a case in which I 18.160 + have a tentative bug fix, but I am worried that if I were to 18.161 + publish it to the central repository, it might subsequently 18.162 + break everyone else's trees as they pull it. To reduce the 18.163 + potential for damage, I can ask you to clone my repository 18.164 + into a temporary repository of your own and test it. This 18.165 + lets us put off publishing the potentially unsafe change until 18.166 + it has had a little testing.</para> 18.167 + 18.168 + <para>In this kind of scenario, people usually use the 18.169 + <command>ssh</command> protocol to securely push changes to 18.170 + the central repository, as documented in section <xref 18.171 + linkend="sec.collab.ssh"/>. It's also 18.172 + usual to publish a read-only copy of the repository over HTTP 18.173 + using CGI, as in section <xref linkend="sec.collab.cgi"/>. 18.174 + Publishing over HTTP 18.175 + satisfies the needs of people who don't have push access, and 18.176 + those who want to use web browsers to browse the repository's 18.177 + history.</para> 18.178 + 18.179 + </sect2> 18.180 + <sect2> 18.181 + <title>Working with multiple branches</title> 18.182 + 18.183 + <para>Projects of any significant size naturally tend to make 18.184 + progress on several fronts simultaneously. In the case of 18.185 + software, it's common for a project to go through periodic 18.186 + official releases. A release might then go into 18.187 + <quote>maintenance mode</quote> for a while after its first 18.188 + publication; maintenance releases tend to contain only bug 18.189 + fixes, not new features. In parallel with these maintenance 18.190 + releases, one or more future releases may be under 18.191 + development. People normally use the word 18.192 + <quote>branch</quote> to refer to one of these many slightly 18.193 + different directions in which development is 18.194 + proceeding.</para> 18.195 + 18.196 + <para>Mercurial is particularly well suited to managing a number 18.197 + of simultaneous, but not identical, branches. Each 18.198 + <quote>development direction</quote> can live in its own 18.199 + central repository, and you can merge changes from one to 18.200 + another as the need arises. Because repositories are 18.201 + independent of each other, unstable changes in a development 18.202 + branch will never affect a stable branch unless someone 18.203 + explicitly merges those changes in.</para> 18.204 + 18.205 + <para>Here's an example of how this can work in practice. Let's 18.206 + say you have one <quote>main branch</quote> on a central 18.207 + server.</para> 18.208 + 18.209 + &interaction.branching.init; 18.210 + 18.211 + <para>People clone it, make changes locally, test them, and push 18.212 + them back.</para> 18.213 + 18.214 + <para>Once the main branch reaches a release milestone, you can 18.215 + use the <command role="hg-cmd">hg tag</command> command to 18.216 + give a permanent name to the milestone revision.</para> 18.217 + 18.218 + &interaction.branching.tag; 18.219 + 18.220 + <para>Let's say some ongoing 18.221 + development occurs on the main branch.</para> 18.222 + 18.223 + &interaction.branching.main; 18.224 + 18.225 + <para>Using the tag that was recorded at the milestone, people 18.226 + who clone that repository at any time in the future can use 18.227 + <command role="hg-cmd">hg update</command> to get a copy of 18.228 + the working directory exactly as it was when that tagged 18.229 + revision was committed.</para> 18.230 + 18.231 + &interaction.branching.update; 18.232 + 18.233 + <para>In addition, immediately after the main branch is tagged, 18.234 + someone can then clone the main branch on the server to a new 18.235 + <quote>stable</quote> branch, also on the server.</para> 18.236 + 18.237 + &interaction.branching.clone; 18.238 + 18.239 + <para>Someone who needs to make a change to the stable branch 18.240 + can then clone <emphasis>that</emphasis> repository, make 18.241 + their changes, commit, and push their changes back there.</para> 18.242 + 18.243 + &interaction.branching.stable; 18.244 + 18.245 + <para>Because Mercurial repositories are independent, and 18.246 + Mercurial doesn't move changes around automatically, the 18.247 + stable and main branches are <emphasis>isolated</emphasis> 18.248 + from each other. The changes that you made on the main branch 18.249 + don't <quote>leak</quote> to the stable branch, and vice 18.250 + versa.</para> 18.251 + 18.252 + <para>You'll often want all of your bugfixes on the stable 18.253 + branch to show up on the main branch, too. Rather than 18.254 + rewrite a bugfix on the main branch, you can simply pull and 18.255 + merge changes from the stable to the main branch, and 18.256 + Mercurial will bring those bugfixes in for you.</para> 18.257 + 18.258 + &interaction.branching.merge; 18.259 + 18.260 + <para>The main branch will still contain changes that are not on 18.261 + the stable branch, but it will also contain all of the 18.262 + bugfixes from the stable branch. The stable branch remains 18.263 + unaffected by these changes.</para> 18.264 + 18.265 + </sect2> 18.266 + <sect2> 18.267 + <title>Feature branches</title> 18.268 + 18.269 + <para>For larger projects, an effective way to manage change is 18.270 + to break up a team into smaller groups. Each group has a 18.271 + shared branch of its own, cloned from a single 18.272 + <quote>master</quote> branch used by the entire project. 18.273 + People working on an individual branch are typically quite 18.274 + isolated from developments on other branches.</para> 18.275 + 18.276 + <informalfigure id="fig.collab.feature-branches"> 18.277 + <mediaobject> 18.278 + <imageobject><imagedata fileref="images/feature-branches.png"/> 18.279 + </imageobject> 18.280 + <textobject><phrase>XXX add text</phrase></textobject> 18.281 + <caption><para id="fig.collab.feature-branches.caption">Feature 18.282 + branches</para></caption> 18.283 + </mediaobject> 18.284 + </informalfigure> 18.285 + 18.286 + <para>When a particular feature is deemed to be in suitable 18.287 + shape, someone on that feature team pulls and merges from the 18.288 + master branch into the feature branch, then pushes back up to 18.289 + the master branch.</para> 18.290 + 18.291 + </sect2> 18.292 + <sect2> 18.293 + <title>The release train</title> 18.294 + 18.295 + <para>Some projects are organised on a <quote>train</quote> 18.296 + basis: a release is scheduled to happen every few months, and 18.297 + whatever features are ready when the <quote>train</quote> is 18.298 + ready to leave are allowed in.</para> 18.299 + 18.300 + <para>This model resembles working with feature branches. The 18.301 + difference is that when a feature branch misses a train, 18.302 + someone on the feature team pulls and merges the changes that 18.303 + went out on that train release into the feature branch, and 18.304 + the team continues its work on top of that release so that 18.305 + their feature can make the next release.</para> 18.306 + 18.307 + </sect2> 18.308 + <sect2> 18.309 + <title>The Linux kernel model</title> 18.310 + 18.311 + <para>The development of the Linux kernel has a shallow 18.312 + hierarchical structure, surrounded by a cloud of apparent 18.313 + chaos. Because most Linux developers use 18.314 + <command>git</command>, a distributed revision control tool 18.315 + with capabilities similar to Mercurial, it's useful to 18.316 + describe the way work flows in that environment; if you like 18.317 + the ideas, the approach translates well across tools.</para> 18.318 + 18.319 + <para>At the center of the community sits Linus Torvalds, the 18.320 + creator of Linux. He publishes a single source repository 18.321 + that is considered the <quote>authoritative</quote> current 18.322 + tree by the entire developer community. Anyone can clone 18.323 + Linus's tree, but he is very choosy about whose trees he pulls 18.324 + from.</para> 18.325 + 18.326 + <para>Linus has a number of <quote>trusted lieutenants</quote>. 18.327 + As a general rule, he pulls whatever changes they publish, in 18.328 + most cases without even reviewing those changes. Some of 18.329 + those lieutenants are generally agreed to be 18.330 + <quote>maintainers</quote>, responsible for specific 18.331 + subsystems within the kernel. If a random kernel hacker wants 18.332 + to make a change to a subsystem that they want to end up in 18.333 + Linus's tree, they must find out who the subsystem's 18.334 + maintainer is, and ask that maintainer to take their change. 18.335 + If the maintainer reviews their changes and agrees to take 18.336 + them, they'll pass them along to Linus in due course.</para> 18.337 + 18.338 + <para>Individual lieutenants have their own approaches to 18.339 + reviewing, accepting, and publishing changes; and for deciding 18.340 + when to feed them to Linus. In addition, there are several 18.341 + well known branches that people use for different purposes. 18.342 + For example, a few people maintain <quote>stable</quote> 18.343 + repositories of older versions of the kernel, to which they 18.344 + apply critical fixes as needed. Some maintainers publish 18.345 + multiple trees: one for experimental changes; one for changes 18.346 + that they are about to feed upstream; and so on. Others just 18.347 + publish a single tree.</para> 18.348 + 18.349 + <para>This model has two notable features. The first is that 18.350 + it's <quote>pull only</quote>. You have to ask, convince, or 18.351 + beg another developer to take a change from you, because there 18.352 + are almost no trees to which more than one person can push, 18.353 + and there's no way to push changes into a tree that someone 18.354 + else controls.</para> 18.355 + 18.356 + <para>The second is that it's based on reputation and acclaim. 18.357 + If you're an unknown, Linus will probably ignore changes from 18.358 + you without even responding. But a subsystem maintainer will 18.359 + probably review them, and will likely take them if they pass 18.360 + their criteria for suitability. The more <quote>good</quote> 18.361 + changes you contribute to a maintainer, the more likely they 18.362 + are to trust your judgment and accept your changes. If you're 18.363 + well-known and maintain a long-lived branch for something 18.364 + Linus hasn't yet accepted, people with similar interests may 18.365 + pull your changes regularly to keep up with your work.</para> 18.366 + 18.367 + <para>Reputation and acclaim don't necessarily cross subsystem 18.368 + or <quote>people</quote> boundaries. If you're a respected 18.369 + but specialised storage hacker, and you try to fix a 18.370 + networking bug, that change will receive a level of scrutiny 18.371 + from a network maintainer comparable to a change from a 18.372 + complete stranger.</para> 18.373 + 18.374 + <para>To people who come from more orderly project backgrounds, 18.375 + the comparatively chaotic Linux kernel development process 18.376 + often seems completely insane. It's subject to the whims of 18.377 + individuals; people make sweeping changes whenever they deem 18.378 + it appropriate; and the pace of development is astounding. 18.379 + And yet Linux is a highly successful, well-regarded piece of 18.380 + software.</para> 18.381 + 18.382 + </sect2> 18.383 + <sect2> 18.384 + <title>Pull-only versus shared-push collaboration</title> 18.385 + 18.386 + <para>A perpetual source of heat in the open source community is 18.387 + whether a development model in which people only ever pull 18.388 + changes from others is <quote>better than</quote> one in which 18.389 + multiple people can push changes to a shared 18.390 + repository.</para> 18.391 + 18.392 + <para>Typically, the backers of the shared-push model use tools 18.393 + that actively enforce this approach. If you're using a 18.394 + centralised revision control tool such as Subversion, there's 18.395 + no way to make a choice over which model you'll use: the tool 18.396 + gives you shared-push, and if you want to do anything else, 18.397 + you'll have to roll your own approach on top (such as applying 18.398 + a patch by hand).</para> 18.399 + 18.400 + <para>A good distributed revision control tool, such as 18.401 + Mercurial, will support both models. You and your 18.402 + collaborators can then structure how you work together based 18.403 + on your own needs and preferences, not on what contortions 18.404 + your tools force you into.</para> 18.405 + 18.406 + </sect2> 18.407 + <sect2> 18.408 + <title>Where collaboration meets branch management</title> 18.409 + 18.410 + <para>Once you and your team set up some shared repositories and 18.411 + start propagating changes back and forth between local and 18.412 + shared repos, you begin to face a related, but slightly 18.413 + different challenge: that of managing the multiple directions 18.414 + in which your team may be moving at once. Even though this 18.415 + subject is intimately related to how your team collaborates, 18.416 + it's dense enough to merit treatment of its own, in chapter 18.417 + <xref linkend="chap.branch"/>.</para> 18.418 + 18.419 + </sect2> 18.420 + </sect1> 18.421 + <sect1> 18.422 + <title>The technical side of sharing</title> 18.423 + 18.424 + <para>The remainder of this chapter is devoted to the question of 18.425 + serving data to your collaborators.</para> 18.426 + 18.427 + </sect1> 18.428 + <sect1 id="sec.collab.serve"> 18.429 + <title>Informal sharing with <command role="hg-cmd">hg 18.430 + serve</command></title> 18.431 + 18.432 + <para>Mercurial's <command role="hg-cmd">hg serve</command> 18.433 + command is wonderfully suited to small, tight-knit, and 18.434 + fast-paced group environments. It also provides a great way to 18.435 + get a feel for using Mercurial commands over a network.</para> 18.436 + 18.437 + <para>Run <command role="hg-cmd">hg serve</command> inside a 18.438 + repository, and in under a second it will bring up a specialised 18.439 + HTTP server; this will accept connections from any client, and 18.440 + serve up data for that repository until you terminate it. 18.441 + Anyone who knows the URL of the server you just started, and can 18.442 + talk to your computer over the network, can then use a web 18.443 + browser or Mercurial to read data from that repository. A URL 18.444 + for a <command role="hg-cmd">hg serve</command> instance running 18.445 + on a laptop is likely to look something like 18.446 + <literal>http://my-laptop.local:8000/</literal>.</para> 18.447 + 18.448 + <para>The <command role="hg-cmd">hg serve</command> command is 18.449 + <emphasis>not</emphasis> a general-purpose web server. It can do 18.450 + only two things:</para> 18.451 + <itemizedlist> 18.452 + <listitem><para>Allow people to browse the history of the 18.453 + repository it's serving, from their normal web 18.454 + browsers.</para> 18.455 + </listitem> 18.456 + <listitem><para>Speak Mercurial's wire protocol, so that people 18.457 + can <command role="hg-cmd">hg clone</command> or <command 18.458 + role="hg-cmd">hg pull</command> changes from that 18.459 + repository.</para> 18.460 + </listitem></itemizedlist> 18.461 + <para>In particular, <command role="hg-cmd">hg serve</command> 18.462 + won't allow remote users to <emphasis>modify</emphasis> your 18.463 + repository. It's intended for read-only use.</para> 18.464 + 18.465 + <para>If you're getting started with Mercurial, there's nothing to 18.466 + prevent you from using <command role="hg-cmd">hg serve</command> 18.467 + to serve up a repository on your own computer, then use commands 18.468 + like <command role="hg-cmd">hg clone</command>, <command 18.469 + role="hg-cmd">hg incoming</command>, and so on to talk to that 18.470 + server as if the repository was hosted remotely. This can help 18.471 + you to quickly get acquainted with using commands on 18.472 + network-hosted repositories.</para> 18.473 + 18.474 + <sect2> 18.475 + <title>A few things to keep in mind</title> 18.476 + 18.477 + <para>Because it provides unauthenticated read access to all 18.478 + clients, you should only use <command role="hg-cmd">hg 18.479 + serve</command> in an environment where you either don't 18.480 + care, or have complete control over, who can access your 18.481 + network and pull data from your repository.</para> 18.482 + 18.483 + <para>The <command role="hg-cmd">hg serve</command> command 18.484 + knows nothing about any firewall software you might have 18.485 + installed on your system or network. It cannot detect or 18.486 + control your firewall software. If other people are unable to 18.487 + talk to a running <command role="hg-cmd">hg serve</command> 18.488 + instance, the second thing you should do 18.489 + (<emphasis>after</emphasis> you make sure that they're using 18.490 + the correct URL) is check your firewall configuration.</para> 18.491 + 18.492 + <para>By default, <command role="hg-cmd">hg serve</command> 18.493 + listens for incoming connections on port 8000. If another 18.494 + process is already listening on the port you want to use, you 18.495 + can specify a different port to listen on using the <option 18.496 + role="hg-opt-serve">-p</option> option.</para> 18.497 + 18.498 + <para>Normally, when <command role="hg-cmd">hg serve</command> 18.499 + starts, it prints no output, which can be a bit unnerving. If 18.500 + you'd like to confirm that it is indeed running correctly, and 18.501 + find out what URL you should send to your collaborators, start 18.502 + it with the <option role="hg-opt-global">-v</option> 18.503 + option.</para> 18.504 + 18.505 + </sect2> 18.506 + </sect1> 18.507 + <sect1 id="sec.collab.ssh"> 18.508 + <title>Using the Secure Shell (ssh) protocol</title> 18.509 + 18.510 + <para>You can pull and push changes securely over a network 18.511 + connection using the Secure Shell (<literal>ssh</literal>) 18.512 + protocol. To use this successfully, you may have to do a little 18.513 + bit of configuration on the client or server sides.</para> 18.514 + 18.515 + <para>If you're not familiar with ssh, it's a network protocol 18.516 + that lets you securely communicate with another computer. To 18.517 + use it with Mercurial, you'll be setting up one or more user 18.518 + accounts on a server so that remote users can log in and execute 18.519 + commands.</para> 18.520 + 18.521 + <para>(If you <emphasis>are</emphasis> familiar with ssh, you'll 18.522 + probably find some of the material that follows to be elementary 18.523 + in nature.)</para> 18.524 + 18.525 + <sect2> 18.526 + <title>How to read and write ssh URLs</title> 18.527 + 18.528 + <para>An ssh URL tends to look like this:</para> 18.529 + <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting> 18.530 + <orderedlist> 18.531 + <listitem><para>The <quote><literal>ssh://</literal></quote> 18.532 + part tells Mercurial to use the ssh protocol.</para> 18.533 + </listitem> 18.534 + <listitem><para>The <quote><literal>bos@</literal></quote> 18.535 + component indicates what username to log into the server 18.536 + as. You can leave this out if the remote username is the 18.537 + same as your local username.</para> 18.538 + </listitem> 18.539 + <listitem><para>The 18.540 + <quote><literal>hg.serpentine.com</literal></quote> gives 18.541 + the hostname of the server to log into.</para> 18.542 + </listitem> 18.543 + <listitem><para>The <quote>:22</quote> identifies the port 18.544 + number to connect to the server on. The default port is 18.545 + 22, so you only need to specify a colon and port number if 18.546 + you're <emphasis>not</emphasis> using port 22.</para> 18.547 + </listitem> 18.548 + <listitem><para>The remainder of the URL is the local path to 18.549 + the repository on the server.</para> 18.550 + </listitem></orderedlist> 18.551 + 18.552 + <para>There's plenty of scope for confusion with the path 18.553 + component of ssh URLs, as there is no standard way for tools 18.554 + to interpret it. Some programs behave differently than others 18.555 + when dealing with these paths. This isn't an ideal situation, 18.556 + but it's unlikely to change. Please read the following 18.557 + paragraphs carefully.</para> 18.558 + 18.559 + <para>Mercurial treats the path to a repository on the server as 18.560 + relative to the remote user's home directory. For example, if 18.561 + user <literal>foo</literal> on the server has a home directory 18.562 + of <filename class="directory">/home/foo</filename>, then an 18.563 + ssh URL that contains a path component of <filename 18.564 + class="directory">bar</filename> <emphasis>really</emphasis> 18.565 + refers to the directory <filename 18.566 + class="directory">/home/foo/bar</filename>.</para> 18.567 + 18.568 + <para>If you want to specify a path relative to another user's 18.569 + home directory, you can use a path that starts with a tilde 18.570 + character followed by the user's name (let's call them 18.571 + <literal>otheruser</literal>), like this.</para> 18.572 + <programlisting>ssh://server/~otheruser/hg/repo</programlisting> 18.573 + 18.574 + <para>And if you really want to specify an 18.575 + <emphasis>absolute</emphasis> path on the server, begin the 18.576 + path component with two slashes, as in this example.</para> 18.577 + <programlisting>ssh://server//absolute/path</programlisting> 18.578 + 18.579 + </sect2> 18.580 + <sect2> 18.581 + <title>Finding an ssh client for your system</title> 18.582 + 18.583 + <para>Almost every Unix-like system comes with OpenSSH 18.584 + preinstalled. If you're using such a system, run 18.585 + <literal>which ssh</literal> to find out if the 18.586 + <command>ssh</command> command is installed (it's usually in 18.587 + <filename class="directory">/usr/bin</filename>). In the 18.588 + unlikely event that it isn't present, take a look at your 18.589 + system documentation to figure out how to install it.</para> 18.590 + 18.591 + <para>On Windows, you'll first need to download a suitable ssh 18.592 + client. There are two alternatives.</para> 18.593 + <itemizedlist> 18.594 + <listitem><para>Simon Tatham's excellent PuTTY package 18.595 + <citation>web:putty</citation> provides a complete suite 18.596 + of ssh client commands.</para> 18.597 + </listitem> 18.598 + <listitem><para>If you have a high tolerance for pain, you can 18.599 + use the Cygwin port of OpenSSH.</para> 18.600 + </listitem></itemizedlist> 18.601 + <para>In either case, you'll need to edit your <filename 18.602 + role="special">hg.ini</filename> file to 18.603 + tell Mercurial where to find the actual client command. For 18.604 + example, if you're using PuTTY, you'll need to use the 18.605 + <command>plink</command> command as a command-line ssh 18.606 + client.</para> 18.607 + <programlisting>[ui] 18.608 +ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"</programlisting> 18.609 + 18.610 + <note> 18.611 + <para> The path to <command>plink</command> shouldn't contain 18.612 + any whitespace characters, or Mercurial may not be able to 18.613 + run it correctly (so putting it in <filename 18.614 + class="directory">C:\Program Files</filename> is probably 18.615 + not a good idea).</para> 18.616 + </note> 18.617 + 18.618 + </sect2> 18.619 + <sect2> 18.620 + <title>Generating a key pair</title> 18.621 + 18.622 + <para>To avoid the need to repetitively type a password every 18.623 + time you need to use your ssh client, I recommend generating a 18.624 + key pair. On a Unix-like system, the 18.625 + <command>ssh-keygen</command> command will do the trick. On 18.626 + Windows, if you're using PuTTY, the 18.627 + <command>puttygen</command> command is what you'll 18.628 + need.</para> 18.629 + 18.630 + <para>When you generate a key pair, it's usually 18.631 + <emphasis>highly</emphasis> advisable to protect it with a 18.632 + passphrase. (The only time that you might not want to do this 18.633 + is when you're using the ssh protocol for automated tasks on a 18.634 + secure network.)</para> 18.635 + 18.636 + <para>Simply generating a key pair isn't enough, however. 18.637 + You'll need to add the public key to the set of authorised 18.638 + keys for whatever user you're logging in remotely as. For 18.639 + servers using OpenSSH (the vast majority), this will mean 18.640 + adding the public key to a list in a file called <filename 18.641 + role="special">authorized_keys</filename> in their <filename 18.642 + role="special" class="directory">.ssh</filename> 18.643 + directory.</para> 18.644 + 18.645 + <para>On a Unix-like system, your public key will have a 18.646 + <filename>.pub</filename> extension. If you're using 18.647 + <command>puttygen</command> on Windows, you can save the 18.648 + public key to a file of your choosing, or paste it from the 18.649 + window it's displayed in straight into the <filename 18.650 + role="special">authorized_keys</filename> file.</para> 18.651 + 18.652 + </sect2> 18.653 + <sect2> 18.654 + <title>Using an authentication agent</title> 18.655 + 18.656 + <para>An authentication agent is a daemon that stores 18.657 + passphrases in memory (so it will forget passphrases if you 18.658 + log out and log back in again). An ssh client will notice if 18.659 + it's running, and query it for a passphrase. If there's no 18.660 + authentication agent running, or the agent doesn't store the 18.661 + necessary passphrase, you'll have to type your passphrase 18.662 + every time Mercurial tries to communicate with a server on 18.663 + your behalf (e.g. whenever you pull or push changes).</para> 18.664 + 18.665 + <para>The downside of storing passphrases in an agent is that 18.666 + it's possible for a well-prepared attacker to recover the 18.667 + plain text of your passphrases, in some cases even if your 18.668 + system has been power-cycled. You should make your own 18.669 + judgment as to whether this is an acceptable risk. It 18.670 + certainly saves a lot of repeated typing.</para> 18.671 + 18.672 + <para>On Unix-like systems, the agent is called 18.673 + <command>ssh-agent</command>, and it's often run automatically 18.674 + for you when you log in. You'll need to use the 18.675 + <command>ssh-add</command> command to add passphrases to the 18.676 + agent's store. On Windows, if you're using PuTTY, the 18.677 + <command>pageant</command> command acts as the agent. It adds 18.678 + an icon to your system tray that will let you manage stored 18.679 + passphrases.</para> 18.680 + 18.681 + </sect2> 18.682 + <sect2> 18.683 + <title>Configuring the server side properly</title> 18.684 + 18.685 + <para>Because ssh can be fiddly to set up if you're new to it, 18.686 + there's a variety of things that can go wrong. Add Mercurial 18.687 + on top, and there's plenty more scope for head-scratching. 18.688 + Most of these potential problems occur on the server side, not 18.689 + the client side. The good news is that once you've gotten a 18.690 + configuration working, it will usually continue to work 18.691 + indefinitely.</para> 18.692 + 18.693 + <para>Before you try using Mercurial to talk to an ssh server, 18.694 + it's best to make sure that you can use the normal 18.695 + <command>ssh</command> or <command>putty</command> command to 18.696 + talk to the server first. If you run into problems with using 18.697 + these commands directly, Mercurial surely won't work. Worse, 18.698 + it will obscure the underlying problem. Any time you want to 18.699 + debug ssh-related Mercurial problems, you should drop back to 18.700 + making sure that plain ssh client commands work first, 18.701 + <emphasis>before</emphasis> you worry about whether there's a 18.702 + problem with Mercurial.</para> 18.703 + 18.704 + <para>The first thing to be sure of on the server side is that 18.705 + you can actually log in from another machine at all. If you 18.706 + can't use <command>ssh</command> or <command>putty</command> 18.707 + to log in, the error message you get may give you a few hints 18.708 + as to what's wrong. The most common problems are as 18.709 + follows.</para> 18.710 + <itemizedlist> 18.711 + <listitem><para>If you get a <quote>connection refused</quote> 18.712 + error, either there isn't an SSH daemon running on the 18.713 + server at all, or it's inaccessible due to firewall 18.714 + configuration.</para> 18.715 + </listitem> 18.716 + <listitem><para>If you get a <quote>no route to host</quote> 18.717 + error, you either have an incorrect address for the server 18.718 + or a seriously locked down firewall that won't admit its 18.719 + existence at all.</para> 18.720 + </listitem> 18.721 + <listitem><para>If you get a <quote>permission denied</quote> 18.722 + error, you may have mistyped the username on the server, 18.723 + or you could have mistyped your key's passphrase or the 18.724 + remote user's password.</para> 18.725 + </listitem></itemizedlist> 18.726 + <para>In summary, if you're having trouble talking to the 18.727 + server's ssh daemon, first make sure that one is running at 18.728 + all. On many systems it will be installed, but disabled, by 18.729 + default. Once you're done with this step, you should then 18.730 + check that the server's firewall is configured to allow 18.731 + incoming connections on the port the ssh daemon is listening 18.732 + on (usually 22). Don't worry about more exotic possibilities 18.733 + for misconfiguration until you've checked these two 18.734 + first.</para> 18.735 + 18.736 + <para>If you're using an authentication agent on the client side 18.737 + to store passphrases for your keys, you ought to be able to 18.738 + log into the server without being prompted for a passphrase or 18.739 + a password. If you're prompted for a passphrase, there are a 18.740 + few possible culprits.</para> 18.741 + <itemizedlist> 18.742 + <listitem><para>You might have forgotten to use 18.743 + <command>ssh-add</command> or <command>pageant</command> 18.744 + to store the passphrase.</para> 18.745 + </listitem> 18.746 + <listitem><para>You might have stored the passphrase for the 18.747 + wrong key.</para> 18.748 + </listitem></itemizedlist> 18.749 + <para>If you're being prompted for the remote user's password, 18.750 + there are another few possible problems to check.</para> 18.751 + <itemizedlist> 18.752 + <listitem><para>Either the user's home directory or their 18.753 + <filename role="special" class="directory">.ssh</filename> 18.754 + directory might have excessively liberal permissions. As 18.755 + a result, the ssh daemon will not trust or read their 18.756 + <filename role="special">authorized_keys</filename> file. 18.757 + For example, a group-writable home or <filename 18.758 + role="special" class="directory">.ssh</filename> 18.759 + directory will often cause this symptom.</para> 18.760 + </listitem> 18.761 + <listitem><para>The user's <filename 18.762 + role="special">authorized_keys</filename> file may have 18.763 + a problem. If anyone other than the user owns or can write 18.764 + to that file, the ssh daemon will not trust or read 18.765 + it.</para> 18.766 + </listitem></itemizedlist> 18.767 + 18.768 + <para>In the ideal world, you should be able to run the 18.769 + following command successfully, and it should print exactly 18.770 + one line of output, the current date and time.</para> 18.771 + <programlisting>ssh myserver date</programlisting> 18.772 + 18.773 + <para>If, on your server, you have login scripts that print 18.774 + banners or other junk even when running non-interactive 18.775 + commands like this, you should fix them before you continue, 18.776 + so that they only print output if they're run interactively. 18.777 + Otherwise these banners will at least clutter up Mercurial's 18.778 + output. Worse, they could potentially cause problems with 18.779 + running Mercurial commands remotely. Mercurial makes tries to 18.780 + detect and ignore banners in non-interactive 18.781 + <command>ssh</command> sessions, but it is not foolproof. (If 18.782 + you're editing your login scripts on your server, the usual 18.783 + way to see if a login script is running in an interactive 18.784 + shell is to check the return code from the command 18.785 + <literal>tty -s</literal>.)</para> 18.786 + 18.787 + <para>Once you've verified that plain old ssh is working with 18.788 + your server, the next step is to ensure that Mercurial runs on 18.789 + the server. The following command should run 18.790 + successfully:</para> 18.791 + 18.792 + <programlisting>ssh myserver hg version</programlisting> 18.793 + 18.794 + <para>If you see an error message instead of normal <command 18.795 + role="hg-cmd">hg version</command> output, this is usually 18.796 + because you haven't installed Mercurial to <filename 18.797 + class="directory">/usr/bin</filename>. Don't worry if this 18.798 + is the case; you don't need to do that. But you should check 18.799 + for a few possible problems.</para> 18.800 + <itemizedlist> 18.801 + <listitem><para>Is Mercurial really installed on the server at 18.802 + all? I know this sounds trivial, but it's worth 18.803 + checking!</para> 18.804 + </listitem> 18.805 + <listitem><para>Maybe your shell's search path (usually set 18.806 + via the <envar>PATH</envar> environment variable) is 18.807 + simply misconfigured.</para> 18.808 + </listitem> 18.809 + <listitem><para>Perhaps your <envar>PATH</envar> environment 18.810 + variable is only being set to point to the location of the 18.811 + <command>hg</command> executable if the login session is 18.812 + interactive. This can happen if you're setting the path 18.813 + in the wrong shell login script. See your shell's 18.814 + documentation for details.</para> 18.815 + </listitem> 18.816 + <listitem><para>The <envar>PYTHONPATH</envar> environment 18.817 + variable may need to contain the path to the Mercurial 18.818 + Python modules. It might not be set at all; it could be 18.819 + incorrect; or it may be set only if the login is 18.820 + interactive.</para> 18.821 + </listitem></itemizedlist> 18.822 + 18.823 + <para>If you can run <command role="hg-cmd">hg version</command> 18.824 + over an ssh connection, well done! You've got the server and 18.825 + client sorted out. You should now be able to use Mercurial to 18.826 + access repositories hosted by that username on that server. 18.827 + If you run into problems with Mercurial and ssh at this point, 18.828 + try using the <option role="hg-opt-global">--debug</option> 18.829 + option to get a clearer picture of what's going on.</para> 18.830 + 18.831 + </sect2> 18.832 + <sect2> 18.833 + <title>Using compression with ssh</title> 18.834 + 18.835 + <para>Mercurial does not compress data when it uses the ssh 18.836 + protocol, because the ssh protocol can transparently compress 18.837 + data. However, the default behaviour of ssh clients is 18.838 + <emphasis>not</emphasis> to request compression.</para> 18.839 + 18.840 + <para>Over any network other than a fast LAN (even a wireless 18.841 + network), using compression is likely to significantly speed 18.842 + up Mercurial's network operations. For example, over a WAN, 18.843 + someone measured compression as reducing the amount of time 18.844 + required to clone a particularly large repository from 51 18.845 + minutes to 17 minutes.</para> 18.846 + 18.847 + <para>Both <command>ssh</command> and <command>plink</command> 18.848 + accept a <option role="cmd-opt-ssh">-C</option> option which 18.849 + turns on compression. You can easily edit your <filename 18.850 + role="special">~/.hgrc</filename> to enable compression for 18.851 + all of Mercurial's uses of the ssh protocol.</para> 18.852 + <programlisting>[ui] 18.853 +ssh = ssh -C</programlisting> 18.854 + 18.855 + <para>If you use <command>ssh</command>, you can configure it to 18.856 + always use compression when talking to your server. To do 18.857 + this, edit your <filename 18.858 + role="special">.ssh/config</filename> file (which may not 18.859 + yet exist), as follows.</para> 18.860 + <programlisting>Host hg 18.861 + Compression yes 18.862 + HostName hg.example.com</programlisting> 18.863 + <para>This defines an alias, <literal>hg</literal>. When you 18.864 + use it on the <command>ssh</command> command line or in a 18.865 + Mercurial <literal>ssh</literal>-protocol URL, it will cause 18.866 + <command>ssh</command> to connect to 18.867 + <literal>hg.example.com</literal> and use compression. This 18.868 + gives you both a shorter name to type and compression, each of 18.869 + which is a good thing in its own right.</para> 18.870 + 18.871 + </sect2> 18.872 + </sect1> 18.873 + <sect1 id="sec.collab.cgi"> 18.874 + <title>Serving over HTTP using CGI</title> 18.875 + 18.876 + <para>Depending on how ambitious you are, configuring Mercurial's 18.877 + CGI interface can take anything from a few moments to several 18.878 + hours.</para> 18.879 + 18.880 + <para>We'll begin with the simplest of examples, and work our way 18.881 + towards a more complex configuration. Even for the most basic 18.882 + case, you're almost certainly going to need to read and modify 18.883 + your web server's configuration.</para> 18.884 + 18.885 + <note> 18.886 + <para> Configuring a web server is a complex, fiddly, and 18.887 + highly system-dependent activity. I can't possibly give you 18.888 + instructions that will cover anything like all of the cases 18.889 + you will encounter. Please use your discretion and judgment in 18.890 + following the sections below. Be prepared to make plenty of 18.891 + mistakes, and to spend a lot of time reading your server's 18.892 + error logs.</para> 18.893 + </note> 18.894 + 18.895 + <sect2> 18.896 + <title>Web server configuration checklist</title> 18.897 + 18.898 + <para>Before you continue, do take a few moments to check a few 18.899 + aspects of your system's setup.</para> 18.900 + 18.901 + <orderedlist> 18.902 + <listitem><para>Do you have a web server installed at all? 18.903 + Mac OS X ships with Apache, but many other systems may not 18.904 + have a web server installed.</para> 18.905 + </listitem> 18.906 + <listitem><para>If you have a web server installed, is it 18.907 + actually running? On most systems, even if one is 18.908 + present, it will be disabled by default.</para> 18.909 + </listitem> 18.910 + <listitem><para>Is your server configured to allow you to run 18.911 + CGI programs in the directory where you plan to do so? 18.912 + Most servers default to explicitly disabling the ability 18.913 + to run CGI programs.</para> 18.914 + </listitem></orderedlist> 18.915 + 18.916 + <para>If you don't have a web server installed, and don't have 18.917 + substantial experience configuring Apache, you should consider 18.918 + using the <literal>lighttpd</literal> web server instead of 18.919 + Apache. Apache has a well-deserved reputation for baroque and 18.920 + confusing configuration. While <literal>lighttpd</literal> is 18.921 + less capable in some ways than Apache, most of these 18.922 + capabilities are not relevant to serving Mercurial 18.923 + repositories. And <literal>lighttpd</literal> is undeniably 18.924 + <emphasis>much</emphasis> easier to get started with than 18.925 + Apache.</para> 18.926 + 18.927 + </sect2> 18.928 + <sect2> 18.929 + <title>Basic CGI configuration</title> 18.930 + 18.931 + <para>On Unix-like systems, it's common for users to have a 18.932 + subdirectory named something like <filename 18.933 + class="directory">public_html</filename> in their home 18.934 + directory, from which they can serve up web pages. A file 18.935 + named <filename>foo</filename> in this directory will be 18.936 + accessible at a URL of the form 18.937 + <literal>http://www.example.com/username/foo</literal>.</para> 18.938 + 18.939 + <para>To get started, find the <filename 18.940 + role="special">hgweb.cgi</filename> script that should be 18.941 + present in your Mercurial installation. If you can't quickly 18.942 + find a local copy on your system, simply download one from the 18.943 + master Mercurial repository at <ulink 18.944 + url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para> 18.945 + 18.946 + <para>You'll need to copy this script into your <filename 18.947 + class="directory">public_html</filename> directory, and 18.948 + ensure that it's executable.</para> 18.949 + <programlisting>cp .../hgweb.cgi ~/public_html 18.950 +chmod 755 ~/public_html/hgweb.cgi</programlisting> 18.951 + <para>The <literal>755</literal> argument to 18.952 + <command>chmod</command> is a little more general than just 18.953 + making the script executable: it ensures that the script is 18.954 + executable by anyone, and that <quote>group</quote> and 18.955 + <quote>other</quote> write permissions are 18.956 + <emphasis>not</emphasis> set. If you were to leave those 18.957 + write permissions enabled, Apache's <literal>suexec</literal> 18.958 + subsystem would likely refuse to execute the script. In fact, 18.959 + <literal>suexec</literal> also insists that the 18.960 + <emphasis>directory</emphasis> in which the script resides 18.961 + must not be writable by others.</para> 18.962 + <programlisting>chmod 755 ~/public_html</programlisting> 18.963 + 18.964 + <sect3 id="sec.collab.wtf"> 18.965 + <title>What could <emphasis>possibly</emphasis> go 18.966 + wrong?</title> 18.967 + 18.968 + <para>Once you've copied the CGI script into place, go into a 18.969 + web browser, and try to open the URL <ulink 18.970 + url="http://myhostname/ 18.971 + myuser/hgweb.cgi">http://myhostname/ 18.972 + myuser/hgweb.cgi</ulink>, <emphasis>but</emphasis> brace 18.973 + yourself for instant failure. There's a high probability 18.974 + that trying to visit this URL will fail, and there are many 18.975 + possible reasons for this. In fact, you're likely to 18.976 + stumble over almost every one of the possible errors below, 18.977 + so please read carefully. The following are all of the 18.978 + problems I ran into on a system running Fedora 7, with a 18.979 + fresh installation of Apache, and a user account that I 18.980 + created specially to perform this exercise.</para> 18.981 + 18.982 + <para>Your web server may have per-user directories disabled. 18.983 + If you're using Apache, search your config file for a 18.984 + <literal>UserDir</literal> directive. If there's none 18.985 + present, per-user directories will be disabled. If one 18.986 + exists, but its value is <literal>disabled</literal>, then 18.987 + per-user directories will be disabled. Otherwise, the 18.988 + string after <literal>UserDir</literal> gives the name of 18.989 + the subdirectory that Apache will look in under your home 18.990 + directory, for example <filename 18.991 + class="directory">public_html</filename>.</para> 18.992 + 18.993 + <para>Your file access permissions may be too restrictive. 18.994 + The web server must be able to traverse your home directory 18.995 + and directories under your <filename 18.996 + class="directory">public_html</filename> directory, and 18.997 + read files under the latter too. Here's a quick recipe to 18.998 + help you to make your permissions more appropriate.</para> 18.999 + <programlisting>chmod 755 ~ 18.1000 +find ~/public_html -type d -print0 | xargs -0r chmod 755 18.1001 +find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting> 18.1002 + 18.1003 + <para>The other possibility with permissions is that you might 18.1004 + get a completely empty window when you try to load the 18.1005 + script. In this case, it's likely that your access 18.1006 + permissions are <emphasis>too permissive</emphasis>. Apache's 18.1007 + <literal>suexec</literal> subsystem won't execute a script 18.1008 + that's group- or world-writable, for example.</para> 18.1009 + 18.1010 + <para>Your web server may be configured to disallow execution 18.1011 + of CGI programs in your per-user web directory. Here's 18.1012 + Apache's default per-user configuration from my Fedora 18.1013 + system.</para> 18.1014 + 18.1015 + <programlisting><![CDATA[&ch06-apache-config.lst;]]></programlisting> 18.1016 + 18.1017 + <para>If you find a similar-looking 18.1018 + <literal>Directory</literal> group in your Apache 18.1019 + configuration, the directive to look at inside it is 18.1020 + <literal>Options</literal>. Add <literal>ExecCGI</literal> 18.1021 + to the end of this list if it's missing, and restart the web 18.1022 + server.</para> 18.1023 + 18.1024 + <para>If you find that Apache serves you the text of the CGI 18.1025 + script instead of executing it, you may need to either 18.1026 + uncomment (if already present) or add a directive like 18.1027 + this.</para> 18.1028 + <programlisting>AddHandler cgi-script .cgi</programlisting> 18.1029 + 18.1030 + <para>The next possibility is that you might be served with a 18.1031 + colourful Python backtrace claiming that it can't import a 18.1032 + <literal>mercurial</literal>-related module. This is 18.1033 + actually progress! The server is now capable of executing 18.1034 + your CGI script. This error is only likely to occur if 18.1035 + you're running a private installation of Mercurial, instead 18.1036 + of a system-wide version. Remember that the web server runs 18.1037 + the CGI program without any of the environment variables 18.1038 + that you take for granted in an interactive session. If 18.1039 + this error happens to you, edit your copy of <filename 18.1040 + role="special">hgweb.cgi</filename> and follow the 18.1041 + directions inside it to correctly set your 18.1042 + <envar>PYTHONPATH</envar> environment variable.</para> 18.1043 + 18.1044 + <para>Finally, you are <emphasis>certain</emphasis> to by 18.1045 + served with another colourful Python backtrace: this one 18.1046 + will complain that it can't find <filename 18.1047 + class="directory">/path/to/repository</filename>. Edit 18.1048 + your <filename role="special">hgweb.cgi</filename> script 18.1049 + and replace the <filename 18.1050 + class="directory">/path/to/repository</filename> string 18.1051 + with the complete path to the repository you want to serve 18.1052 + up.</para> 18.1053 + 18.1054 + <para>At this point, when you try to reload the page, you 18.1055 + should be presented with a nice HTML view of your 18.1056 + repository's history. Whew!</para> 18.1057 + 18.1058 + </sect3> 18.1059 + <sect3> 18.1060 + <title>Configuring lighttpd</title> 18.1061 + 18.1062 + <para>To be exhaustive in my experiments, I tried configuring 18.1063 + the increasingly popular <literal>lighttpd</literal> web 18.1064 + server to serve the same repository as I described with 18.1065 + Apache above. I had already overcome all of the problems I 18.1066 + outlined with Apache, many of which are not server-specific. 18.1067 + As a result, I was fairly sure that my file and directory 18.1068 + permissions were good, and that my <filename 18.1069 + role="special">hgweb.cgi</filename> script was properly 18.1070 + edited.</para> 18.1071 + 18.1072 + <para>Once I had Apache running, getting 18.1073 + <literal>lighttpd</literal> to serve the repository was a 18.1074 + snap (in other words, even if you're trying to use 18.1075 + <literal>lighttpd</literal>, you should read the Apache 18.1076 + section). I first had to edit the 18.1077 + <literal>mod_access</literal> section of its config file to 18.1078 + enable <literal>mod_cgi</literal> and 18.1079 + <literal>mod_userdir</literal>, both of which were disabled 18.1080 + by default on my system. I then added a few lines to the 18.1081 + end of the config file, to configure these modules.</para> 18.1082 + <programlisting>userdir.path = "public_html" 18.1083 +cgi.assign = (".cgi" => "" )</programlisting> 18.1084 + <para>With this done, <literal>lighttpd</literal> ran 18.1085 + immediately for me. If I had configured 18.1086 + <literal>lighttpd</literal> before Apache, I'd almost 18.1087 + certainly have run into many of the same system-level 18.1088 + configuration problems as I did with Apache. However, I 18.1089 + found <literal>lighttpd</literal> to be noticeably easier to 18.1090 + configure than Apache, even though I've used Apache for over 18.1091 + a decade, and this was my first exposure to 18.1092 + <literal>lighttpd</literal>.</para> 18.1093 + 18.1094 + </sect3> 18.1095 + </sect2> 18.1096 + <sect2> 18.1097 + <title>Sharing multiple repositories with one CGI script</title> 18.1098 + 18.1099 + <para>The <filename role="special">hgweb.cgi</filename> script 18.1100 + only lets you publish a single repository, which is an 18.1101 + annoying restriction. If you want to publish more than one 18.1102 + without wracking yourself with multiple copies of the same 18.1103 + script, each with different names, a better choice is to use 18.1104 + the <filename role="special">hgwebdir.cgi</filename> 18.1105 + script.</para> 18.1106 + 18.1107 + <para>The procedure to configure <filename 18.1108 + role="special">hgwebdir.cgi</filename> is only a little more 18.1109 + involved than for <filename 18.1110 + role="special">hgweb.cgi</filename>. First, you must obtain 18.1111 + a copy of the script. If you don't have one handy, you can 18.1112 + download a copy from the master Mercurial repository at <ulink 18.1113 + url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para> 18.1114 + 18.1115 + <para>You'll need to copy this script into your <filename 18.1116 + class="directory">public_html</filename> directory, and 18.1117 + ensure that it's executable.</para> 18.1118 + <programlisting>cp .../hgwebdir.cgi ~/public_html 18.1119 +chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting> 18.1120 + <para>With basic configuration out of the way, try to visit 18.1121 + <ulink url="http://myhostname/ 18.1122 + myuser/hgwebdir.cgi">http://myhostname/ 18.1123 + myuser/hgwebdir.cgi</ulink> in your browser. It should 18.1124 + display an empty list of repositories. If you get a blank 18.1125 + window or error message, try walking through the list of 18.1126 + potential problems in section <xref 18.1127 + linkend="sec.collab.wtf"/>.</para> 18.1128 + 18.1129 + <para>The <filename role="special">hgwebdir.cgi</filename> 18.1130 + script relies on an external configuration file. By default, 18.1131 + it searches for a file named <filename 18.1132 + role="special">hgweb.config</filename> in the same directory 18.1133 + as itself. You'll need to create this file, and make it 18.1134 + world-readable. The format of the file is similar to a 18.1135 + Windows <quote>ini</quote> file, as understood by Python's 18.1136 + <literal>ConfigParser</literal> 18.1137 + <citation>web:configparser</citation> module.</para> 18.1138 + 18.1139 + <para>The easiest way to configure <filename 18.1140 + role="special">hgwebdir.cgi</filename> is with a section 18.1141 + named <literal>collections</literal>. This will automatically 18.1142 + publish <emphasis>every</emphasis> repository under the 18.1143 + directories you name. The section should look like 18.1144 + this:</para> 18.1145 + <programlisting>[collections] 18.1146 +/my/root = /my/root</programlisting> 18.1147 + <para>Mercurial interprets this by looking at the directory name 18.1148 + on the <emphasis>right</emphasis> hand side of the 18.1149 + <quote><literal>=</literal></quote> sign; finding repositories 18.1150 + in that directory hierarchy; and using the text on the 18.1151 + <emphasis>left</emphasis> to strip off matching text from the 18.1152 + names it will actually list in the web interface. The 18.1153 + remaining component of a path after this stripping has 18.1154 + occurred is called a <quote>virtual path</quote>.</para> 18.1155 + 18.1156 + <para>Given the example above, if we have a repository whose 18.1157 + local path is <filename 18.1158 + class="directory">/my/root/this/repo</filename>, the CGI 18.1159 + script will strip the leading <filename 18.1160 + class="directory">/my/root</filename> from the name, and 18.1161 + publish the repository with a virtual path of <filename 18.1162 + class="directory">this/repo</filename>. If the base URL for 18.1163 + our CGI script is <ulink url="http://myhostname/ 18.1164 + myuser/hgwebdir.cgi">http://myhostname/ 18.1165 + myuser/hgwebdir.cgi</ulink>, the complete URL for that 18.1166 + repository will be <ulink url="http://myhostname/ 18.1167 + myuser/hgwebdir.cgi/this/repo">http://myhostname/ 18.1168 + myuser/hgwebdir.cgi/this/repo</ulink>.</para> 18.1169 + 18.1170 + <para>If we replace <filename 18.1171 + class="directory">/my/root</filename> on the left hand side 18.1172 + of this example with <filename 18.1173 + class="directory">/my</filename>, then <filename 18.1174 + role="special">hgwebdir.cgi</filename> will only strip off 18.1175 + <filename class="directory">/my</filename> from the repository 18.1176 + name, and will give us a virtual path of <filename 18.1177 + class="directory">root/this/repo</filename> instead of 18.1178 + <filename class="directory">this/repo</filename>.</para> 18.1179 + 18.1180 + <para>The <filename role="special">hgwebdir.cgi</filename> 18.1181 + script will recursively search each directory listed in the 18.1182 + <literal>collections</literal> section of its configuration 18.1183 + file, but it will <literal>not</literal> recurse into the 18.1184 + repositories it finds.</para> 18.1185 + 18.1186 + <para>The <literal>collections</literal> mechanism makes it easy 18.1187 + to publish many repositories in a <quote>fire and 18.1188 + forget</quote> manner. You only need to set up the CGI 18.1189 + script and configuration file one time. Afterwards, you can 18.1190 + publish or unpublish a repository at any time by simply moving 18.1191 + it into, or out of, the directory hierarchy in which you've 18.1192 + configured <filename role="special">hgwebdir.cgi</filename> to 18.1193 + look.</para> 18.1194 + 18.1195 + <sect3> 18.1196 + <title>Explicitly specifying which repositories to 18.1197 + publish</title> 18.1198 + 18.1199 + <para>In addition to the <literal>collections</literal> 18.1200 + mechanism, the <filename 18.1201 + role="special">hgwebdir.cgi</filename> script allows you 18.1202 + to publish a specific list of repositories. To do so, 18.1203 + create a <literal>paths</literal> section, with contents of 18.1204 + the following form.</para> 18.1205 + <programlisting>[paths] 18.1206 +repo1 = /my/path/to/some/repo 18.1207 +repo2 = /some/path/to/another</programlisting> 18.1208 + <para>In this case, the virtual path (the component that will 18.1209 + appear in a URL) is on the left hand side of each 18.1210 + definition, while the path to the repository is on the 18.1211 + right. Notice that there does not need to be any 18.1212 + relationship between the virtual path you choose and the 18.1213 + location of a repository in your filesystem.</para> 18.1214 + 18.1215 + <para>If you wish, you can use both the 18.1216 + <literal>collections</literal> and <literal>paths</literal> 18.1217 + mechanisms simultaneously in a single configuration 18.1218 + file.</para> 18.1219 + 18.1220 + <note> 18.1221 + <para> If multiple repositories have the same virtual path, 18.1222 + <filename role="special">hgwebdir.cgi</filename> will not 18.1223 + report an error. Instead, it will behave 18.1224 + unpredictably.</para> 18.1225 + </note> 18.1226 + 18.1227 + </sect3> 18.1228 + </sect2> 18.1229 + <sect2> 18.1230 + <title>Downloading source archives</title> 18.1231 + 18.1232 + <para>Mercurial's web interface lets users download an archive 18.1233 + of any revision. This archive will contain a snapshot of the 18.1234 + working directory as of that revision, but it will not contain 18.1235 + a copy of the repository data.</para> 18.1236 + 18.1237 + <para>By default, this feature is not enabled. To enable it, 18.1238 + you'll need to add an <envar 18.1239 + role="rc-item-web">allow_archive</envar> item to the 18.1240 + <literal role="rc-web">web</literal> section of your <filename 18.1241 + role="special">~/.hgrc</filename>.</para> 18.1242 + 18.1243 + </sect2> 18.1244 + <sect2> 18.1245 + <title>Web configuration options</title> 18.1246 + 18.1247 + <para>Mercurial's web interfaces (the <command role="hg-cmd">hg 18.1248 + serve</command> command, and the <filename 18.1249 + role="special">hgweb.cgi</filename> and <filename 18.1250 + role="special">hgwebdir.cgi</filename> scripts) have a 18.1251 + number of configuration options that you can set. These 18.1252 + belong in a section named <literal 18.1253 + role="rc-web">web</literal>.</para> 18.1254 + <itemizedlist> 18.1255 + <listitem><para><envar 18.1256 + role="rc-item-web">allow_archive</envar>: Determines 18.1257 + which (if any) archive download mechanisms Mercurial 18.1258 + supports. If you enable this feature, users of the web 18.1259 + interface will be able to download an archive of whatever 18.1260 + revision of a repository they are viewing. To enable the 18.1261 + archive feature, this item must take the form of a 18.1262 + sequence of words drawn from the list below.</para> 18.1263 + <itemizedlist> 18.1264 + <listitem><para><literal>bz2</literal>: A 18.1265 + <command>tar</command> archive, compressed using 18.1266 + <literal>bzip2</literal> compression. This has the 18.1267 + best compression ratio, but uses the most CPU time on 18.1268 + the server.</para> 18.1269 + </listitem> 18.1270 + <listitem><para><literal>gz</literal>: A 18.1271 + <command>tar</command> archive, compressed using 18.1272 + <literal>gzip</literal> compression.</para> 18.1273 + </listitem> 18.1274 + <listitem><para><literal>zip</literal>: A 18.1275 + <command>zip</command> archive, compressed using LZW 18.1276 + compression. This format has the worst compression 18.1277 + ratio, but is widely used in the Windows world.</para> 18.1278 + </listitem> 18.1279 + </itemizedlist> 18.1280 + <para> If you provide an empty list, or don't have an 18.1281 + <envar role="rc-item-web">allow_archive</envar> entry at 18.1282 + all, this feature will be disabled. Here is an example of 18.1283 + how to enable all three supported formats.</para> 18.1284 + <programlisting>[web] 18.1285 +allow_archive = bz2 gz zip</programlisting> 18.1286 + </listitem> 18.1287 + <listitem><para><envar role="rc-item-web">allowpull</envar>: 18.1288 + Boolean. Determines whether the web interface allows 18.1289 + remote users to <command role="hg-cmd">hg pull</command> 18.1290 + and <command role="hg-cmd">hg clone</command> this 18.1291 + repository over HTTP. If set to <literal>no</literal> or 18.1292 + <literal>false</literal>, only the 18.1293 + <quote>human-oriented</quote> portion of the web interface 18.1294 + is available.</para> 18.1295 + </listitem> 18.1296 + <listitem><para><envar role="rc-item-web">contact</envar>: 18.1297 + String. A free-form (but preferably brief) string 18.1298 + identifying the person or group in charge of the 18.1299 + repository. This often contains the name and email 18.1300 + address of a person or mailing list. It often makes sense 18.1301 + to place this entry in a repository's own <filename 18.1302 + role="special">.hg/hgrc</filename> file, but it can make 18.1303 + sense to use in a global <filename 18.1304 + role="special">~/.hgrc</filename> if every repository 18.1305 + has a single maintainer.</para> 18.1306 + </listitem> 18.1307 + <listitem><para><envar role="rc-item-web">maxchanges</envar>: 18.1308 + Integer. The default maximum number of changesets to 18.1309 + display in a single page of output.</para> 18.1310 + </listitem> 18.1311 + <listitem><para><envar role="rc-item-web">maxfiles</envar>: 18.1312 + Integer. The default maximum number of modified files to 18.1313 + display in a single page of output.</para> 18.1314 + </listitem> 18.1315 + <listitem><para><envar role="rc-item-web">stripes</envar>: 18.1316 + Integer. If the web interface displays alternating 18.1317 + <quote>stripes</quote> to make it easier to visually align 18.1318 + rows when you are looking at a table, this number controls 18.1319 + the number of rows in each stripe.</para> 18.1320 + </listitem> 18.1321 + <listitem><para><envar role="rc-item-web">style</envar>: 18.1322 + Controls the template Mercurial uses to display the web 18.1323 + interface. Mercurial ships with two web templates, named 18.1324 + <literal>default</literal> and <literal>gitweb</literal> 18.1325 + (the latter is much more visually attractive). You can 18.1326 + also specify a custom template of your own; see chapter 18.1327 + <xref linkend="chap.template"/> for details. 18.1328 + Here, you can see how to enable the 18.1329 + <literal>gitweb</literal> style.</para> 18.1330 + <programlisting>[web] 18.1331 +style = gitweb</programlisting> 18.1332 + </listitem> 18.1333 + <listitem><para><envar role="rc-item-web">templates</envar>: 18.1334 + Path. The directory in which to search for template 18.1335 + files. By default, Mercurial searches in the directory in 18.1336 + which it was installed.</para> 18.1337 + </listitem></itemizedlist> 18.1338 + <para>If you are using <filename 18.1339 + role="special">hgwebdir.cgi</filename>, you can place a few 18.1340 + configuration items in a <literal role="rc-web">web</literal> 18.1341 + section of the <filename 18.1342 + role="special">hgweb.config</filename> file instead of a 18.1343 + <filename role="special">~/.hgrc</filename> file, for 18.1344 + convenience. These items are <envar 18.1345 + role="rc-item-web">motd</envar> and <envar 18.1346 + role="rc-item-web">style</envar>.</para> 18.1347 + 18.1348 + <sect3> 18.1349 + <title>Options specific to an individual repository</title> 18.1350 + 18.1351 + <para>A few <literal role="rc-web">web</literal> configuration 18.1352 + items ought to be placed in a repository's local <filename 18.1353 + role="special">.hg/hgrc</filename>, rather than a user's 18.1354 + or global <filename role="special">~/.hgrc</filename>.</para> 18.1355 + <itemizedlist> 18.1356 + <listitem><para><envar 18.1357 + role="rc-item-web">description</envar>: String. A 18.1358 + free-form (but preferably brief) string that describes 18.1359 + the contents or purpose of the repository.</para> 18.1360 + </listitem> 18.1361 + <listitem><para><envar role="rc-item-web">name</envar>: 18.1362 + String. The name to use for the repository in the web 18.1363 + interface. This overrides the default name, which is 18.1364 + the last component of the repository's path.</para> 18.1365 + </listitem></itemizedlist> 18.1366 + 18.1367 + </sect3> 18.1368 + <sect3> 18.1369 + <title>Options specific to the <command role="hg-cmd">hg 18.1370 + serve</command> command</title> 18.1371 + 18.1372 + <para>Some of the items in the <literal 18.1373 + role="rc-web">web</literal> section of a <filename 18.1374 + role="special">~/.hgrc</filename> file are only for use 18.1375 + with the <command role="hg-cmd">hg serve</command> 18.1376 + command.</para> 18.1377 + <itemizedlist> 18.1378 + <listitem><para><envar role="rc-item-web">accesslog</envar>: 18.1379 + Path. The name of a file into which to write an access 18.1380 + log. By default, the <command role="hg-cmd">hg 18.1381 + serve</command> command writes this information to 18.1382 + standard output, not to a file. Log entries are written 18.1383 + in the standard <quote>combined</quote> file format used 18.1384 + by almost all web servers.</para> 18.1385 + </listitem> 18.1386 + <listitem><para><envar role="rc-item-web">address</envar>: 18.1387 + String. The local address on which the server should 18.1388 + listen for incoming connections. By default, the server 18.1389 + listens on all addresses.</para> 18.1390 + </listitem> 18.1391 + <listitem><para><envar role="rc-item-web">errorlog</envar>: 18.1392 + Path. The name of a file into which to write an error 18.1393 + log. By default, the <command role="hg-cmd">hg 18.1394 + serve</command> command writes this information to 18.1395 + standard error, not to a file.</para> 18.1396 + </listitem> 18.1397 + <listitem><para><envar role="rc-item-web">ipv6</envar>: 18.1398 + Boolean. Whether to use the IPv6 protocol. By default, 18.1399 + IPv6 is not used.</para> 18.1400 + </listitem> 18.1401 + <listitem><para><envar role="rc-item-web">port</envar>: 18.1402 + Integer. The TCP port number on which the server should 18.1403 + listen. The default port number used is 8000.</para> 18.1404 + </listitem></itemizedlist> 18.1405 + 18.1406 + </sect3> 18.1407 + <sect3> 18.1408 + <title>Choosing the right <filename 18.1409 + role="special">~/.hgrc</filename> file to add <literal 18.1410 + role="rc-web">web</literal> items to</title> 18.1411 + 18.1412 + <para>It is important to remember that a web server like 18.1413 + Apache or <literal>lighttpd</literal> will run under a user 18.1414 + ID that is different to yours. CGI scripts run by your 18.1415 + server, such as <filename 18.1416 + role="special">hgweb.cgi</filename>, will usually also run 18.1417 + under that user ID.</para> 18.1418 + 18.1419 + <para>If you add <literal role="rc-web">web</literal> items to 18.1420 + your own personal <filename role="special">~/.hgrc</filename> file, CGI scripts won't read that 18.1421 + <filename role="special">~/.hgrc</filename> file. Those 18.1422 + settings will thus only affect the behaviour of the <command 18.1423 + role="hg-cmd">hg serve</command> command when you run it. 18.1424 + To cause CGI scripts to see your settings, either create a 18.1425 + <filename role="special">~/.hgrc</filename> file in the 18.1426 + home directory of the user ID that runs your web server, or 18.1427 + add those settings to a system-wide <filename 18.1428 + role="special">~/.hgrc</filename> file.</para> 18.1429 + 18.1430 + 18.1431 + </sect3> 18.1432 + </sect2> 18.1433 + </sect1> 18.1434 +</chapter> 18.1435 + 18.1436 +<!-- 18.1437 +local variables: 18.1438 +sgml-parent-document: ("00book.xml" "book" "chapter") 18.1439 +end: 18.1440 +-->
19.1 --- a/en/ch05-daily.xml Fri Mar 20 15:40:06 2009 +0800 19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 19.3 @@ -1,544 +0,0 @@ 19.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 19.5 - 19.6 -<chapter id="chap.daily"> 19.7 - <?dbhtml filename="mercurial-in-daily-use.html"?> 19.8 - <title>Mercurial in daily use</title> 19.9 - 19.10 - <sect1> 19.11 - <title>Telling Mercurial which files to track</title> 19.12 - 19.13 - <para>Mercurial does not work with files in your repository unless 19.14 - you tell it to manage them. The <command role="hg-cmd">hg 19.15 - status</command> command will tell you which files Mercurial 19.16 - doesn't know about; it uses a 19.17 - <quote><literal>?</literal></quote> to display such 19.18 - files.</para> 19.19 - 19.20 - <para>To tell Mercurial to track a file, use the <command 19.21 - role="hg-cmd">hg add</command> command. Once you have added a 19.22 - file, the entry in the output of <command role="hg-cmd">hg 19.23 - status</command> for that file changes from 19.24 - <quote><literal>?</literal></quote> to 19.25 - <quote><literal>A</literal></quote>.</para> 19.26 - 19.27 - &interaction.daily.files.add; 19.28 - 19.29 - <para>After you run a <command role="hg-cmd">hg commit</command>, 19.30 - the files that you added before the commit will no longer be 19.31 - listed in the output of <command role="hg-cmd">hg 19.32 - status</command>. The reason for this is that <command 19.33 - role="hg-cmd">hg status</command> only tells you about 19.34 - <quote>interesting</quote> files&emdash;those that you have 19.35 - modified or told Mercurial to do something with&emdash;by 19.36 - default. If you have a repository that contains thousands of 19.37 - files, you will rarely want to know about files that Mercurial 19.38 - is tracking, but that have not changed. (You can still get this 19.39 - information; we'll return to this later.)</para> 19.40 - 19.41 - <para>Once you add a file, Mercurial doesn't do anything with it 19.42 - immediately. Instead, it will take a snapshot of the file's 19.43 - state the next time you perform a commit. It will then continue 19.44 - to track the changes you make to the file every time you commit, 19.45 - until you remove the file.</para> 19.46 - 19.47 - <sect2> 19.48 - <title>Explicit versus implicit file naming</title> 19.49 - 19.50 - <para>A useful behaviour that Mercurial has is that if you pass 19.51 - the name of a directory to a command, every Mercurial command 19.52 - will treat this as <quote>I want to operate on every file in 19.53 - this directory and its subdirectories</quote>.</para> 19.54 - 19.55 - &interaction.daily.files.add-dir; 19.56 - 19.57 - <para>Notice in this example that Mercurial printed the names of 19.58 - the files it added, whereas it didn't do so when we added the 19.59 - file named <filename>a</filename> in the earlier 19.60 - example.</para> 19.61 - 19.62 - <para>What's going on is that in the former case, we explicitly 19.63 - named the file to add on the command line, so the assumption 19.64 - that Mercurial makes in such cases is that you know what you 19.65 - were doing, and it doesn't print any output.</para> 19.66 - 19.67 - <para>However, when we <emphasis>imply</emphasis> the names of 19.68 - files by giving the name of a directory, Mercurial takes the 19.69 - extra step of printing the name of each file that it does 19.70 - something with. This makes it more clear what is happening, 19.71 - and reduces the likelihood of a silent and nasty surprise. 19.72 - This behaviour is common to most Mercurial commands.</para> 19.73 - 19.74 - </sect2> 19.75 - <sect2> 19.76 - <title>Aside: Mercurial tracks files, not directories</title> 19.77 - 19.78 - <para>Mercurial does not track directory information. Instead, 19.79 - it tracks the path to a file. Before creating a file, it 19.80 - first creates any missing directory components of the path. 19.81 - After it deletes a file, it then deletes any empty directories 19.82 - that were in the deleted file's path. This sounds like a 19.83 - trivial distinction, but it has one minor practical 19.84 - consequence: it is not possible to represent a completely 19.85 - empty directory in Mercurial.</para> 19.86 - 19.87 - <para>Empty directories are rarely useful, and there are 19.88 - unintrusive workarounds that you can use to achieve an 19.89 - appropriate effect. The developers of Mercurial thus felt 19.90 - that the complexity that would be required to manage empty 19.91 - directories was not worth the limited benefit this feature 19.92 - would bring.</para> 19.93 - 19.94 - <para>If you need an empty directory in your repository, there 19.95 - are a few ways to achieve this. One is to create a directory, 19.96 - then <command role="hg-cmd">hg add</command> a 19.97 - <quote>hidden</quote> file to that directory. On Unix-like 19.98 - systems, any file name that begins with a period 19.99 - (<quote><literal>.</literal></quote>) is treated as hidden by 19.100 - most commands and GUI tools. This approach is illustrated 19.101 - below.</para> 19.102 - 19.103 -&interaction.daily.files.hidden; 19.104 - 19.105 - <para>Another way to tackle a need for an empty directory is to 19.106 - simply create one in your automated build scripts before they 19.107 - will need it.</para> 19.108 - 19.109 - </sect2> 19.110 - </sect1> 19.111 - <sect1> 19.112 - <title>How to stop tracking a file</title> 19.113 - 19.114 - <para>Once you decide that a file no longer belongs in your 19.115 - repository, use the <command role="hg-cmd">hg remove</command> 19.116 - command; this deletes the file, and tells Mercurial to stop 19.117 - tracking it. A removed file is represented in the output of 19.118 - <command role="hg-cmd">hg status</command> with a 19.119 - <quote><literal>R</literal></quote>.</para> 19.120 - 19.121 - &interaction.daily.files.remove; 19.122 - 19.123 - <para>After you <command role="hg-cmd">hg remove</command> a file, 19.124 - Mercurial will no longer track changes to that file, even if you 19.125 - recreate a file with the same name in your working directory. 19.126 - If you do recreate a file with the same name and want Mercurial 19.127 - to track the new file, simply <command role="hg-cmd">hg 19.128 - add</command> it. Mercurial will know that the newly added 19.129 - file is not related to the old file of the same name.</para> 19.130 - 19.131 - <sect2> 19.132 - <title>Removing a file does not affect its history</title> 19.133 - 19.134 - <para>It is important to understand that removing a file has 19.135 - only two effects.</para> 19.136 - <itemizedlist> 19.137 - <listitem><para>It removes the current version of the file 19.138 - from the working directory.</para> 19.139 - </listitem> 19.140 - <listitem><para>It stops Mercurial from tracking changes to 19.141 - the file, from the time of the next commit.</para> 19.142 - </listitem></itemizedlist> 19.143 - <para>Removing a file <emphasis>does not</emphasis> in any way 19.144 - alter the <emphasis>history</emphasis> of the file.</para> 19.145 - 19.146 - <para>If you update the working directory to a changeset in 19.147 - which a file that you have removed was still tracked, it will 19.148 - reappear in the working directory, with the contents it had 19.149 - when you committed that changeset. If you then update the 19.150 - working directory to a later changeset, in which the file had 19.151 - been removed, Mercurial will once again remove the file from 19.152 - the working directory.</para> 19.153 - 19.154 - </sect2> 19.155 - <sect2> 19.156 - <title>Missing files</title> 19.157 - 19.158 - <para>Mercurial considers a file that you have deleted, but not 19.159 - used <command role="hg-cmd">hg remove</command> to delete, to 19.160 - be <emphasis>missing</emphasis>. A missing file is 19.161 - represented with <quote><literal>!</literal></quote> in the 19.162 - output of <command role="hg-cmd">hg status</command>. 19.163 - Mercurial commands will not generally do anything with missing 19.164 - files.</para> 19.165 - 19.166 - &interaction.daily.files.missing; 19.167 - 19.168 - <para>If your repository contains a file that <command 19.169 - role="hg-cmd">hg status</command> reports as missing, and 19.170 - you want the file to stay gone, you can run <command 19.171 - role="hg-cmd">hg remove <option 19.172 - role="hg-opt-remove">--after</option></command> at any 19.173 - time later on, to tell Mercurial that you really did mean to 19.174 - remove the file.</para> 19.175 - 19.176 - &interaction.daily.files.remove-after; 19.177 - 19.178 - <para>On the other hand, if you deleted the missing file by 19.179 - accident, give <command role="hg-cmd">hg revert</command> the 19.180 - name of the file to recover. It will reappear, in unmodified 19.181 - form.</para> 19.182 - 19.183 -&interaction.daily.files.recover-missing; 19.184 - 19.185 - </sect2> 19.186 - <sect2> 19.187 - <title>Aside: why tell Mercurial explicitly to remove a 19.188 - file?</title> 19.189 - 19.190 - <para>You might wonder why Mercurial requires you to explicitly 19.191 - tell it that you are deleting a file. Early during the 19.192 - development of Mercurial, it let you delete a file however you 19.193 - pleased; Mercurial would notice the absence of the file 19.194 - automatically when you next ran a <command role="hg-cmd">hg 19.195 - commit</command>, and stop tracking the file. In practice, 19.196 - this made it too easy to accidentally remove a file without 19.197 - noticing.</para> 19.198 - 19.199 - </sect2> 19.200 - <sect2> 19.201 - <title>Useful shorthand&emdash;adding and removing files in one 19.202 - step</title> 19.203 - 19.204 - <para>Mercurial offers a combination command, <command 19.205 - role="hg-cmd">hg addremove</command>, that adds untracked 19.206 - files and marks missing files as removed.</para> 19.207 - 19.208 - &interaction.daily.files.addremove; 19.209 - 19.210 - <para>The <command role="hg-cmd">hg commit</command> command 19.211 - also provides a <option role="hg-opt-commit">-A</option> 19.212 - option that performs this same add-and-remove, immediately 19.213 - followed by a commit.</para> 19.214 - 19.215 - &interaction.daily.files.commit-addremove; 19.216 - 19.217 - </sect2> 19.218 - </sect1> 19.219 - <sect1> 19.220 - <title>Copying files</title> 19.221 - 19.222 - <para>Mercurial provides a <command role="hg-cmd">hg 19.223 - copy</command> command that lets you make a new copy of a 19.224 - file. When you copy a file using this command, Mercurial makes 19.225 - a record of the fact that the new file is a copy of the original 19.226 - file. It treats these copied files specially when you merge 19.227 - your work with someone else's.</para> 19.228 - 19.229 - <sect2> 19.230 - <title>The results of copying during a merge</title> 19.231 - 19.232 - <para>What happens during a merge is that changes 19.233 - <quote>follow</quote> a copy. To best illustrate what this 19.234 - means, let's create an example. We'll start with the usual 19.235 - tiny repository that contains a single file.</para> 19.236 - 19.237 - &interaction.daily.copy.init; 19.238 - 19.239 - <para>We need to do some work in 19.240 - parallel, so that we'll have something to merge. So let's 19.241 - clone our repository.</para> 19.242 - 19.243 - &interaction.daily.copy.clone; 19.244 - 19.245 - <para>Back in our initial repository, let's use the <command 19.246 - role="hg-cmd">hg copy</command> command to make a copy of 19.247 - the first file we created.</para> 19.248 - 19.249 - &interaction.daily.copy.copy; 19.250 - 19.251 - <para>If we look at the output of the <command role="hg-cmd">hg 19.252 - status</command> command afterwards, the copied file looks 19.253 - just like a normal added file.</para> 19.254 - 19.255 - &interaction.daily.copy.status; 19.256 - 19.257 - <para>But if we pass the <option 19.258 - role="hg-opt-status">-C</option> option to <command 19.259 - role="hg-cmd">hg status</command>, it prints another line of 19.260 - output: this is the file that our newly-added file was copied 19.261 - <emphasis>from</emphasis>.</para> 19.262 - 19.263 - &interaction.daily.copy.status-copy; 19.264 - 19.265 - <para>Now, back in the repository we cloned, let's make a change 19.266 - in parallel. We'll add a line of content to the original file 19.267 - that we created.</para> 19.268 - 19.269 - &interaction.daily.copy.other; 19.270 - 19.271 - <para>Now we have a modified <filename>file</filename> in this 19.272 - repository. When we pull the changes from the first 19.273 - repository, and merge the two heads, Mercurial will propagate 19.274 - the changes that we made locally to <filename>file</filename> 19.275 - into its copy, <filename>new-file</filename>.</para> 19.276 - 19.277 - &interaction.daily.copy.merge; 19.278 - 19.279 - </sect2> 19.280 - <sect2 id="sec.daily.why-copy"> 19.281 - <title>Why should changes follow copies?</title> 19.282 - 19.283 - <para>This behaviour, of changes to a file propagating out to 19.284 - copies of the file, might seem esoteric, but in most cases 19.285 - it's highly desirable.</para> 19.286 - 19.287 - <para>First of all, remember that this propagation 19.288 - <emphasis>only</emphasis> happens when you merge. So if you 19.289 - <command role="hg-cmd">hg copy</command> a file, and 19.290 - subsequently modify the original file during the normal course 19.291 - of your work, nothing will happen.</para> 19.292 - 19.293 - <para>The second thing to know is that modifications will only 19.294 - propagate across a copy as long as the repository that you're 19.295 - pulling changes from <emphasis>doesn't know</emphasis> about 19.296 - the copy.</para> 19.297 - 19.298 - <para>The reason that Mercurial does this is as follows. Let's 19.299 - say I make an important bug fix in a source file, and commit 19.300 - my changes. Meanwhile, you've decided to <command 19.301 - role="hg-cmd">hg copy</command> the file in your repository, 19.302 - without knowing about the bug or having seen the fix, and you 19.303 - have started hacking on your copy of the file.</para> 19.304 - 19.305 - <para>If you pulled and merged my changes, and Mercurial 19.306 - <emphasis>didn't</emphasis> propagate changes across copies, 19.307 - your source file would now contain the bug, and unless you 19.308 - remembered to propagate the bug fix by hand, the bug would 19.309 - <emphasis>remain</emphasis> in your copy of the file.</para> 19.310 - 19.311 - <para>By automatically propagating the change that fixed the bug 19.312 - from the original file to the copy, Mercurial prevents this 19.313 - class of problem. To my knowledge, Mercurial is the 19.314 - <emphasis>only</emphasis> revision control system that 19.315 - propagates changes across copies like this.</para> 19.316 - 19.317 - <para>Once your change history has a record that the copy and 19.318 - subsequent merge occurred, there's usually no further need to 19.319 - propagate changes from the original file to the copied file, 19.320 - and that's why Mercurial only propagates changes across copies 19.321 - until this point, and no further.</para> 19.322 - 19.323 - </sect2> 19.324 - <sect2> 19.325 - <title>How to make changes <emphasis>not</emphasis> follow a 19.326 - copy</title> 19.327 - 19.328 - <para>If, for some reason, you decide that this business of 19.329 - automatically propagating changes across copies is not for 19.330 - you, simply use your system's normal file copy command (on 19.331 - Unix-like systems, that's <command>cp</command>) to make a 19.332 - copy of a file, then <command role="hg-cmd">hg add</command> 19.333 - the new copy by hand. Before you do so, though, please do 19.334 - reread section <xref linkend="sec.daily.why-copy"/>, and make 19.335 - an informed 19.336 - decision that this behaviour is not appropriate to your 19.337 - specific case.</para> 19.338 - 19.339 - </sect2> 19.340 - <sect2> 19.341 - <title>Behaviour of the <command role="hg-cmd">hg copy</command> 19.342 - command</title> 19.343 - 19.344 - <para>When you use the <command role="hg-cmd">hg copy</command> 19.345 - command, Mercurial makes a copy of each source file as it 19.346 - currently stands in the working directory. This means that if 19.347 - you make some modifications to a file, then <command 19.348 - role="hg-cmd">hg copy</command> it without first having 19.349 - committed those changes, the new copy will also contain the 19.350 - modifications you have made up until that point. (I find this 19.351 - behaviour a little counterintuitive, which is why I mention it 19.352 - here.)</para> 19.353 - 19.354 - <para>The <command role="hg-cmd">hg copy</command> command acts 19.355 - similarly to the Unix <command>cp</command> command (you can 19.356 - use the <command role="hg-cmd">hg cp</command> alias if you 19.357 - prefer). The last argument is the 19.358 - <emphasis>destination</emphasis>, and all prior arguments are 19.359 - <emphasis>sources</emphasis>. If you pass it a single file as 19.360 - the source, and the destination does not exist, it creates a 19.361 - new file with that name.</para> 19.362 - 19.363 - &interaction.daily.copy.simple; 19.364 - 19.365 - <para>If the destination is a directory, Mercurial copies its 19.366 - sources into that directory.</para> 19.367 - 19.368 - &interaction.daily.copy.dir-dest; 19.369 - 19.370 - <para>Copying a directory is 19.371 - recursive, and preserves the directory structure of the 19.372 - source.</para> 19.373 - 19.374 - &interaction.daily.copy.dir-src; 19.375 - 19.376 - <para>If the source and destination are both directories, the 19.377 - source tree is recreated in the destination directory.</para> 19.378 - 19.379 - &interaction.daily.copy.dir-src-dest; 19.380 - 19.381 - <para>As with the <command role="hg-cmd">hg rename</command> 19.382 - command, if you copy a file manually and then want Mercurial 19.383 - to know that you've copied the file, simply use the <option 19.384 - role="hg-opt-copy">--after</option> option to <command 19.385 - role="hg-cmd">hg copy</command>.</para> 19.386 - 19.387 - &interaction.daily.copy.after; 19.388 - 19.389 - </sect2> 19.390 - </sect1> 19.391 - <sect1> 19.392 - <title>Renaming files</title> 19.393 - 19.394 - <para>It's rather more common to need to rename a file than to 19.395 - make a copy of it. The reason I discussed the <command 19.396 - role="hg-cmd">hg copy</command> command before talking about 19.397 - renaming files is that Mercurial treats a rename in essentially 19.398 - the same way as a copy. Therefore, knowing what Mercurial does 19.399 - when you copy a file tells you what to expect when you rename a 19.400 - file.</para> 19.401 - 19.402 - <para>When you use the <command role="hg-cmd">hg rename</command> 19.403 - command, Mercurial makes a copy of each source file, then 19.404 - deletes it and marks the file as removed.</para> 19.405 - 19.406 - &interaction.daily.rename.rename; 19.407 - 19.408 - <para>The <command role="hg-cmd">hg status</command> command shows 19.409 - the newly copied file as added, and the copied-from file as 19.410 - removed.</para> 19.411 - 19.412 - &interaction.daily.rename.status; 19.413 - 19.414 - <para>As with the results of a <command role="hg-cmd">hg 19.415 - copy</command>, we must use the <option 19.416 - role="hg-opt-status">-C</option> option to <command 19.417 - role="hg-cmd">hg status</command> to see that the added file 19.418 - is really being tracked by Mercurial as a copy of the original, 19.419 - now removed, file.</para> 19.420 - 19.421 - &interaction.daily.rename.status-copy; 19.422 - 19.423 - <para>As with <command role="hg-cmd">hg remove</command> and 19.424 - <command role="hg-cmd">hg copy</command>, you can tell Mercurial 19.425 - about a rename after the fact using the <option 19.426 - role="hg-opt-rename">--after</option> option. In most other 19.427 - respects, the behaviour of the <command role="hg-cmd">hg 19.428 - rename</command> command, and the options it accepts, are 19.429 - similar to the <command role="hg-cmd">hg copy</command> 19.430 - command.</para> 19.431 - 19.432 - <sect2> 19.433 - <title>Renaming files and merging changes</title> 19.434 - 19.435 - <para>Since Mercurial's rename is implemented as 19.436 - copy-and-remove, the same propagation of changes happens when 19.437 - you merge after a rename as after a copy.</para> 19.438 - 19.439 - <para>If I modify a file, and you rename it to a new name, and 19.440 - then we merge our respective changes, my modifications to the 19.441 - file under its original name will be propagated into the file 19.442 - under its new name. (This is something you might expect to 19.443 - <quote>simply work,</quote> but not all revision control 19.444 - systems actually do this.)</para> 19.445 - 19.446 - <para>Whereas having changes follow a copy is a feature where 19.447 - you can perhaps nod and say <quote>yes, that might be 19.448 - useful,</quote> it should be clear that having them follow a 19.449 - rename is definitely important. Without this facility, it 19.450 - would simply be too easy for changes to become orphaned when 19.451 - files are renamed.</para> 19.452 - 19.453 - </sect2> 19.454 - <sect2> 19.455 - <title>Divergent renames and merging</title> 19.456 - 19.457 - <para>The case of diverging names occurs when two developers 19.458 - start with a file&emdash;let's call it 19.459 - <filename>foo</filename>&emdash;in their respective 19.460 - repositories.</para> 19.461 - 19.462 - &interaction.rename.divergent.clone; 19.463 - 19.464 - <para>Anne renames the file to <filename>bar</filename>.</para> 19.465 - 19.466 - &interaction.rename.divergent.rename.anne; 19.467 - 19.468 - <para>Meanwhile, Bob renames it to 19.469 - <filename>quux</filename>.</para> 19.470 - 19.471 - &interaction.rename.divergent.rename.bob; 19.472 - 19.473 - <para>I like to think of this as a conflict because each 19.474 - developer has expressed different intentions about what the 19.475 - file ought to be named.</para> 19.476 - 19.477 - <para>What do you think should happen when they merge their 19.478 - work? Mercurial's actual behaviour is that it always preserves 19.479 - <emphasis>both</emphasis> names when it merges changesets that 19.480 - contain divergent renames.</para> 19.481 - 19.482 - &interaction.rename.divergent.merge; 19.483 - 19.484 - <para>Notice that Mercurial does warn about the divergent 19.485 - renames, but it leaves it up to you to do something about the 19.486 - divergence after the merge.</para> 19.487 - 19.488 - </sect2> 19.489 - <sect2> 19.490 - <title>Convergent renames and merging</title> 19.491 - 19.492 - <para>Another kind of rename conflict occurs when two people 19.493 - choose to rename different <emphasis>source</emphasis> files 19.494 - to the same <emphasis>destination</emphasis>. In this case, 19.495 - Mercurial runs its normal merge machinery, and lets you guide 19.496 - it to a suitable resolution.</para> 19.497 - 19.498 - </sect2> 19.499 - <sect2> 19.500 - <title>Other name-related corner cases</title> 19.501 - 19.502 - <para>Mercurial has a longstanding bug in which it fails to 19.503 - handle a merge where one side has a file with a given name, 19.504 - while another has a directory with the same name. This is 19.505 - documented as <ulink role="hg-bug" 19.506 - url="http://www.selenic.com/mercurial/bts/issue29">issue 19.507 - 29</ulink>.</para> 19.508 - 19.509 - &interaction.issue29.go; 19.510 - 19.511 - </sect2> 19.512 - </sect1> 19.513 - <sect1> 19.514 - <title>Recovering from mistakes</title> 19.515 - 19.516 - <para>Mercurial has some useful commands that will help you to 19.517 - recover from some common mistakes.</para> 19.518 - 19.519 - <para>The <command role="hg-cmd">hg revert</command> command lets 19.520 - you undo changes that you have made to your working directory. 19.521 - For example, if you <command role="hg-cmd">hg add</command> a 19.522 - file by accident, just run <command role="hg-cmd">hg 19.523 - revert</command> with the name of the file you added, and 19.524 - while the file won't be touched in any way, it won't be tracked 19.525 - for adding by Mercurial any longer, either. You can also use 19.526 - <command role="hg-cmd">hg revert</command> to get rid of 19.527 - erroneous changes to a file.</para> 19.528 - 19.529 - <para>It's useful to remember that the <command role="hg-cmd">hg 19.530 - revert</command> command is useful for changes that you have 19.531 - not yet committed. Once you've committed a change, if you 19.532 - decide it was a mistake, you can still do something about it, 19.533 - though your options may be more limited.</para> 19.534 - 19.535 - <para>For more information about the <command role="hg-cmd">hg 19.536 - revert</command> command, and details about how to deal with 19.537 - changes you have already committed, see chapter <xref 19.538 - linkend="chap.undo"/>.</para> 19.539 - 19.540 - </sect1> 19.541 -</chapter> 19.542 - 19.543 -<!-- 19.544 -local variables: 19.545 -sgml-parent-document: ("00book.xml" "book" "chapter") 19.546 -end: 19.547 --->
20.1 --- a/en/ch06-collab.xml Fri Mar 20 15:40:06 2009 +0800 20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 20.3 @@ -1,1437 +0,0 @@ 20.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 20.5 - 20.6 -<chapter id="cha.collab"> 20.7 - <?dbhtml filename="collaborating-with-other-people.html"?> 20.8 - <title>Collaborating with other people</title> 20.9 - 20.10 - <para>As a completely decentralised tool, Mercurial doesn't impose 20.11 - any policy on how people ought to work with each other. However, 20.12 - if you're new to distributed revision control, it helps to have 20.13 - some tools and examples in mind when you're thinking about 20.14 - possible workflow models.</para> 20.15 - 20.16 - <sect1> 20.17 - <title>Mercurial's web interface</title> 20.18 - 20.19 - <para>Mercurial has a powerful web interface that provides several 20.20 - useful capabilities.</para> 20.21 - 20.22 - <para>For interactive use, the web interface lets you browse a 20.23 - single repository or a collection of repositories. You can view 20.24 - the history of a repository, examine each change (comments and 20.25 - diffs), and view the contents of each directory and file.</para> 20.26 - 20.27 - <para>Also for human consumption, the web interface provides an 20.28 - RSS feed of the changes in a repository. This lets you 20.29 - <quote>subscribe</quote> to a repository using your favourite 20.30 - feed reader, and be automatically notified of activity in that 20.31 - repository as soon as it happens. I find this capability much 20.32 - more convenient than the model of subscribing to a mailing list 20.33 - to which notifications are sent, as it requires no additional 20.34 - configuration on the part of whoever is serving the 20.35 - repository.</para> 20.36 - 20.37 - <para>The web interface also lets remote users clone a repository, 20.38 - pull changes from it, and (when the server is configured to 20.39 - permit it) push changes back to it. Mercurial's HTTP tunneling 20.40 - protocol aggressively compresses data, so that it works 20.41 - efficiently even over low-bandwidth network connections.</para> 20.42 - 20.43 - <para>The easiest way to get started with the web interface is to 20.44 - use your web browser to visit an existing repository, such as 20.45 - the master Mercurial repository at <ulink 20.46 - url="http://www.selenic.com/repo/hg?style=gitweb">http://www.selenic.com/repo/hg?style=gitweb</ulink>.</para> 20.47 - 20.48 - <para>If you're interested in providing a web interface to your 20.49 - own repositories, Mercurial provides two ways to do this. The 20.50 - first is using the <command role="hg-cmd">hg serve</command> 20.51 - command, which is best suited to short-term 20.52 - <quote>lightweight</quote> serving. See section <xref 20.53 - linkend="sec.collab.serve"/> below for details of how to use 20.54 - this command. If you have a long-lived repository that you'd 20.55 - like to make permanently available, Mercurial has built-in 20.56 - support for the CGI (Common Gateway Interface) standard, which 20.57 - all common web servers support. See section <xref 20.58 - linkend="sec.collab.cgi"/> for details of CGI 20.59 - configuration.</para> 20.60 - 20.61 - </sect1> 20.62 - <sect1> 20.63 - <title>Collaboration models</title> 20.64 - 20.65 - <para>With a suitably flexible tool, making decisions about 20.66 - workflow is much more of a social engineering challenge than a 20.67 - technical one. Mercurial imposes few limitations on how you can 20.68 - structure the flow of work in a project, so it's up to you and 20.69 - your group to set up and live with a model that matches your own 20.70 - particular needs.</para> 20.71 - 20.72 - <sect2> 20.73 - <title>Factors to keep in mind</title> 20.74 - 20.75 - <para>The most important aspect of any model that you must keep 20.76 - in mind is how well it matches the needs and capabilities of 20.77 - the people who will be using it. This might seem 20.78 - self-evident; even so, you still can't afford to forget it for 20.79 - a moment.</para> 20.80 - 20.81 - <para>I once put together a workflow model that seemed to make 20.82 - perfect sense to me, but that caused a considerable amount of 20.83 - consternation and strife within my development team. In spite 20.84 - of my attempts to explain why we needed a complex set of 20.85 - branches, and how changes ought to flow between them, a few 20.86 - team members revolted. Even though they were smart people, 20.87 - they didn't want to pay attention to the constraints we were 20.88 - operating under, or face the consequences of those constraints 20.89 - in the details of the model that I was advocating.</para> 20.90 - 20.91 - <para>Don't sweep foreseeable social or technical problems under 20.92 - the rug. Whatever scheme you put into effect, you should plan 20.93 - for mistakes and problem scenarios. Consider adding automated 20.94 - machinery to prevent, or quickly recover from, trouble that 20.95 - you can anticipate. As an example, if you intend to have a 20.96 - branch with not-for-release changes in it, you'd do well to 20.97 - think early about the possibility that someone might 20.98 - accidentally merge those changes into a release branch. You 20.99 - could avoid this particular problem by writing a hook that 20.100 - prevents changes from being merged from an inappropriate 20.101 - branch.</para> 20.102 - 20.103 - </sect2> 20.104 - <sect2> 20.105 - <title>Informal anarchy</title> 20.106 - 20.107 - <para>I wouldn't suggest an <quote>anything goes</quote> 20.108 - approach as something sustainable, but it's a model that's 20.109 - easy to grasp, and it works perfectly well in a few unusual 20.110 - situations.</para> 20.111 - 20.112 - <para>As one example, many projects have a loose-knit group of 20.113 - collaborators who rarely physically meet each other. Some 20.114 - groups like to overcome the isolation of working at a distance 20.115 - by organising occasional <quote>sprints</quote>. In a sprint, 20.116 - a number of people get together in a single location (a 20.117 - company's conference room, a hotel meeting room, that kind of 20.118 - place) and spend several days more or less locked in there, 20.119 - hacking intensely on a handful of projects.</para> 20.120 - 20.121 - <para>A sprint is the perfect place to use the <command 20.122 - role="hg-cmd">hg serve</command> command, since <command 20.123 - role="hg-cmd">hg serve</command> does not require any fancy 20.124 - server infrastructure. You can get started with <command 20.125 - role="hg-cmd">hg serve</command> in moments, by reading 20.126 - section <xref linkend="sec.collab.serve"/> below. Then simply 20.127 - tell 20.128 - the person next to you that you're running a server, send the 20.129 - URL to them in an instant message, and you immediately have a 20.130 - quick-turnaround way to work together. They can type your URL 20.131 - into their web browser and quickly review your changes; or 20.132 - they can pull a bugfix from you and verify it; or they can 20.133 - clone a branch containing a new feature and try it out.</para> 20.134 - 20.135 - <para>The charm, and the problem, with doing things in an ad hoc 20.136 - fashion like this is that only people who know about your 20.137 - changes, and where they are, can see them. Such an informal 20.138 - approach simply doesn't scale beyond a handful people, because 20.139 - each individual needs to know about $n$ different repositories 20.140 - to pull from.</para> 20.141 - 20.142 - </sect2> 20.143 - <sect2> 20.144 - <title>A single central repository</title> 20.145 - 20.146 - <para>For smaller projects migrating from a centralised revision 20.147 - control tool, perhaps the easiest way to get started is to 20.148 - have changes flow through a single shared central repository. 20.149 - This is also the most common <quote>building block</quote> for 20.150 - more ambitious workflow schemes.</para> 20.151 - 20.152 - <para>Contributors start by cloning a copy of this repository. 20.153 - They can pull changes from it whenever they need to, and some 20.154 - (perhaps all) developers have permission to push a change back 20.155 - when they're ready for other people to see it.</para> 20.156 - 20.157 - <para>Under this model, it can still often make sense for people 20.158 - to pull changes directly from each other, without going 20.159 - through the central repository. Consider a case in which I 20.160 - have a tentative bug fix, but I am worried that if I were to 20.161 - publish it to the central repository, it might subsequently 20.162 - break everyone else's trees as they pull it. To reduce the 20.163 - potential for damage, I can ask you to clone my repository 20.164 - into a temporary repository of your own and test it. This 20.165 - lets us put off publishing the potentially unsafe change until 20.166 - it has had a little testing.</para> 20.167 - 20.168 - <para>In this kind of scenario, people usually use the 20.169 - <command>ssh</command> protocol to securely push changes to 20.170 - the central repository, as documented in section <xref 20.171 - linkend="sec.collab.ssh"/>. It's also 20.172 - usual to publish a read-only copy of the repository over HTTP 20.173 - using CGI, as in section <xref linkend="sec.collab.cgi"/>. 20.174 - Publishing over HTTP 20.175 - satisfies the needs of people who don't have push access, and 20.176 - those who want to use web browsers to browse the repository's 20.177 - history.</para> 20.178 - 20.179 - </sect2> 20.180 - <sect2> 20.181 - <title>Working with multiple branches</title> 20.182 - 20.183 - <para>Projects of any significant size naturally tend to make 20.184 - progress on several fronts simultaneously. In the case of 20.185 - software, it's common for a project to go through periodic 20.186 - official releases. A release might then go into 20.187 - <quote>maintenance mode</quote> for a while after its first 20.188 - publication; maintenance releases tend to contain only bug 20.189 - fixes, not new features. In parallel with these maintenance 20.190 - releases, one or more future releases may be under 20.191 - development. People normally use the word 20.192 - <quote>branch</quote> to refer to one of these many slightly 20.193 - different directions in which development is 20.194 - proceeding.</para> 20.195 - 20.196 - <para>Mercurial is particularly well suited to managing a number 20.197 - of simultaneous, but not identical, branches. Each 20.198 - <quote>development direction</quote> can live in its own 20.199 - central repository, and you can merge changes from one to 20.200 - another as the need arises. Because repositories are 20.201 - independent of each other, unstable changes in a development 20.202 - branch will never affect a stable branch unless someone 20.203 - explicitly merges those changes in.</para> 20.204 - 20.205 - <para>Here's an example of how this can work in practice. Let's 20.206 - say you have one <quote>main branch</quote> on a central 20.207 - server.</para> 20.208 - 20.209 - &interaction.branching.init; 20.210 - 20.211 - <para>People clone it, make changes locally, test them, and push 20.212 - them back.</para> 20.213 - 20.214 - <para>Once the main branch reaches a release milestone, you can 20.215 - use the <command role="hg-cmd">hg tag</command> command to 20.216 - give a permanent name to the milestone revision.</para> 20.217 - 20.218 - &interaction.branching.tag; 20.219 - 20.220 - <para>Let's say some ongoing 20.221 - development occurs on the main branch.</para> 20.222 - 20.223 - &interaction.branching.main; 20.224 - 20.225 - <para>Using the tag that was recorded at the milestone, people 20.226 - who clone that repository at any time in the future can use 20.227 - <command role="hg-cmd">hg update</command> to get a copy of 20.228 - the working directory exactly as it was when that tagged 20.229 - revision was committed.</para> 20.230 - 20.231 - &interaction.branching.update; 20.232 - 20.233 - <para>In addition, immediately after the main branch is tagged, 20.234 - someone can then clone the main branch on the server to a new 20.235 - <quote>stable</quote> branch, also on the server.</para> 20.236 - 20.237 - &interaction.branching.clone; 20.238 - 20.239 - <para>Someone who needs to make a change to the stable branch 20.240 - can then clone <emphasis>that</emphasis> repository, make 20.241 - their changes, commit, and push their changes back there.</para> 20.242 - 20.243 - &interaction.branching.stable; 20.244 - 20.245 - <para>Because Mercurial repositories are independent, and 20.246 - Mercurial doesn't move changes around automatically, the 20.247 - stable and main branches are <emphasis>isolated</emphasis> 20.248 - from each other. The changes that you made on the main branch 20.249 - don't <quote>leak</quote> to the stable branch, and vice 20.250 - versa.</para> 20.251 - 20.252 - <para>You'll often want all of your bugfixes on the stable 20.253 - branch to show up on the main branch, too. Rather than 20.254 - rewrite a bugfix on the main branch, you can simply pull and 20.255 - merge changes from the stable to the main branch, and 20.256 - Mercurial will bring those bugfixes in for you.</para> 20.257 - 20.258 - &interaction.branching.merge; 20.259 - 20.260 - <para>The main branch will still contain changes that are not on 20.261 - the stable branch, but it will also contain all of the 20.262 - bugfixes from the stable branch. The stable branch remains 20.263 - unaffected by these changes.</para> 20.264 - 20.265 - </sect2> 20.266 - <sect2> 20.267 - <title>Feature branches</title> 20.268 - 20.269 - <para>For larger projects, an effective way to manage change is 20.270 - to break up a team into smaller groups. Each group has a 20.271 - shared branch of its own, cloned from a single 20.272 - <quote>master</quote> branch used by the entire project. 20.273 - People working on an individual branch are typically quite 20.274 - isolated from developments on other branches.</para> 20.275 - 20.276 - <informalfigure id="fig.collab.feature-branches"> 20.277 - <mediaobject> 20.278 - <imageobject><imagedata fileref="images/feature-branches.png"/> 20.279 - </imageobject> 20.280 - <textobject><phrase>XXX add text</phrase></textobject> 20.281 - <caption><para id="fig.collab.feature-branches.caption">Feature 20.282 - branches</para></caption> 20.283 - </mediaobject> 20.284 - </informalfigure> 20.285 - 20.286 - <para>When a particular feature is deemed to be in suitable 20.287 - shape, someone on that feature team pulls and merges from the 20.288 - master branch into the feature branch, then pushes back up to 20.289 - the master branch.</para> 20.290 - 20.291 - </sect2> 20.292 - <sect2> 20.293 - <title>The release train</title> 20.294 - 20.295 - <para>Some projects are organised on a <quote>train</quote> 20.296 - basis: a release is scheduled to happen every few months, and 20.297 - whatever features are ready when the <quote>train</quote> is 20.298 - ready to leave are allowed in.</para> 20.299 - 20.300 - <para>This model resembles working with feature branches. The 20.301 - difference is that when a feature branch misses a train, 20.302 - someone on the feature team pulls and merges the changes that 20.303 - went out on that train release into the feature branch, and 20.304 - the team continues its work on top of that release so that 20.305 - their feature can make the next release.</para> 20.306 - 20.307 - </sect2> 20.308 - <sect2> 20.309 - <title>The Linux kernel model</title> 20.310 - 20.311 - <para>The development of the Linux kernel has a shallow 20.312 - hierarchical structure, surrounded by a cloud of apparent 20.313 - chaos. Because most Linux developers use 20.314 - <command>git</command>, a distributed revision control tool 20.315 - with capabilities similar to Mercurial, it's useful to 20.316 - describe the way work flows in that environment; if you like 20.317 - the ideas, the approach translates well across tools.</para> 20.318 - 20.319 - <para>At the center of the community sits Linus Torvalds, the 20.320 - creator of Linux. He publishes a single source repository 20.321 - that is considered the <quote>authoritative</quote> current 20.322 - tree by the entire developer community. Anyone can clone 20.323 - Linus's tree, but he is very choosy about whose trees he pulls 20.324 - from.</para> 20.325 - 20.326 - <para>Linus has a number of <quote>trusted lieutenants</quote>. 20.327 - As a general rule, he pulls whatever changes they publish, in 20.328 - most cases without even reviewing those changes. Some of 20.329 - those lieutenants are generally agreed to be 20.330 - <quote>maintainers</quote>, responsible for specific 20.331 - subsystems within the kernel. If a random kernel hacker wants 20.332 - to make a change to a subsystem that they want to end up in 20.333 - Linus's tree, they must find out who the subsystem's 20.334 - maintainer is, and ask that maintainer to take their change. 20.335 - If the maintainer reviews their changes and agrees to take 20.336 - them, they'll pass them along to Linus in due course.</para> 20.337 - 20.338 - <para>Individual lieutenants have their own approaches to 20.339 - reviewing, accepting, and publishing changes; and for deciding 20.340 - when to feed them to Linus. In addition, there are several 20.341 - well known branches that people use for different purposes. 20.342 - For example, a few people maintain <quote>stable</quote> 20.343 - repositories of older versions of the kernel, to which they 20.344 - apply critical fixes as needed. Some maintainers publish 20.345 - multiple trees: one for experimental changes; one for changes 20.346 - that they are about to feed upstream; and so on. Others just 20.347 - publish a single tree.</para> 20.348 - 20.349 - <para>This model has two notable features. The first is that 20.350 - it's <quote>pull only</quote>. You have to ask, convince, or 20.351 - beg another developer to take a change from you, because there 20.352 - are almost no trees to which more than one person can push, 20.353 - and there's no way to push changes into a tree that someone 20.354 - else controls.</para> 20.355 - 20.356 - <para>The second is that it's based on reputation and acclaim. 20.357 - If you're an unknown, Linus will probably ignore changes from 20.358 - you without even responding. But a subsystem maintainer will 20.359 - probably review them, and will likely take them if they pass 20.360 - their criteria for suitability. The more <quote>good</quote> 20.361 - changes you contribute to a maintainer, the more likely they 20.362 - are to trust your judgment and accept your changes. If you're 20.363 - well-known and maintain a long-lived branch for something 20.364 - Linus hasn't yet accepted, people with similar interests may 20.365 - pull your changes regularly to keep up with your work.</para> 20.366 - 20.367 - <para>Reputation and acclaim don't necessarily cross subsystem 20.368 - or <quote>people</quote> boundaries. If you're a respected 20.369 - but specialised storage hacker, and you try to fix a 20.370 - networking bug, that change will receive a level of scrutiny 20.371 - from a network maintainer comparable to a change from a 20.372 - complete stranger.</para> 20.373 - 20.374 - <para>To people who come from more orderly project backgrounds, 20.375 - the comparatively chaotic Linux kernel development process 20.376 - often seems completely insane. It's subject to the whims of 20.377 - individuals; people make sweeping changes whenever they deem 20.378 - it appropriate; and the pace of development is astounding. 20.379 - And yet Linux is a highly successful, well-regarded piece of 20.380 - software.</para> 20.381 - 20.382 - </sect2> 20.383 - <sect2> 20.384 - <title>Pull-only versus shared-push collaboration</title> 20.385 - 20.386 - <para>A perpetual source of heat in the open source community is 20.387 - whether a development model in which people only ever pull 20.388 - changes from others is <quote>better than</quote> one in which 20.389 - multiple people can push changes to a shared 20.390 - repository.</para> 20.391 - 20.392 - <para>Typically, the backers of the shared-push model use tools 20.393 - that actively enforce this approach. If you're using a 20.394 - centralised revision control tool such as Subversion, there's 20.395 - no way to make a choice over which model you'll use: the tool 20.396 - gives you shared-push, and if you want to do anything else, 20.397 - you'll have to roll your own approach on top (such as applying 20.398 - a patch by hand).</para> 20.399 - 20.400 - <para>A good distributed revision control tool, such as 20.401 - Mercurial, will support both models. You and your 20.402 - collaborators can then structure how you work together based 20.403 - on your own needs and preferences, not on what contortions 20.404 - your tools force you into.</para> 20.405 - 20.406 - </sect2> 20.407 - <sect2> 20.408 - <title>Where collaboration meets branch management</title> 20.409 - 20.410 - <para>Once you and your team set up some shared repositories and 20.411 - start propagating changes back and forth between local and 20.412 - shared repos, you begin to face a related, but slightly 20.413 - different challenge: that of managing the multiple directions 20.414 - in which your team may be moving at once. Even though this 20.415 - subject is intimately related to how your team collaborates, 20.416 - it's dense enough to merit treatment of its own, in chapter 20.417 - <xref linkend="chap.branch"/>.</para> 20.418 - 20.419 - </sect2> 20.420 - </sect1> 20.421 - <sect1> 20.422 - <title>The technical side of sharing</title> 20.423 - 20.424 - <para>The remainder of this chapter is devoted to the question of 20.425 - serving data to your collaborators.</para> 20.426 - 20.427 - </sect1> 20.428 - <sect1 id="sec.collab.serve"> 20.429 - <title>Informal sharing with <command role="hg-cmd">hg 20.430 - serve</command></title> 20.431 - 20.432 - <para>Mercurial's <command role="hg-cmd">hg serve</command> 20.433 - command is wonderfully suited to small, tight-knit, and 20.434 - fast-paced group environments. It also provides a great way to 20.435 - get a feel for using Mercurial commands over a network.</para> 20.436 - 20.437 - <para>Run <command role="hg-cmd">hg serve</command> inside a 20.438 - repository, and in under a second it will bring up a specialised 20.439 - HTTP server; this will accept connections from any client, and 20.440 - serve up data for that repository until you terminate it. 20.441 - Anyone who knows the URL of the server you just started, and can 20.442 - talk to your computer over the network, can then use a web 20.443 - browser or Mercurial to read data from that repository. A URL 20.444 - for a <command role="hg-cmd">hg serve</command> instance running 20.445 - on a laptop is likely to look something like 20.446 - <literal>http://my-laptop.local:8000/</literal>.</para> 20.447 - 20.448 - <para>The <command role="hg-cmd">hg serve</command> command is 20.449 - <emphasis>not</emphasis> a general-purpose web server. It can do 20.450 - only two things:</para> 20.451 - <itemizedlist> 20.452 - <listitem><para>Allow people to browse the history of the 20.453 - repository it's serving, from their normal web 20.454 - browsers.</para> 20.455 - </listitem> 20.456 - <listitem><para>Speak Mercurial's wire protocol, so that people 20.457 - can <command role="hg-cmd">hg clone</command> or <command 20.458 - role="hg-cmd">hg pull</command> changes from that 20.459 - repository.</para> 20.460 - </listitem></itemizedlist> 20.461 - <para>In particular, <command role="hg-cmd">hg serve</command> 20.462 - won't allow remote users to <emphasis>modify</emphasis> your 20.463 - repository. It's intended for read-only use.</para> 20.464 - 20.465 - <para>If you're getting started with Mercurial, there's nothing to 20.466 - prevent you from using <command role="hg-cmd">hg serve</command> 20.467 - to serve up a repository on your own computer, then use commands 20.468 - like <command role="hg-cmd">hg clone</command>, <command 20.469 - role="hg-cmd">hg incoming</command>, and so on to talk to that 20.470 - server as if the repository was hosted remotely. This can help 20.471 - you to quickly get acquainted with using commands on 20.472 - network-hosted repositories.</para> 20.473 - 20.474 - <sect2> 20.475 - <title>A few things to keep in mind</title> 20.476 - 20.477 - <para>Because it provides unauthenticated read access to all 20.478 - clients, you should only use <command role="hg-cmd">hg 20.479 - serve</command> in an environment where you either don't 20.480 - care, or have complete control over, who can access your 20.481 - network and pull data from your repository.</para> 20.482 - 20.483 - <para>The <command role="hg-cmd">hg serve</command> command 20.484 - knows nothing about any firewall software you might have 20.485 - installed on your system or network. It cannot detect or 20.486 - control your firewall software. If other people are unable to 20.487 - talk to a running <command role="hg-cmd">hg serve</command> 20.488 - instance, the second thing you should do 20.489 - (<emphasis>after</emphasis> you make sure that they're using 20.490 - the correct URL) is check your firewall configuration.</para> 20.491 - 20.492 - <para>By default, <command role="hg-cmd">hg serve</command> 20.493 - listens for incoming connections on port 8000. If another 20.494 - process is already listening on the port you want to use, you 20.495 - can specify a different port to listen on using the <option 20.496 - role="hg-opt-serve">-p</option> option.</para> 20.497 - 20.498 - <para>Normally, when <command role="hg-cmd">hg serve</command> 20.499 - starts, it prints no output, which can be a bit unnerving. If 20.500 - you'd like to confirm that it is indeed running correctly, and 20.501 - find out what URL you should send to your collaborators, start 20.502 - it with the <option role="hg-opt-global">-v</option> 20.503 - option.</para> 20.504 - 20.505 - </sect2> 20.506 - </sect1> 20.507 - <sect1 id="sec.collab.ssh"> 20.508 - <title>Using the Secure Shell (ssh) protocol</title> 20.509 - 20.510 - <para>You can pull and push changes securely over a network 20.511 - connection using the Secure Shell (<literal>ssh</literal>) 20.512 - protocol. To use this successfully, you may have to do a little 20.513 - bit of configuration on the client or server sides.</para> 20.514 - 20.515 - <para>If you're not familiar with ssh, it's a network protocol 20.516 - that lets you securely communicate with another computer. To 20.517 - use it with Mercurial, you'll be setting up one or more user 20.518 - accounts on a server so that remote users can log in and execute 20.519 - commands.</para> 20.520 - 20.521 - <para>(If you <emphasis>are</emphasis> familiar with ssh, you'll 20.522 - probably find some of the material that follows to be elementary 20.523 - in nature.)</para> 20.524 - 20.525 - <sect2> 20.526 - <title>How to read and write ssh URLs</title> 20.527 - 20.528 - <para>An ssh URL tends to look like this:</para> 20.529 - <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting> 20.530 - <orderedlist> 20.531 - <listitem><para>The <quote><literal>ssh://</literal></quote> 20.532 - part tells Mercurial to use the ssh protocol.</para> 20.533 - </listitem> 20.534 - <listitem><para>The <quote><literal>bos@</literal></quote> 20.535 - component indicates what username to log into the server 20.536 - as. You can leave this out if the remote username is the 20.537 - same as your local username.</para> 20.538 - </listitem> 20.539 - <listitem><para>The 20.540 - <quote><literal>hg.serpentine.com</literal></quote> gives 20.541 - the hostname of the server to log into.</para> 20.542 - </listitem> 20.543 - <listitem><para>The <quote>:22</quote> identifies the port 20.544 - number to connect to the server on. The default port is 20.545 - 22, so you only need to specify a colon and port number if 20.546 - you're <emphasis>not</emphasis> using port 22.</para> 20.547 - </listitem> 20.548 - <listitem><para>The remainder of the URL is the local path to 20.549 - the repository on the server.</para> 20.550 - </listitem></orderedlist> 20.551 - 20.552 - <para>There's plenty of scope for confusion with the path 20.553 - component of ssh URLs, as there is no standard way for tools 20.554 - to interpret it. Some programs behave differently than others 20.555 - when dealing with these paths. This isn't an ideal situation, 20.556 - but it's unlikely to change. Please read the following 20.557 - paragraphs carefully.</para> 20.558 - 20.559 - <para>Mercurial treats the path to a repository on the server as 20.560 - relative to the remote user's home directory. For example, if 20.561 - user <literal>foo</literal> on the server has a home directory 20.562 - of <filename class="directory">/home/foo</filename>, then an 20.563 - ssh URL that contains a path component of <filename 20.564 - class="directory">bar</filename> <emphasis>really</emphasis> 20.565 - refers to the directory <filename 20.566 - class="directory">/home/foo/bar</filename>.</para> 20.567 - 20.568 - <para>If you want to specify a path relative to another user's 20.569 - home directory, you can use a path that starts with a tilde 20.570 - character followed by the user's name (let's call them 20.571 - <literal>otheruser</literal>), like this.</para> 20.572 - <programlisting>ssh://server/~otheruser/hg/repo</programlisting> 20.573 - 20.574 - <para>And if you really want to specify an 20.575 - <emphasis>absolute</emphasis> path on the server, begin the 20.576 - path component with two slashes, as in this example.</para> 20.577 - <programlisting>ssh://server//absolute/path</programlisting> 20.578 - 20.579 - </sect2> 20.580 - <sect2> 20.581 - <title>Finding an ssh client for your system</title> 20.582 - 20.583 - <para>Almost every Unix-like system comes with OpenSSH 20.584 - preinstalled. If you're using such a system, run 20.585 - <literal>which ssh</literal> to find out if the 20.586 - <command>ssh</command> command is installed (it's usually in 20.587 - <filename class="directory">/usr/bin</filename>). In the 20.588 - unlikely event that it isn't present, take a look at your 20.589 - system documentation to figure out how to install it.</para> 20.590 - 20.591 - <para>On Windows, you'll first need to download a suitable ssh 20.592 - client. There are two alternatives.</para> 20.593 - <itemizedlist> 20.594 - <listitem><para>Simon Tatham's excellent PuTTY package 20.595 - <citation>web:putty</citation> provides a complete suite 20.596 - of ssh client commands.</para> 20.597 - </listitem> 20.598 - <listitem><para>If you have a high tolerance for pain, you can 20.599 - use the Cygwin port of OpenSSH.</para> 20.600 - </listitem></itemizedlist> 20.601 - <para>In either case, you'll need to edit your <filename 20.602 - role="special">hg.ini</filename> file to 20.603 - tell Mercurial where to find the actual client command. For 20.604 - example, if you're using PuTTY, you'll need to use the 20.605 - <command>plink</command> command as a command-line ssh 20.606 - client.</para> 20.607 - <programlisting>[ui] 20.608 -ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"</programlisting> 20.609 - 20.610 - <note> 20.611 - <para> The path to <command>plink</command> shouldn't contain 20.612 - any whitespace characters, or Mercurial may not be able to 20.613 - run it correctly (so putting it in <filename 20.614 - class="directory">C:\Program Files</filename> is probably 20.615 - not a good idea).</para> 20.616 - </note> 20.617 - 20.618 - </sect2> 20.619 - <sect2> 20.620 - <title>Generating a key pair</title> 20.621 - 20.622 - <para>To avoid the need to repetitively type a password every 20.623 - time you need to use your ssh client, I recommend generating a 20.624 - key pair. On a Unix-like system, the 20.625 - <command>ssh-keygen</command> command will do the trick. On 20.626 - Windows, if you're using PuTTY, the 20.627 - <command>puttygen</command> command is what you'll 20.628 - need.</para> 20.629 - 20.630 - <para>When you generate a key pair, it's usually 20.631 - <emphasis>highly</emphasis> advisable to protect it with a 20.632 - passphrase. (The only time that you might not want to do this 20.633 - is when you're using the ssh protocol for automated tasks on a 20.634 - secure network.)</para> 20.635 - 20.636 - <para>Simply generating a key pair isn't enough, however. 20.637 - You'll need to add the public key to the set of authorised 20.638 - keys for whatever user you're logging in remotely as. For 20.639 - servers using OpenSSH (the vast majority), this will mean 20.640 - adding the public key to a list in a file called <filename 20.641 - role="special">authorized_keys</filename> in their <filename 20.642 - role="special" class="directory">.ssh</filename> 20.643 - directory.</para> 20.644 - 20.645 - <para>On a Unix-like system, your public key will have a 20.646 - <filename>.pub</filename> extension. If you're using 20.647 - <command>puttygen</command> on Windows, you can save the 20.648 - public key to a file of your choosing, or paste it from the 20.649 - window it's displayed in straight into the <filename 20.650 - role="special">authorized_keys</filename> file.</para> 20.651 - 20.652 - </sect2> 20.653 - <sect2> 20.654 - <title>Using an authentication agent</title> 20.655 - 20.656 - <para>An authentication agent is a daemon that stores 20.657 - passphrases in memory (so it will forget passphrases if you 20.658 - log out and log back in again). An ssh client will notice if 20.659 - it's running, and query it for a passphrase. If there's no 20.660 - authentication agent running, or the agent doesn't store the 20.661 - necessary passphrase, you'll have to type your passphrase 20.662 - every time Mercurial tries to communicate with a server on 20.663 - your behalf (e.g. whenever you pull or push changes).</para> 20.664 - 20.665 - <para>The downside of storing passphrases in an agent is that 20.666 - it's possible for a well-prepared attacker to recover the 20.667 - plain text of your passphrases, in some cases even if your 20.668 - system has been power-cycled. You should make your own 20.669 - judgment as to whether this is an acceptable risk. It 20.670 - certainly saves a lot of repeated typing.</para> 20.671 - 20.672 - <para>On Unix-like systems, the agent is called 20.673 - <command>ssh-agent</command>, and it's often run automatically 20.674 - for you when you log in. You'll need to use the 20.675 - <command>ssh-add</command> command to add passphrases to the 20.676 - agent's store. On Windows, if you're using PuTTY, the 20.677 - <command>pageant</command> command acts as the agent. It adds 20.678 - an icon to your system tray that will let you manage stored 20.679 - passphrases.</para> 20.680 - 20.681 - </sect2> 20.682 - <sect2> 20.683 - <title>Configuring the server side properly</title> 20.684 - 20.685 - <para>Because ssh can be fiddly to set up if you're new to it, 20.686 - there's a variety of things that can go wrong. Add Mercurial 20.687 - on top, and there's plenty more scope for head-scratching. 20.688 - Most of these potential problems occur on the server side, not 20.689 - the client side. The good news is that once you've gotten a 20.690 - configuration working, it will usually continue to work 20.691 - indefinitely.</para> 20.692 - 20.693 - <para>Before you try using Mercurial to talk to an ssh server, 20.694 - it's best to make sure that you can use the normal 20.695 - <command>ssh</command> or <command>putty</command> command to 20.696 - talk to the server first. If you run into problems with using 20.697 - these commands directly, Mercurial surely won't work. Worse, 20.698 - it will obscure the underlying problem. Any time you want to 20.699 - debug ssh-related Mercurial problems, you should drop back to 20.700 - making sure that plain ssh client commands work first, 20.701 - <emphasis>before</emphasis> you worry about whether there's a 20.702 - problem with Mercurial.</para> 20.703 - 20.704 - <para>The first thing to be sure of on the server side is that 20.705 - you can actually log in from another machine at all. If you 20.706 - can't use <command>ssh</command> or <command>putty</command> 20.707 - to log in, the error message you get may give you a few hints 20.708 - as to what's wrong. The most common problems are as 20.709 - follows.</para> 20.710 - <itemizedlist> 20.711 - <listitem><para>If you get a <quote>connection refused</quote> 20.712 - error, either there isn't an SSH daemon running on the 20.713 - server at all, or it's inaccessible due to firewall 20.714 - configuration.</para> 20.715 - </listitem> 20.716 - <listitem><para>If you get a <quote>no route to host</quote> 20.717 - error, you either have an incorrect address for the server 20.718 - or a seriously locked down firewall that won't admit its 20.719 - existence at all.</para> 20.720 - </listitem> 20.721 - <listitem><para>If you get a <quote>permission denied</quote> 20.722 - error, you may have mistyped the username on the server, 20.723 - or you could have mistyped your key's passphrase or the 20.724 - remote user's password.</para> 20.725 - </listitem></itemizedlist> 20.726 - <para>In summary, if you're having trouble talking to the 20.727 - server's ssh daemon, first make sure that one is running at 20.728 - all. On many systems it will be installed, but disabled, by 20.729 - default. Once you're done with this step, you should then 20.730 - check that the server's firewall is configured to allow 20.731 - incoming connections on the port the ssh daemon is listening 20.732 - on (usually 22). Don't worry about more exotic possibilities 20.733 - for misconfiguration until you've checked these two 20.734 - first.</para> 20.735 - 20.736 - <para>If you're using an authentication agent on the client side 20.737 - to store passphrases for your keys, you ought to be able to 20.738 - log into the server without being prompted for a passphrase or 20.739 - a password. If you're prompted for a passphrase, there are a 20.740 - few possible culprits.</para> 20.741 - <itemizedlist> 20.742 - <listitem><para>You might have forgotten to use 20.743 - <command>ssh-add</command> or <command>pageant</command> 20.744 - to store the passphrase.</para> 20.745 - </listitem> 20.746 - <listitem><para>You might have stored the passphrase for the 20.747 - wrong key.</para> 20.748 - </listitem></itemizedlist> 20.749 - <para>If you're being prompted for the remote user's password, 20.750 - there are another few possible problems to check.</para> 20.751 - <itemizedlist> 20.752 - <listitem><para>Either the user's home directory or their 20.753 - <filename role="special" class="directory">.ssh</filename> 20.754 - directory might have excessively liberal permissions. As 20.755 - a result, the ssh daemon will not trust or read their 20.756 - <filename role="special">authorized_keys</filename> file. 20.757 - For example, a group-writable home or <filename 20.758 - role="special" class="directory">.ssh</filename> 20.759 - directory will often cause this symptom.</para> 20.760 - </listitem> 20.761 - <listitem><para>The user's <filename 20.762 - role="special">authorized_keys</filename> file may have 20.763 - a problem. If anyone other than the user owns or can write 20.764 - to that file, the ssh daemon will not trust or read 20.765 - it.</para> 20.766 - </listitem></itemizedlist> 20.767 - 20.768 - <para>In the ideal world, you should be able to run the 20.769 - following command successfully, and it should print exactly 20.770 - one line of output, the current date and time.</para> 20.771 - <programlisting>ssh myserver date</programlisting> 20.772 - 20.773 - <para>If, on your server, you have login scripts that print 20.774 - banners or other junk even when running non-interactive 20.775 - commands like this, you should fix them before you continue, 20.776 - so that they only print output if they're run interactively. 20.777 - Otherwise these banners will at least clutter up Mercurial's 20.778 - output. Worse, they could potentially cause problems with 20.779 - running Mercurial commands remotely. Mercurial makes tries to 20.780 - detect and ignore banners in non-interactive 20.781 - <command>ssh</command> sessions, but it is not foolproof. (If 20.782 - you're editing your login scripts on your server, the usual 20.783 - way to see if a login script is running in an interactive 20.784 - shell is to check the return code from the command 20.785 - <literal>tty -s</literal>.)</para> 20.786 - 20.787 - <para>Once you've verified that plain old ssh is working with 20.788 - your server, the next step is to ensure that Mercurial runs on 20.789 - the server. The following command should run 20.790 - successfully:</para> 20.791 - 20.792 - <programlisting>ssh myserver hg version</programlisting> 20.793 - 20.794 - <para>If you see an error message instead of normal <command 20.795 - role="hg-cmd">hg version</command> output, this is usually 20.796 - because you haven't installed Mercurial to <filename 20.797 - class="directory">/usr/bin</filename>. Don't worry if this 20.798 - is the case; you don't need to do that. But you should check 20.799 - for a few possible problems.</para> 20.800 - <itemizedlist> 20.801 - <listitem><para>Is Mercurial really installed on the server at 20.802 - all? I know this sounds trivial, but it's worth 20.803 - checking!</para> 20.804 - </listitem> 20.805 - <listitem><para>Maybe your shell's search path (usually set 20.806 - via the <envar>PATH</envar> environment variable) is 20.807 - simply misconfigured.</para> 20.808 - </listitem> 20.809 - <listitem><para>Perhaps your <envar>PATH</envar> environment 20.810 - variable is only being set to point to the location of the 20.811 - <command>hg</command> executable if the login session is 20.812 - interactive. This can happen if you're setting the path 20.813 - in the wrong shell login script. See your shell's 20.814 - documentation for details.</para> 20.815 - </listitem> 20.816 - <listitem><para>The <envar>PYTHONPATH</envar> environment 20.817 - variable may need to contain the path to the Mercurial 20.818 - Python modules. It might not be set at all; it could be 20.819 - incorrect; or it may be set only if the login is 20.820 - interactive.</para> 20.821 - </listitem></itemizedlist> 20.822 - 20.823 - <para>If you can run <command role="hg-cmd">hg version</command> 20.824 - over an ssh connection, well done! You've got the server and 20.825 - client sorted out. You should now be able to use Mercurial to 20.826 - access repositories hosted by that username on that server. 20.827 - If you run into problems with Mercurial and ssh at this point, 20.828 - try using the <option role="hg-opt-global">--debug</option> 20.829 - option to get a clearer picture of what's going on.</para> 20.830 - 20.831 - </sect2> 20.832 - <sect2> 20.833 - <title>Using compression with ssh</title> 20.834 - 20.835 - <para>Mercurial does not compress data when it uses the ssh 20.836 - protocol, because the ssh protocol can transparently compress 20.837 - data. However, the default behaviour of ssh clients is 20.838 - <emphasis>not</emphasis> to request compression.</para> 20.839 - 20.840 - <para>Over any network other than a fast LAN (even a wireless 20.841 - network), using compression is likely to significantly speed 20.842 - up Mercurial's network operations. For example, over a WAN, 20.843 - someone measured compression as reducing the amount of time 20.844 - required to clone a particularly large repository from 51 20.845 - minutes to 17 minutes.</para> 20.846 - 20.847 - <para>Both <command>ssh</command> and <command>plink</command> 20.848 - accept a <option role="cmd-opt-ssh">-C</option> option which 20.849 - turns on compression. You can easily edit your <filename 20.850 - role="special">~/.hgrc</filename> to enable compression for 20.851 - all of Mercurial's uses of the ssh protocol.</para> 20.852 - <programlisting>[ui] 20.853 -ssh = ssh -C</programlisting> 20.854 - 20.855 - <para>If you use <command>ssh</command>, you can configure it to 20.856 - always use compression when talking to your server. To do 20.857 - this, edit your <filename 20.858 - role="special">.ssh/config</filename> file (which may not 20.859 - yet exist), as follows.</para> 20.860 - <programlisting>Host hg 20.861 - Compression yes 20.862 - HostName hg.example.com</programlisting> 20.863 - <para>This defines an alias, <literal>hg</literal>. When you 20.864 - use it on the <command>ssh</command> command line or in a 20.865 - Mercurial <literal>ssh</literal>-protocol URL, it will cause 20.866 - <command>ssh</command> to connect to 20.867 - <literal>hg.example.com</literal> and use compression. This 20.868 - gives you both a shorter name to type and compression, each of 20.869 - which is a good thing in its own right.</para> 20.870 - 20.871 - </sect2> 20.872 - </sect1> 20.873 - <sect1 id="sec.collab.cgi"> 20.874 - <title>Serving over HTTP using CGI</title> 20.875 - 20.876 - <para>Depending on how ambitious you are, configuring Mercurial's 20.877 - CGI interface can take anything from a few moments to several 20.878 - hours.</para> 20.879 - 20.880 - <para>We'll begin with the simplest of examples, and work our way 20.881 - towards a more complex configuration. Even for the most basic 20.882 - case, you're almost certainly going to need to read and modify 20.883 - your web server's configuration.</para> 20.884 - 20.885 - <note> 20.886 - <para> Configuring a web server is a complex, fiddly, and 20.887 - highly system-dependent activity. I can't possibly give you 20.888 - instructions that will cover anything like all of the cases 20.889 - you will encounter. Please use your discretion and judgment in 20.890 - following the sections below. Be prepared to make plenty of 20.891 - mistakes, and to spend a lot of time reading your server's 20.892 - error logs.</para> 20.893 - </note> 20.894 - 20.895 - <sect2> 20.896 - <title>Web server configuration checklist</title> 20.897 - 20.898 - <para>Before you continue, do take a few moments to check a few 20.899 - aspects of your system's setup.</para> 20.900 - 20.901 - <orderedlist> 20.902 - <listitem><para>Do you have a web server installed at all? 20.903 - Mac OS X ships with Apache, but many other systems may not 20.904 - have a web server installed.</para> 20.905 - </listitem> 20.906 - <listitem><para>If you have a web server installed, is it 20.907 - actually running? On most systems, even if one is 20.908 - present, it will be disabled by default.</para> 20.909 - </listitem> 20.910 - <listitem><para>Is your server configured to allow you to run 20.911 - CGI programs in the directory where you plan to do so? 20.912 - Most servers default to explicitly disabling the ability 20.913 - to run CGI programs.</para> 20.914 - </listitem></orderedlist> 20.915 - 20.916 - <para>If you don't have a web server installed, and don't have 20.917 - substantial experience configuring Apache, you should consider 20.918 - using the <literal>lighttpd</literal> web server instead of 20.919 - Apache. Apache has a well-deserved reputation for baroque and 20.920 - confusing configuration. While <literal>lighttpd</literal> is 20.921 - less capable in some ways than Apache, most of these 20.922 - capabilities are not relevant to serving Mercurial 20.923 - repositories. And <literal>lighttpd</literal> is undeniably 20.924 - <emphasis>much</emphasis> easier to get started with than 20.925 - Apache.</para> 20.926 - 20.927 - </sect2> 20.928 - <sect2> 20.929 - <title>Basic CGI configuration</title> 20.930 - 20.931 - <para>On Unix-like systems, it's common for users to have a 20.932 - subdirectory named something like <filename 20.933 - class="directory">public_html</filename> in their home 20.934 - directory, from which they can serve up web pages. A file 20.935 - named <filename>foo</filename> in this directory will be 20.936 - accessible at a URL of the form 20.937 - <literal>http://www.example.com/username/foo</literal>.</para> 20.938 - 20.939 - <para>To get started, find the <filename 20.940 - role="special">hgweb.cgi</filename> script that should be 20.941 - present in your Mercurial installation. If you can't quickly 20.942 - find a local copy on your system, simply download one from the 20.943 - master Mercurial repository at <ulink 20.944 - url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para> 20.945 - 20.946 - <para>You'll need to copy this script into your <filename 20.947 - class="directory">public_html</filename> directory, and 20.948 - ensure that it's executable.</para> 20.949 - <programlisting>cp .../hgweb.cgi ~/public_html 20.950 -chmod 755 ~/public_html/hgweb.cgi</programlisting> 20.951 - <para>The <literal>755</literal> argument to 20.952 - <command>chmod</command> is a little more general than just 20.953 - making the script executable: it ensures that the script is 20.954 - executable by anyone, and that <quote>group</quote> and 20.955 - <quote>other</quote> write permissions are 20.956 - <emphasis>not</emphasis> set. If you were to leave those 20.957 - write permissions enabled, Apache's <literal>suexec</literal> 20.958 - subsystem would likely refuse to execute the script. In fact, 20.959 - <literal>suexec</literal> also insists that the 20.960 - <emphasis>directory</emphasis> in which the script resides 20.961 - must not be writable by others.</para> 20.962 - <programlisting>chmod 755 ~/public_html</programlisting> 20.963 - 20.964 - <sect3 id="sec.collab.wtf"> 20.965 - <title>What could <emphasis>possibly</emphasis> go 20.966 - wrong?</title> 20.967 - 20.968 - <para>Once you've copied the CGI script into place, go into a 20.969 - web browser, and try to open the URL <ulink 20.970 - url="http://myhostname/ 20.971 - myuser/hgweb.cgi">http://myhostname/ 20.972 - myuser/hgweb.cgi</ulink>, <emphasis>but</emphasis> brace 20.973 - yourself for instant failure. There's a high probability 20.974 - that trying to visit this URL will fail, and there are many 20.975 - possible reasons for this. In fact, you're likely to 20.976 - stumble over almost every one of the possible errors below, 20.977 - so please read carefully. The following are all of the 20.978 - problems I ran into on a system running Fedora 7, with a 20.979 - fresh installation of Apache, and a user account that I 20.980 - created specially to perform this exercise.</para> 20.981 - 20.982 - <para>Your web server may have per-user directories disabled. 20.983 - If you're using Apache, search your config file for a 20.984 - <literal>UserDir</literal> directive. If there's none 20.985 - present, per-user directories will be disabled. If one 20.986 - exists, but its value is <literal>disabled</literal>, then 20.987 - per-user directories will be disabled. Otherwise, the 20.988 - string after <literal>UserDir</literal> gives the name of 20.989 - the subdirectory that Apache will look in under your home 20.990 - directory, for example <filename 20.991 - class="directory">public_html</filename>.</para> 20.992 - 20.993 - <para>Your file access permissions may be too restrictive. 20.994 - The web server must be able to traverse your home directory 20.995 - and directories under your <filename 20.996 - class="directory">public_html</filename> directory, and 20.997 - read files under the latter too. Here's a quick recipe to 20.998 - help you to make your permissions more appropriate.</para> 20.999 - <programlisting>chmod 755 ~ 20.1000 -find ~/public_html -type d -print0 | xargs -0r chmod 755 20.1001 -find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting> 20.1002 - 20.1003 - <para>The other possibility with permissions is that you might 20.1004 - get a completely empty window when you try to load the 20.1005 - script. In this case, it's likely that your access 20.1006 - permissions are <emphasis>too permissive</emphasis>. Apache's 20.1007 - <literal>suexec</literal> subsystem won't execute a script 20.1008 - that's group- or world-writable, for example.</para> 20.1009 - 20.1010 - <para>Your web server may be configured to disallow execution 20.1011 - of CGI programs in your per-user web directory. Here's 20.1012 - Apache's default per-user configuration from my Fedora 20.1013 - system.</para> 20.1014 - 20.1015 - <programlisting><![CDATA[&ch06-apache-config.lst;]]></programlisting> 20.1016 - 20.1017 - <para>If you find a similar-looking 20.1018 - <literal>Directory</literal> group in your Apache 20.1019 - configuration, the directive to look at inside it is 20.1020 - <literal>Options</literal>. Add <literal>ExecCGI</literal> 20.1021 - to the end of this list if it's missing, and restart the web 20.1022 - server.</para> 20.1023 - 20.1024 - <para>If you find that Apache serves you the text of the CGI 20.1025 - script instead of executing it, you may need to either 20.1026 - uncomment (if already present) or add a directive like 20.1027 - this.</para> 20.1028 - <programlisting>AddHandler cgi-script .cgi</programlisting> 20.1029 - 20.1030 - <para>The next possibility is that you might be served with a 20.1031 - colourful Python backtrace claiming that it can't import a 20.1032 - <literal>mercurial</literal>-related module. This is 20.1033 - actually progress! The server is now capable of executing 20.1034 - your CGI script. This error is only likely to occur if 20.1035 - you're running a private installation of Mercurial, instead 20.1036 - of a system-wide version. Remember that the web server runs 20.1037 - the CGI program without any of the environment variables 20.1038 - that you take for granted in an interactive session. If 20.1039 - this error happens to you, edit your copy of <filename 20.1040 - role="special">hgweb.cgi</filename> and follow the 20.1041 - directions inside it to correctly set your 20.1042 - <envar>PYTHONPATH</envar> environment variable.</para> 20.1043 - 20.1044 - <para>Finally, you are <emphasis>certain</emphasis> to by 20.1045 - served with another colourful Python backtrace: this one 20.1046 - will complain that it can't find <filename 20.1047 - class="directory">/path/to/repository</filename>. Edit 20.1048 - your <filename role="special">hgweb.cgi</filename> script 20.1049 - and replace the <filename 20.1050 - class="directory">/path/to/repository</filename> string 20.1051 - with the complete path to the repository you want to serve 20.1052 - up.</para> 20.1053 - 20.1054 - <para>At this point, when you try to reload the page, you 20.1055 - should be presented with a nice HTML view of your 20.1056 - repository's history. Whew!</para> 20.1057 - 20.1058 - </sect3> 20.1059 - <sect3> 20.1060 - <title>Configuring lighttpd</title> 20.1061 - 20.1062 - <para>To be exhaustive in my experiments, I tried configuring 20.1063 - the increasingly popular <literal>lighttpd</literal> web 20.1064 - server to serve the same repository as I described with 20.1065 - Apache above. I had already overcome all of the problems I 20.1066 - outlined with Apache, many of which are not server-specific. 20.1067 - As a result, I was fairly sure that my file and directory 20.1068 - permissions were good, and that my <filename 20.1069 - role="special">hgweb.cgi</filename> script was properly 20.1070 - edited.</para> 20.1071 - 20.1072 - <para>Once I had Apache running, getting 20.1073 - <literal>lighttpd</literal> to serve the repository was a 20.1074 - snap (in other words, even if you're trying to use 20.1075 - <literal>lighttpd</literal>, you should read the Apache 20.1076 - section). I first had to edit the 20.1077 - <literal>mod_access</literal> section of its config file to 20.1078 - enable <literal>mod_cgi</literal> and 20.1079 - <literal>mod_userdir</literal>, both of which were disabled 20.1080 - by default on my system. I then added a few lines to the 20.1081 - end of the config file, to configure these modules.</para> 20.1082 - <programlisting>userdir.path = "public_html" 20.1083 -cgi.assign = (".cgi" => "" )</programlisting> 20.1084 - <para>With this done, <literal>lighttpd</literal> ran 20.1085 - immediately for me. If I had configured 20.1086 - <literal>lighttpd</literal> before Apache, I'd almost 20.1087 - certainly have run into many of the same system-level 20.1088 - configuration problems as I did with Apache. However, I 20.1089 - found <literal>lighttpd</literal> to be noticeably easier to 20.1090 - configure than Apache, even though I've used Apache for over 20.1091 - a decade, and this was my first exposure to 20.1092 - <literal>lighttpd</literal>.</para> 20.1093 - 20.1094 - </sect3> 20.1095 - </sect2> 20.1096 - <sect2> 20.1097 - <title>Sharing multiple repositories with one CGI script</title> 20.1098 - 20.1099 - <para>The <filename role="special">hgweb.cgi</filename> script 20.1100 - only lets you publish a single repository, which is an 20.1101 - annoying restriction. If you want to publish more than one 20.1102 - without wracking yourself with multiple copies of the same 20.1103 - script, each with different names, a better choice is to use 20.1104 - the <filename role="special">hgwebdir.cgi</filename> 20.1105 - script.</para> 20.1106 - 20.1107 - <para>The procedure to configure <filename 20.1108 - role="special">hgwebdir.cgi</filename> is only a little more 20.1109 - involved than for <filename 20.1110 - role="special">hgweb.cgi</filename>. First, you must obtain 20.1111 - a copy of the script. If you don't have one handy, you can 20.1112 - download a copy from the master Mercurial repository at <ulink 20.1113 - url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para> 20.1114 - 20.1115 - <para>You'll need to copy this script into your <filename 20.1116 - class="directory">public_html</filename> directory, and 20.1117 - ensure that it's executable.</para> 20.1118 - <programlisting>cp .../hgwebdir.cgi ~/public_html 20.1119 -chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting> 20.1120 - <para>With basic configuration out of the way, try to visit 20.1121 - <ulink url="http://myhostname/ 20.1122 - myuser/hgwebdir.cgi">http://myhostname/ 20.1123 - myuser/hgwebdir.cgi</ulink> in your browser. It should 20.1124 - display an empty list of repositories. If you get a blank 20.1125 - window or error message, try walking through the list of 20.1126 - potential problems in section <xref 20.1127 - linkend="sec.collab.wtf"/>.</para> 20.1128 - 20.1129 - <para>The <filename role="special">hgwebdir.cgi</filename> 20.1130 - script relies on an external configuration file. By default, 20.1131 - it searches for a file named <filename 20.1132 - role="special">hgweb.config</filename> in the same directory 20.1133 - as itself. You'll need to create this file, and make it 20.1134 - world-readable. The format of the file is similar to a 20.1135 - Windows <quote>ini</quote> file, as understood by Python's 20.1136 - <literal>ConfigParser</literal> 20.1137 - <citation>web:configparser</citation> module.</para> 20.1138 - 20.1139 - <para>The easiest way to configure <filename 20.1140 - role="special">hgwebdir.cgi</filename> is with a section 20.1141 - named <literal>collections</literal>. This will automatically 20.1142 - publish <emphasis>every</emphasis> repository under the 20.1143 - directories you name. The section should look like 20.1144 - this:</para> 20.1145 - <programlisting>[collections] 20.1146 -/my/root = /my/root</programlisting> 20.1147 - <para>Mercurial interprets this by looking at the directory name 20.1148 - on the <emphasis>right</emphasis> hand side of the 20.1149 - <quote><literal>=</literal></quote> sign; finding repositories 20.1150 - in that directory hierarchy; and using the text on the 20.1151 - <emphasis>left</emphasis> to strip off matching text from the 20.1152 - names it will actually list in the web interface. The 20.1153 - remaining component of a path after this stripping has 20.1154 - occurred is called a <quote>virtual path</quote>.</para> 20.1155 - 20.1156 - <para>Given the example above, if we have a repository whose 20.1157 - local path is <filename 20.1158 - class="directory">/my/root/this/repo</filename>, the CGI 20.1159 - script will strip the leading <filename 20.1160 - class="directory">/my/root</filename> from the name, and 20.1161 - publish the repository with a virtual path of <filename 20.1162 - class="directory">this/repo</filename>. If the base URL for 20.1163 - our CGI script is <ulink url="http://myhostname/ 20.1164 - myuser/hgwebdir.cgi">http://myhostname/ 20.1165 - myuser/hgwebdir.cgi</ulink>, the complete URL for that 20.1166 - repository will be <ulink url="http://myhostname/ 20.1167 - myuser/hgwebdir.cgi/this/repo">http://myhostname/ 20.1168 - myuser/hgwebdir.cgi/this/repo</ulink>.</para> 20.1169 - 20.1170 - <para>If we replace <filename 20.1171 - class="directory">/my/root</filename> on the left hand side 20.1172 - of this example with <filename 20.1173 - class="directory">/my</filename>, then <filename 20.1174 - role="special">hgwebdir.cgi</filename> will only strip off 20.1175 - <filename class="directory">/my</filename> from the repository 20.1176 - name, and will give us a virtual path of <filename 20.1177 - class="directory">root/this/repo</filename> instead of 20.1178 - <filename class="directory">this/repo</filename>.</para> 20.1179 - 20.1180 - <para>The <filename role="special">hgwebdir.cgi</filename> 20.1181 - script will recursively search each directory listed in the 20.1182 - <literal>collections</literal> section of its configuration 20.1183 - file, but it will <literal>not</literal> recurse into the 20.1184 - repositories it finds.</para> 20.1185 - 20.1186 - <para>The <literal>collections</literal> mechanism makes it easy 20.1187 - to publish many repositories in a <quote>fire and 20.1188 - forget</quote> manner. You only need to set up the CGI 20.1189 - script and configuration file one time. Afterwards, you can 20.1190 - publish or unpublish a repository at any time by simply moving 20.1191 - it into, or out of, the directory hierarchy in which you've 20.1192 - configured <filename role="special">hgwebdir.cgi</filename> to 20.1193 - look.</para> 20.1194 - 20.1195 - <sect3> 20.1196 - <title>Explicitly specifying which repositories to 20.1197 - publish</title> 20.1198 - 20.1199 - <para>In addition to the <literal>collections</literal> 20.1200 - mechanism, the <filename 20.1201 - role="special">hgwebdir.cgi</filename> script allows you 20.1202 - to publish a specific list of repositories. To do so, 20.1203 - create a <literal>paths</literal> section, with contents of 20.1204 - the following form.</para> 20.1205 - <programlisting>[paths] 20.1206 -repo1 = /my/path/to/some/repo 20.1207 -repo2 = /some/path/to/another</programlisting> 20.1208 - <para>In this case, the virtual path (the component that will 20.1209 - appear in a URL) is on the left hand side of each 20.1210 - definition, while the path to the repository is on the 20.1211 - right. Notice that there does not need to be any 20.1212 - relationship between the virtual path you choose and the 20.1213 - location of a repository in your filesystem.</para> 20.1214 - 20.1215 - <para>If you wish, you can use both the 20.1216 - <literal>collections</literal> and <literal>paths</literal> 20.1217 - mechanisms simultaneously in a single configuration 20.1218 - file.</para> 20.1219 - 20.1220 - <note> 20.1221 - <para> If multiple repositories have the same virtual path, 20.1222 - <filename role="special">hgwebdir.cgi</filename> will not 20.1223 - report an error. Instead, it will behave 20.1224 - unpredictably.</para> 20.1225 - </note> 20.1226 - 20.1227 - </sect3> 20.1228 - </sect2> 20.1229 - <sect2> 20.1230 - <title>Downloading source archives</title> 20.1231 - 20.1232 - <para>Mercurial's web interface lets users download an archive 20.1233 - of any revision. This archive will contain a snapshot of the 20.1234 - working directory as of that revision, but it will not contain 20.1235 - a copy of the repository data.</para> 20.1236 - 20.1237 - <para>By default, this feature is not enabled. To enable it, 20.1238 - you'll need to add an <envar 20.1239 - role="rc-item-web">allow_archive</envar> item to the 20.1240 - <literal role="rc-web">web</literal> section of your <filename 20.1241 - role="special">~/.hgrc</filename>.</para> 20.1242 - 20.1243 - </sect2> 20.1244 - <sect2> 20.1245 - <title>Web configuration options</title> 20.1246 - 20.1247 - <para>Mercurial's web interfaces (the <command role="hg-cmd">hg 20.1248 - serve</command> command, and the <filename 20.1249 - role="special">hgweb.cgi</filename> and <filename 20.1250 - role="special">hgwebdir.cgi</filename> scripts) have a 20.1251 - number of configuration options that you can set. These 20.1252 - belong in a section named <literal 20.1253 - role="rc-web">web</literal>.</para> 20.1254 - <itemizedlist> 20.1255 - <listitem><para><envar 20.1256 - role="rc-item-web">allow_archive</envar>: Determines 20.1257 - which (if any) archive download mechanisms Mercurial 20.1258 - supports. If you enable this feature, users of the web 20.1259 - interface will be able to download an archive of whatever 20.1260 - revision of a repository they are viewing. To enable the 20.1261 - archive feature, this item must take the form of a 20.1262 - sequence of words drawn from the list below.</para> 20.1263 - <itemizedlist> 20.1264 - <listitem><para><literal>bz2</literal>: A 20.1265 - <command>tar</command> archive, compressed using 20.1266 - <literal>bzip2</literal> compression. This has the 20.1267 - best compression ratio, but uses the most CPU time on 20.1268 - the server.</para> 20.1269 - </listitem> 20.1270 - <listitem><para><literal>gz</literal>: A 20.1271 - <command>tar</command> archive, compressed using 20.1272 - <literal>gzip</literal> compression.</para> 20.1273 - </listitem> 20.1274 - <listitem><para><literal>zip</literal>: A 20.1275 - <command>zip</command> archive, compressed using LZW 20.1276 - compression. This format has the worst compression 20.1277 - ratio, but is widely used in the Windows world.</para> 20.1278 - </listitem> 20.1279 - </itemizedlist> 20.1280 - <para> If you provide an empty list, or don't have an 20.1281 - <envar role="rc-item-web">allow_archive</envar> entry at 20.1282 - all, this feature will be disabled. Here is an example of 20.1283 - how to enable all three supported formats.</para> 20.1284 - <programlisting>[web] 20.1285 -allow_archive = bz2 gz zip</programlisting> 20.1286 - </listitem> 20.1287 - <listitem><para><envar role="rc-item-web">allowpull</envar>: 20.1288 - Boolean. Determines whether the web interface allows 20.1289 - remote users to <command role="hg-cmd">hg pull</command> 20.1290 - and <command role="hg-cmd">hg clone</command> this 20.1291 - repository over HTTP. If set to <literal>no</literal> or 20.1292 - <literal>false</literal>, only the 20.1293 - <quote>human-oriented</quote> portion of the web interface 20.1294 - is available.</para> 20.1295 - </listitem> 20.1296 - <listitem><para><envar role="rc-item-web">contact</envar>: 20.1297 - String. A free-form (but preferably brief) string 20.1298 - identifying the person or group in charge of the 20.1299 - repository. This often contains the name and email 20.1300 - address of a person or mailing list. It often makes sense 20.1301 - to place this entry in a repository's own <filename 20.1302 - role="special">.hg/hgrc</filename> file, but it can make 20.1303 - sense to use in a global <filename 20.1304 - role="special">~/.hgrc</filename> if every repository 20.1305 - has a single maintainer.</para> 20.1306 - </listitem> 20.1307 - <listitem><para><envar role="rc-item-web">maxchanges</envar>: 20.1308 - Integer. The default maximum number of changesets to 20.1309 - display in a single page of output.</para> 20.1310 - </listitem> 20.1311 - <listitem><para><envar role="rc-item-web">maxfiles</envar>: 20.1312 - Integer. The default maximum number of modified files to 20.1313 - display in a single page of output.</para> 20.1314 - </listitem> 20.1315 - <listitem><para><envar role="rc-item-web">stripes</envar>: 20.1316 - Integer. If the web interface displays alternating 20.1317 - <quote>stripes</quote> to make it easier to visually align 20.1318 - rows when you are looking at a table, this number controls 20.1319 - the number of rows in each stripe.</para> 20.1320 - </listitem> 20.1321 - <listitem><para><envar role="rc-item-web">style</envar>: 20.1322 - Controls the template Mercurial uses to display the web 20.1323 - interface. Mercurial ships with two web templates, named 20.1324 - <literal>default</literal> and <literal>gitweb</literal> 20.1325 - (the latter is much more visually attractive). You can 20.1326 - also specify a custom template of your own; see chapter 20.1327 - <xref linkend="chap.template"/> for details. 20.1328 - Here, you can see how to enable the 20.1329 - <literal>gitweb</literal> style.</para> 20.1330 - <programlisting>[web] 20.1331 -style = gitweb</programlisting> 20.1332 - </listitem> 20.1333 - <listitem><para><envar role="rc-item-web">templates</envar>: 20.1334 - Path. The directory in which to search for template 20.1335 - files. By default, Mercurial searches in the directory in 20.1336 - which it was installed.</para> 20.1337 - </listitem></itemizedlist> 20.1338 - <para>If you are using <filename 20.1339 - role="special">hgwebdir.cgi</filename>, you can place a few 20.1340 - configuration items in a <literal role="rc-web">web</literal> 20.1341 - section of the <filename 20.1342 - role="special">hgweb.config</filename> file instead of a 20.1343 - <filename role="special">~/.hgrc</filename> file, for 20.1344 - convenience. These items are <envar 20.1345 - role="rc-item-web">motd</envar> and <envar 20.1346 - role="rc-item-web">style</envar>.</para> 20.1347 - 20.1348 - <sect3> 20.1349 - <title>Options specific to an individual repository</title> 20.1350 - 20.1351 - <para>A few <literal role="rc-web">web</literal> configuration 20.1352 - items ought to be placed in a repository's local <filename 20.1353 - role="special">.hg/hgrc</filename>, rather than a user's 20.1354 - or global <filename role="special">~/.hgrc</filename>.</para> 20.1355 - <itemizedlist> 20.1356 - <listitem><para><envar 20.1357 - role="rc-item-web">description</envar>: String. A 20.1358 - free-form (but preferably brief) string that describes 20.1359 - the contents or purpose of the repository.</para> 20.1360 - </listitem> 20.1361 - <listitem><para><envar role="rc-item-web">name</envar>: 20.1362 - String. The name to use for the repository in the web 20.1363 - interface. This overrides the default name, which is 20.1364 - the last component of the repository's path.</para> 20.1365 - </listitem></itemizedlist> 20.1366 - 20.1367 - </sect3> 20.1368 - <sect3> 20.1369 - <title>Options specific to the <command role="hg-cmd">hg 20.1370 - serve</command> command</title> 20.1371 - 20.1372 - <para>Some of the items in the <literal 20.1373 - role="rc-web">web</literal> section of a <filename 20.1374 - role="special">~/.hgrc</filename> file are only for use 20.1375 - with the <command role="hg-cmd">hg serve</command> 20.1376 - command.</para> 20.1377 - <itemizedlist> 20.1378 - <listitem><para><envar role="rc-item-web">accesslog</envar>: 20.1379 - Path. The name of a file into which to write an access 20.1380 - log. By default, the <command role="hg-cmd">hg 20.1381 - serve</command> command writes this information to 20.1382 - standard output, not to a file. Log entries are written 20.1383 - in the standard <quote>combined</quote> file format used 20.1384 - by almost all web servers.</para> 20.1385 - </listitem> 20.1386 - <listitem><para><envar role="rc-item-web">address</envar>: 20.1387 - String. The local address on which the server should 20.1388 - listen for incoming connections. By default, the server 20.1389 - listens on all addresses.</para> 20.1390 - </listitem> 20.1391 - <listitem><para><envar role="rc-item-web">errorlog</envar>: 20.1392 - Path. The name of a file into which to write an error 20.1393 - log. By default, the <command role="hg-cmd">hg 20.1394 - serve</command> command writes this information to 20.1395 - standard error, not to a file.</para> 20.1396 - </listitem> 20.1397 - <listitem><para><envar role="rc-item-web">ipv6</envar>: 20.1398 - Boolean. Whether to use the IPv6 protocol. By default, 20.1399 - IPv6 is not used.</para> 20.1400 - </listitem> 20.1401 - <listitem><para><envar role="rc-item-web">port</envar>: 20.1402 - Integer. The TCP port number on which the server should 20.1403 - listen. The default port number used is 8000.</para> 20.1404 - </listitem></itemizedlist> 20.1405 - 20.1406 - </sect3> 20.1407 - <sect3> 20.1408 - <title>Choosing the right <filename 20.1409 - role="special">~/.hgrc</filename> file to add <literal 20.1410 - role="rc-web">web</literal> items to</title> 20.1411 - 20.1412 - <para>It is important to remember that a web server like 20.1413 - Apache or <literal>lighttpd</literal> will run under a user 20.1414 - ID that is different to yours. CGI scripts run by your 20.1415 - server, such as <filename 20.1416 - role="special">hgweb.cgi</filename>, will usually also run 20.1417 - under that user ID.</para> 20.1418 - 20.1419 - <para>If you add <literal role="rc-web">web</literal> items to 20.1420 - your own personal <filename role="special">~/.hgrc</filename> file, CGI scripts won't read that 20.1421 - <filename role="special">~/.hgrc</filename> file. Those 20.1422 - settings will thus only affect the behaviour of the <command 20.1423 - role="hg-cmd">hg serve</command> command when you run it. 20.1424 - To cause CGI scripts to see your settings, either create a 20.1425 - <filename role="special">~/.hgrc</filename> file in the 20.1426 - home directory of the user ID that runs your web server, or 20.1427 - add those settings to a system-wide <filename 20.1428 - role="special">~/.hgrc</filename> file.</para> 20.1429 - 20.1430 - 20.1431 - </sect3> 20.1432 - </sect2> 20.1433 - </sect1> 20.1434 -</chapter> 20.1435 - 20.1436 -<!-- 20.1437 -local variables: 20.1438 -sgml-parent-document: ("00book.xml" "book" "chapter") 20.1439 -end: 20.1440 --->
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/en/ch06-filenames.xml Fri Mar 20 16:43:35 2009 +0800 21.3 @@ -0,0 +1,408 @@ 21.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 21.5 + 21.6 +<chapter id="chap.names"> 21.7 + <?dbhtml filename="file-names-and-pattern-matching.html"?> 21.8 + <title>File names and pattern matching</title> 21.9 + 21.10 + <para id="x_543">Mercurial provides mechanisms that let you work with file 21.11 + names in a consistent and expressive way.</para> 21.12 + 21.13 + <sect1> 21.14 + <title>Simple file naming</title> 21.15 + 21.16 + <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the 21.17 + hood</quote> to handle file names. Every command behaves 21.18 + uniformly with respect to file names. The way in which commands 21.19 + work with file names is as follows.</para> 21.20 + 21.21 + <para id="x_545">If you explicitly name real files on the command line, 21.22 + Mercurial works with exactly those files, as you would expect. 21.23 + &interaction.filenames.files;</para> 21.24 + 21.25 + <para id="x_546">When you provide a directory name, Mercurial will interpret 21.26 + this as <quote>operate on every file in this directory and its 21.27 + subdirectories</quote>. Mercurial traverses the files and 21.28 + subdirectories in a directory in alphabetical order. When it 21.29 + encounters a subdirectory, it will traverse that subdirectory 21.30 + before continuing with the current directory.</para> 21.31 + 21.32 + &interaction.filenames.dirs; 21.33 + 21.34 + </sect1> 21.35 + <sect1> 21.36 + <title>Running commands without any file names</title> 21.37 + 21.38 + <para id="x_547">Mercurial's commands that work with file names have useful 21.39 + default behaviours when you invoke them without providing any 21.40 + file names or patterns. What kind of behaviour you should 21.41 + expect depends on what the command does. Here are a few rules 21.42 + of thumb you can use to predict what a command is likely to do 21.43 + if you don't give it any names to work with.</para> 21.44 + <itemizedlist> 21.45 + <listitem><para id="x_548">Most commands will operate on the entire working 21.46 + directory. This is what the <command role="hg-cmd">hg 21.47 + add</command> command does, for example.</para> 21.48 + </listitem> 21.49 + <listitem><para id="x_549">If the command has effects that are difficult or 21.50 + impossible to reverse, it will force you to explicitly 21.51 + provide at least one name or pattern (see below). This 21.52 + protects you from accidentally deleting files by running 21.53 + <command role="hg-cmd">hg remove</command> with no 21.54 + arguments, for example.</para> 21.55 + </listitem></itemizedlist> 21.56 + 21.57 + <para id="x_54a">It's easy to work around these default behaviours if they 21.58 + don't suit you. If a command normally operates on the whole 21.59 + working directory, you can invoke it on just the current 21.60 + directory and its subdirectories by giving it the name 21.61 + <quote><filename class="directory">.</filename></quote>.</para> 21.62 + 21.63 + &interaction.filenames.wdir-subdir; 21.64 + 21.65 + <para id="x_54b">Along the same lines, some commands normally print file 21.66 + names relative to the root of the repository, even if you're 21.67 + invoking them from a subdirectory. Such a command will print 21.68 + file names relative to your subdirectory if you give it explicit 21.69 + names. Here, we're going to run <command role="hg-cmd">hg 21.70 + status</command> from a subdirectory, and get it to operate on 21.71 + the entire working directory while printing file names relative 21.72 + to our subdirectory, by passing it the output of the <command 21.73 + role="hg-cmd">hg root</command> command.</para> 21.74 + 21.75 + &interaction.filenames.wdir-relname; 21.76 + 21.77 + </sect1> 21.78 + <sect1> 21.79 + <title>Telling you what's going on</title> 21.80 + 21.81 + <para id="x_54c">The <command role="hg-cmd">hg add</command> example in the 21.82 + preceding section illustrates something else that's helpful 21.83 + about Mercurial commands. If a command operates on a file that 21.84 + you didn't name explicitly on the command line, it will usually 21.85 + print the name of the file, so that you will not be surprised 21.86 + what's going on.</para> 21.87 + 21.88 + <para id="x_54d">The principle here is of <emphasis>least 21.89 + surprise</emphasis>. If you've exactly named a file on the 21.90 + command line, there's no point in repeating it back at you. If 21.91 + Mercurial is acting on a file <emphasis>implicitly</emphasis>, 21.92 + because you provided no names, or a directory, or a pattern (see 21.93 + below), it's safest to tell you what it's doing.</para> 21.94 + 21.95 + <para id="x_54e">For commands that behave this way, you can silence them 21.96 + using the <option role="hg-opt-global">-q</option> option. You 21.97 + can also get them to print the name of every file, even those 21.98 + you've named explicitly, using the <option 21.99 + role="hg-opt-global">-v</option> option.</para> 21.100 + 21.101 + </sect1> 21.102 + <sect1> 21.103 + <title>Using patterns to identify files</title> 21.104 + 21.105 + <para id="x_54f">In addition to working with file and directory names, 21.106 + Mercurial lets you use <emphasis>patterns</emphasis> to identify 21.107 + files. Mercurial's pattern handling is expressive.</para> 21.108 + 21.109 + <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of 21.110 + matching file names to patterns normally falls to the shell. On 21.111 + these systems, you must explicitly tell Mercurial that a name is 21.112 + a pattern. On Windows, the shell does not expand patterns, so 21.113 + Mercurial will automatically identify names that are patterns, 21.114 + and expand them for you.</para> 21.115 + 21.116 + <para id="x_551">To provide a pattern in place of a regular name on the 21.117 + command line, the mechanism is simple:</para> 21.118 + <programlisting>syntax:patternbody</programlisting> 21.119 + <para id="x_552">That is, a pattern is identified by a short text string that 21.120 + says what kind of pattern this is, followed by a colon, followed 21.121 + by the actual pattern.</para> 21.122 + 21.123 + <para id="x_553">Mercurial supports two kinds of pattern syntax. The most 21.124 + frequently used is called <literal>glob</literal>; this is the 21.125 + same kind of pattern matching used by the Unix shell, and should 21.126 + be familiar to Windows command prompt users, too.</para> 21.127 + 21.128 + <para id="x_554">When Mercurial does automatic pattern matching on Windows, 21.129 + it uses <literal>glob</literal> syntax. You can thus omit the 21.130 + <quote><literal>glob:</literal></quote> prefix on Windows, but 21.131 + it's safe to use it, too.</para> 21.132 + 21.133 + <para id="x_555">The <literal>re</literal> syntax is more powerful; it lets 21.134 + you specify patterns using regular expressions, also known as 21.135 + regexps.</para> 21.136 + 21.137 + <para id="x_556">By the way, in the examples that follow, notice that I'm 21.138 + careful to wrap all of my patterns in quote characters, so that 21.139 + they won't get expanded by the shell before Mercurial sees 21.140 + them.</para> 21.141 + 21.142 + <sect2> 21.143 + <title>Shell-style <literal>glob</literal> patterns</title> 21.144 + 21.145 + <para id="x_557">This is an overview of the kinds of patterns you can use 21.146 + when you're matching on glob patterns.</para> 21.147 + 21.148 + <para id="x_558">The <quote><literal>*</literal></quote> character matches 21.149 + any string, within a single directory.</para> 21.150 + 21.151 + &interaction.filenames.glob.star; 21.152 + 21.153 + <para id="x_559">The <quote><literal>**</literal></quote> pattern matches 21.154 + any string, and crosses directory boundaries. It's not a 21.155 + standard Unix glob token, but it's accepted by several popular 21.156 + Unix shells, and is very useful.</para> 21.157 + 21.158 + &interaction.filenames.glob.starstar; 21.159 + 21.160 + <para id="x_55a">The <quote><literal>?</literal></quote> pattern matches 21.161 + any single character.</para> 21.162 + 21.163 + &interaction.filenames.glob.question; 21.164 + 21.165 + <para id="x_55b">The <quote><literal>[</literal></quote> character begins a 21.166 + <emphasis>character class</emphasis>. This matches any single 21.167 + character within the class. The class ends with a 21.168 + <quote><literal>]</literal></quote> character. A class may 21.169 + contain multiple <emphasis>range</emphasis>s of the form 21.170 + <quote><literal>a-f</literal></quote>, which is shorthand for 21.171 + <quote><literal>abcdef</literal></quote>.</para> 21.172 + 21.173 + &interaction.filenames.glob.range; 21.174 + 21.175 + <para id="x_55c">If the first character after the 21.176 + <quote><literal>[</literal></quote> in a character class is a 21.177 + <quote><literal>!</literal></quote>, it 21.178 + <emphasis>negates</emphasis> the class, making it match any 21.179 + single character not in the class.</para> 21.180 + 21.181 + <para id="x_55d">A <quote><literal>{</literal></quote> begins a group of 21.182 + subpatterns, where the whole group matches if any subpattern 21.183 + in the group matches. The <quote><literal>,</literal></quote> 21.184 + character separates subpatterns, and 21.185 + <quote><literal>}</literal></quote> ends the group.</para> 21.186 + 21.187 + &interaction.filenames.glob.group; 21.188 + 21.189 + <sect3> 21.190 + <title>Watch out!</title> 21.191 + 21.192 + <para id="x_55e">Don't forget that if you want to match a pattern in any 21.193 + directory, you should not be using the 21.194 + <quote><literal>*</literal></quote> match-any token, as this 21.195 + will only match within one directory. Instead, use the 21.196 + <quote><literal>**</literal></quote> token. This small 21.197 + example illustrates the difference between the two.</para> 21.198 + 21.199 + &interaction.filenames.glob.star-starstar; 21.200 + 21.201 + </sect3> 21.202 + </sect2> 21.203 + <sect2> 21.204 + <title>Regular expression matching with <literal>re</literal> 21.205 + patterns</title> 21.206 + 21.207 + <para id="x_55f">Mercurial accepts the same regular expression syntax as 21.208 + the Python programming language (it uses Python's regexp 21.209 + engine internally). This is based on the Perl language's 21.210 + regexp syntax, which is the most popular dialect in use (it's 21.211 + also used in Java, for example).</para> 21.212 + 21.213 + <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail 21.214 + here, as regexps are not often used. Perl-style regexps are 21.215 + in any case already exhaustively documented on a multitude of 21.216 + web sites, and in many books. Instead, I will focus here on a 21.217 + few things you should know if you find yourself needing to use 21.218 + regexps with Mercurial.</para> 21.219 + 21.220 + <para id="x_561">A regexp is matched against an entire file name, relative 21.221 + to the root of the repository. In other words, even if you're 21.222 + already in subbdirectory <filename 21.223 + class="directory">foo</filename>, if you want to match files 21.224 + under this directory, your pattern must start with 21.225 + <quote><literal>foo/</literal></quote>.</para> 21.226 + 21.227 + <para id="x_562">One thing to note, if you're familiar with Perl-style 21.228 + regexps, is that Mercurial's are <emphasis>rooted</emphasis>. 21.229 + That is, a regexp starts matching against the beginning of a 21.230 + string; it doesn't look for a match anywhere within the 21.231 + string. To match anywhere in a string, start your pattern 21.232 + with <quote><literal>.*</literal></quote>.</para> 21.233 + 21.234 + </sect2> 21.235 + </sect1> 21.236 + <sect1> 21.237 + <title>Filtering files</title> 21.238 + 21.239 + <para id="x_563">Not only does Mercurial give you a variety of ways to 21.240 + specify files; it lets you further winnow those files using 21.241 + <emphasis>filters</emphasis>. Commands that work with file 21.242 + names accept two filtering options.</para> 21.243 + <itemizedlist> 21.244 + <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or 21.245 + <option role="hg-opt-global">--include</option>, lets you 21.246 + specify a pattern that file names must match in order to be 21.247 + processed.</para> 21.248 + </listitem> 21.249 + <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or 21.250 + <option role="hg-opt-global">--exclude</option>, gives you a 21.251 + way to <emphasis>avoid</emphasis> processing files, if they 21.252 + match this pattern.</para> 21.253 + </listitem></itemizedlist> 21.254 + <para id="x_566">You can provide multiple <option 21.255 + role="hg-opt-global">-I</option> and <option 21.256 + role="hg-opt-global">-X</option> options on the command line, 21.257 + and intermix them as you please. Mercurial interprets the 21.258 + patterns you provide using glob syntax by default (but you can 21.259 + use regexps if you need to).</para> 21.260 + 21.261 + <para id="x_567">You can read a <option role="hg-opt-global">-I</option> 21.262 + filter as <quote>process only the files that match this 21.263 + filter</quote>.</para> 21.264 + 21.265 + &interaction.filenames.filter.include; 21.266 + 21.267 + <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best 21.268 + read as <quote>process only the files that don't match this 21.269 + pattern</quote>.</para> 21.270 + 21.271 + &interaction.filenames.filter.exclude; 21.272 + 21.273 + </sect1> 21.274 + <sect1> 21.275 + <title>Ignoring unwanted files and directories</title> 21.276 + 21.277 + <para id="x_569">XXX.</para> 21.278 + 21.279 + </sect1> 21.280 + <sect1 id="sec.names.case"> 21.281 + <title>Case sensitivity</title> 21.282 + 21.283 + <para id="x_56a">If you're working in a mixed development environment that 21.284 + contains both Linux (or other Unix) systems and Macs or Windows 21.285 + systems, you should keep in the back of your mind the knowledge 21.286 + that they treat the case (<quote>N</quote> versus 21.287 + <quote>n</quote>) of file names in incompatible ways. This is 21.288 + not very likely to affect you, and it's easy to deal with if it 21.289 + does, but it could surprise you if you don't know about 21.290 + it.</para> 21.291 + 21.292 + <para id="x_56b">Operating systems and filesystems differ in the way they 21.293 + handle the <emphasis>case</emphasis> of characters in file and 21.294 + directory names. There are three common ways to handle case in 21.295 + names.</para> 21.296 + <itemizedlist> 21.297 + <listitem><para id="x_56c">Completely case insensitive. Uppercase and 21.298 + lowercase versions of a letter are treated as identical, 21.299 + both when creating a file and during subsequent accesses. 21.300 + This is common on older DOS-based systems.</para> 21.301 + </listitem> 21.302 + <listitem><para id="x_56d">Case preserving, but insensitive. When a file 21.303 + or directory is created, the case of its name is stored, and 21.304 + can be retrieved and displayed by the operating system. 21.305 + When an existing file is being looked up, its case is 21.306 + ignored. This is the standard arrangement on Windows and 21.307 + MacOS. The names <filename>foo</filename> and 21.308 + <filename>FoO</filename> identify the same file. This 21.309 + treatment of uppercase and lowercase letters as 21.310 + interchangeable is also referred to as <emphasis>case 21.311 + folding</emphasis>.</para> 21.312 + </listitem> 21.313 + <listitem><para id="x_56e">Case sensitive. The case of a name is 21.314 + significant at all times. The names <filename>foo</filename> 21.315 + and {FoO} identify different files. This is the way Linux 21.316 + and Unix systems normally work.</para> 21.317 + </listitem></itemizedlist> 21.318 + 21.319 + <para id="x_56f">On Unix-like systems, it is possible to have any or all of 21.320 + the above ways of handling case in action at once. For example, 21.321 + if you use a USB thumb drive formatted with a FAT32 filesystem 21.322 + on a Linux system, Linux will handle names on that filesystem in 21.323 + a case preserving, but insensitive, way.</para> 21.324 + 21.325 + <sect2> 21.326 + <title>Safe, portable repository storage</title> 21.327 + 21.328 + <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case 21.329 + safe</emphasis>. It translates file names so that they can 21.330 + be safely stored on both case sensitive and case insensitive 21.331 + filesystems. This means that you can use normal file copying 21.332 + tools to transfer a Mercurial repository onto, for example, a 21.333 + USB thumb drive, and safely move that drive and repository 21.334 + back and forth between a Mac, a PC running Windows, and a 21.335 + Linux box.</para> 21.336 + 21.337 + </sect2> 21.338 + <sect2> 21.339 + <title>Detecting case conflicts</title> 21.340 + 21.341 + <para id="x_571">When operating in the working directory, Mercurial honours 21.342 + the naming policy of the filesystem where the working 21.343 + directory is located. If the filesystem is case preserving, 21.344 + but insensitive, Mercurial will treat names that differ only 21.345 + in case as the same.</para> 21.346 + 21.347 + <para id="x_572">An important aspect of this approach is that it is 21.348 + possible to commit a changeset on a case sensitive (typically 21.349 + Linux or Unix) filesystem that will cause trouble for users on 21.350 + case insensitive (usually Windows and MacOS) users. If a 21.351 + Linux user commits changes to two files, one named 21.352 + <filename>myfile.c</filename> and the other named 21.353 + <filename>MyFile.C</filename>, they will be stored correctly 21.354 + in the repository. And in the working directories of other 21.355 + Linux users, they will be correctly represented as separate 21.356 + files.</para> 21.357 + 21.358 + <para id="x_573">If a Windows or Mac user pulls this change, they will not 21.359 + initially have a problem, because Mercurial's repository 21.360 + storage mechanism is case safe. However, once they try to 21.361 + <command role="hg-cmd">hg update</command> the working 21.362 + directory to that changeset, or <command role="hg-cmd">hg 21.363 + merge</command> with that changeset, Mercurial will spot the 21.364 + conflict between the two file names that the filesystem would 21.365 + treat as the same, and forbid the update or merge from 21.366 + occurring.</para> 21.367 + 21.368 + </sect2> 21.369 + <sect2> 21.370 + <title>Fixing a case conflict</title> 21.371 + 21.372 + <para id="x_574">If you are using Windows or a Mac in a mixed environment 21.373 + where some of your collaborators are using Linux or Unix, and 21.374 + Mercurial reports a case folding conflict when you try to 21.375 + <command role="hg-cmd">hg update</command> or <command 21.376 + role="hg-cmd">hg merge</command>, the procedure to fix the 21.377 + problem is simple.</para> 21.378 + 21.379 + <para id="x_575">Just find a nearby Linux or Unix box, clone the problem 21.380 + repository onto it, and use Mercurial's <command 21.381 + role="hg-cmd">hg rename</command> command to change the 21.382 + names of any offending files or directories so that they will 21.383 + no longer cause case folding conflicts. Commit this change, 21.384 + <command role="hg-cmd">hg pull</command> or <command 21.385 + role="hg-cmd">hg push</command> it across to your Windows or 21.386 + MacOS system, and <command role="hg-cmd">hg update</command> 21.387 + to the revision with the non-conflicting names.</para> 21.388 + 21.389 + <para id="x_576">The changeset with case-conflicting names will remain in 21.390 + your project's history, and you still won't be able to 21.391 + <command role="hg-cmd">hg update</command> your working 21.392 + directory to that changeset on a Windows or MacOS system, but 21.393 + you can continue development unimpeded.</para> 21.394 + 21.395 + <note> 21.396 + <para id="x_577"> Prior to version 0.9.3, Mercurial did not use a case 21.397 + safe repository storage mechanism, and did not detect case 21.398 + folding conflicts. If you are using an older version of 21.399 + Mercurial on Windows or MacOS, I strongly recommend that you 21.400 + upgrade.</para> 21.401 + </note> 21.402 + 21.403 + </sect2> 21.404 + </sect1> 21.405 +</chapter> 21.406 + 21.407 +<!-- 21.408 +local variables: 21.409 +sgml-parent-document: ("00book.xml" "book" "chapter") 21.410 +end: 21.411 +-->
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/en/ch07-branch.xml Fri Mar 20 16:43:35 2009 +0800 22.3 @@ -0,0 +1,533 @@ 22.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 22.5 + 22.6 +<chapter id="chap.branch"> 22.7 + <?dbhtml filename="managing-releases-and-branchy-development.html"?> 22.8 + <title>Managing releases and branchy development</title> 22.9 + 22.10 + <para id="x_369">Mercurial provides several mechanisms for you to manage a 22.11 + project that is making progress on multiple fronts at once. To 22.12 + understand these mechanisms, let's first take a brief look at a 22.13 + fairly normal software project structure.</para> 22.14 + 22.15 + <para id="x_36a">Many software projects issue periodic <quote>major</quote> 22.16 + releases that contain substantial new features. In parallel, they 22.17 + may issue <quote>minor</quote> releases. These are usually 22.18 + identical to the major releases off which they're based, but with 22.19 + a few bugs fixed.</para> 22.20 + 22.21 + <para id="x_36b">In this chapter, we'll start by talking about how to keep 22.22 + records of project milestones such as releases. We'll then 22.23 + continue on to talk about the flow of work between different 22.24 + phases of a project, and how Mercurial can help you to isolate and 22.25 + manage this work.</para> 22.26 + 22.27 + <sect1> 22.28 + <title>Giving a persistent name to a revision</title> 22.29 + 22.30 + <para id="x_36c">Once you decide that you'd like to call a particular 22.31 + revision a <quote>release</quote>, it's a good idea to record 22.32 + the identity of that revision. This will let you reproduce that 22.33 + release at a later date, for whatever purpose you might need at 22.34 + the time (reproducing a bug, porting to a new platform, etc). 22.35 + &interaction.tag.init;</para> 22.36 + 22.37 + <para id="x_36d">Mercurial lets you give a permanent name to any revision 22.38 + using the <command role="hg-cmd">hg tag</command> command. Not 22.39 + surprisingly, these names are called <quote>tags</quote>.</para> 22.40 + 22.41 + &interaction.tag.tag; 22.42 + 22.43 + <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote> 22.44 + for a revision. Tags exist purely for your convenience, so that 22.45 + you have a handy permanent way to refer to a revision; Mercurial 22.46 + doesn't interpret the tag names you use in any way. Neither 22.47 + does Mercurial place any restrictions on the name of a tag, 22.48 + beyond a few that are necessary to ensure that a tag can be 22.49 + parsed unambiguously. A tag name cannot contain any of the 22.50 + following characters:</para> 22.51 + <itemizedlist> 22.52 + <listitem><para id="x_36f">Colon (ASCII 58, 22.53 + <quote><literal>:</literal></quote>)</para> 22.54 + </listitem> 22.55 + <listitem><para id="x_370">Carriage return (ASCII 13, 22.56 + <quote><literal>\r</literal></quote>)</para> 22.57 + </listitem> 22.58 + <listitem><para id="x_371">Newline (ASCII 10, 22.59 + <quote><literal>\n</literal></quote>)</para> 22.60 + </listitem></itemizedlist> 22.61 + 22.62 + <para id="x_372">You can use the <command role="hg-cmd">hg tags</command> 22.63 + command to display the tags present in your repository. In the 22.64 + output, each tagged revision is identified first by its name, 22.65 + then by revision number, and finally by the unique hash of the 22.66 + revision.</para> 22.67 + 22.68 + &interaction.tag.tags; 22.69 + 22.70 + <para id="x_373">Notice that <literal>tip</literal> is listed in the output 22.71 + of <command role="hg-cmd">hg tags</command>. The 22.72 + <literal>tip</literal> tag is a special <quote>floating</quote> 22.73 + tag, which always identifies the newest revision in the 22.74 + repository.</para> 22.75 + 22.76 + <para id="x_374">In the output of the <command role="hg-cmd">hg 22.77 + tags</command> command, tags are listed in reverse order, by 22.78 + revision number. This usually means that recent tags are listed 22.79 + before older tags. It also means that <literal>tip</literal> is 22.80 + always going to be the first tag listed in the output of 22.81 + <command role="hg-cmd">hg tags</command>.</para> 22.82 + 22.83 + <para id="x_375">When you run <command role="hg-cmd">hg log</command>, if it 22.84 + displays a revision that has tags associated with it, it will 22.85 + print those tags.</para> 22.86 + 22.87 + &interaction.tag.log; 22.88 + 22.89 + <para id="x_376">Any time you need to provide a revision ID to a Mercurial 22.90 + command, the command will accept a tag name in its place. 22.91 + Internally, Mercurial will translate your tag name into the 22.92 + corresponding revision ID, then use that.</para> 22.93 + 22.94 + &interaction.tag.log.v1.0; 22.95 + 22.96 + <para id="x_377">There's no limit on the number of tags you can have in a 22.97 + repository, or on the number of tags that a single revision can 22.98 + have. As a practical matter, it's not a great idea to have 22.99 + <quote>too many</quote> (a number which will vary from project 22.100 + to project), simply because tags are supposed to help you to 22.101 + find revisions. If you have lots of tags, the ease of using 22.102 + them to identify revisions diminishes rapidly.</para> 22.103 + 22.104 + <para id="x_378">For example, if your project has milestones as frequent as 22.105 + every few days, it's perfectly reasonable to tag each one of 22.106 + those. But if you have a continuous build system that makes 22.107 + sure every revision can be built cleanly, you'd be introducing a 22.108 + lot of noise if you were to tag every clean build. Instead, you 22.109 + could tag failed builds (on the assumption that they're rare!), 22.110 + or simply not use tags to track buildability.</para> 22.111 + 22.112 + <para id="x_379">If you want to remove a tag that you no longer want, use 22.113 + <command role="hg-cmd">hg tag --remove</command>.</para> 22.114 + 22.115 + &interaction.tag.remove; 22.116 + 22.117 + <para id="x_37a">You can also modify a tag at any time, so that it identifies 22.118 + a different revision, by simply issuing a new <command 22.119 + role="hg-cmd">hg tag</command> command. You'll have to use the 22.120 + <option role="hg-opt-tag">-f</option> option to tell Mercurial 22.121 + that you <emphasis>really</emphasis> want to update the 22.122 + tag.</para> 22.123 + 22.124 + &interaction.tag.replace; 22.125 + 22.126 + <para id="x_37b">There will still be a permanent record of the previous 22.127 + identity of the tag, but Mercurial will no longer use it. 22.128 + There's thus no penalty to tagging the wrong revision; all you 22.129 + have to do is turn around and tag the correct revision once you 22.130 + discover your error.</para> 22.131 + 22.132 + <para id="x_37c">Mercurial stores tags in a normal revision-controlled file 22.133 + in your repository. If you've created any tags, you'll find 22.134 + them in a file named <filename 22.135 + role="special">.hgtags</filename>. When you run the <command 22.136 + role="hg-cmd">hg tag</command> command, Mercurial modifies 22.137 + this file, then automatically commits the change to it. This 22.138 + means that every time you run <command role="hg-cmd">hg 22.139 + tag</command>, you'll see a corresponding changeset in the 22.140 + output of <command role="hg-cmd">hg log</command>.</para> 22.141 + 22.142 + &interaction.tag.tip; 22.143 + 22.144 + <sect2> 22.145 + <title>Handling tag conflicts during a merge</title> 22.146 + 22.147 + <para id="x_37d">You won't often need to care about the <filename 22.148 + role="special">.hgtags</filename> file, but it sometimes 22.149 + makes its presence known during a merge. The format of the 22.150 + file is simple: it consists of a series of lines. Each line 22.151 + starts with a changeset hash, followed by a space, followed by 22.152 + the name of a tag.</para> 22.153 + 22.154 + <para id="x_37e">If you're resolving a conflict in the <filename 22.155 + role="special">.hgtags</filename> file during a merge, 22.156 + there's one twist to modifying the <filename 22.157 + role="special">.hgtags</filename> file: when Mercurial is 22.158 + parsing the tags in a repository, it 22.159 + <emphasis>never</emphasis> reads the working copy of the 22.160 + <filename role="special">.hgtags</filename> file. Instead, it 22.161 + reads the <emphasis>most recently committed</emphasis> 22.162 + revision of the file.</para> 22.163 + 22.164 + <para id="x_37f">An unfortunate consequence of this design is that you 22.165 + can't actually verify that your merged <filename 22.166 + role="special">.hgtags</filename> file is correct until 22.167 + <emphasis>after</emphasis> you've committed a change. So if 22.168 + you find yourself resolving a conflict on <filename 22.169 + role="special">.hgtags</filename> during a merge, be sure to 22.170 + run <command role="hg-cmd">hg tags</command> after you commit. 22.171 + If it finds an error in the <filename 22.172 + role="special">.hgtags</filename> file, it will report the 22.173 + location of the error, which you can then fix and commit. You 22.174 + should then run <command role="hg-cmd">hg tags</command> 22.175 + again, just to be sure that your fix is correct.</para> 22.176 + 22.177 + </sect2> 22.178 + <sect2> 22.179 + <title>Tags and cloning</title> 22.180 + 22.181 + <para id="x_380">You may have noticed that the <command role="hg-cmd">hg 22.182 + clone</command> command has a <option 22.183 + role="hg-opt-clone">-r</option> option that lets you clone 22.184 + an exact copy of the repository as of a particular changeset. 22.185 + The new clone will not contain any project history that comes 22.186 + after the revision you specified. This has an interaction 22.187 + with tags that can surprise the unwary.</para> 22.188 + 22.189 + <para id="x_381">Recall that a tag is stored as a revision to the <filename 22.190 + role="special">.hgtags</filename> file, so that when you 22.191 + create a tag, the changeset in which it's recorded necessarily 22.192 + refers to an older changeset. When you run <command 22.193 + role="hg-cmd">hg clone -r foo</command> to clone a 22.194 + repository as of tag <literal>foo</literal>, the new clone 22.195 + <emphasis>will not contain the history that created the 22.196 + tag</emphasis> that you used to clone the repository. The 22.197 + result is that you'll get exactly the right subset of the 22.198 + project's history in the new repository, but 22.199 + <emphasis>not</emphasis> the tag you might have 22.200 + expected.</para> 22.201 + 22.202 + </sect2> 22.203 + <sect2> 22.204 + <title>When permanent tags are too much</title> 22.205 + 22.206 + <para id="x_382">Since Mercurial's tags are revision controlled and carried 22.207 + around with a project's history, everyone you work with will 22.208 + see the tags you create. But giving names to revisions has 22.209 + uses beyond simply noting that revision 22.210 + <literal>4237e45506ee</literal> is really 22.211 + <literal>v2.0.2</literal>. If you're trying to track down a 22.212 + subtle bug, you might want a tag to remind you of something 22.213 + like <quote>Anne saw the symptoms with this 22.214 + revision</quote>.</para> 22.215 + 22.216 + <para id="x_383">For cases like this, what you might want to use are 22.217 + <emphasis>local</emphasis> tags. You can create a local tag 22.218 + with the <option role="hg-opt-tag">-l</option> option to the 22.219 + <command role="hg-cmd">hg tag</command> command. This will 22.220 + store the tag in a file called <filename 22.221 + role="special">.hg/localtags</filename>. Unlike <filename 22.222 + role="special">.hgtags</filename>, <filename 22.223 + role="special">.hg/localtags</filename> is not revision 22.224 + controlled. Any tags you create using <option 22.225 + role="hg-opt-tag">-l</option> remain strictly local to the 22.226 + repository you're currently working in.</para> 22.227 + 22.228 + </sect2> 22.229 + </sect1> 22.230 + <sect1> 22.231 + <title>The flow of changes&emdash;big picture vs. little</title> 22.232 + 22.233 + <para id="x_384">To return to the outline I sketched at the beginning of a 22.234 + chapter, let's think about a project that has multiple 22.235 + concurrent pieces of work under development at once.</para> 22.236 + 22.237 + <para id="x_385">There might be a push for a new <quote>main</quote> release; 22.238 + a new minor bugfix release to the last main release; and an 22.239 + unexpected <quote>hot fix</quote> to an old release that is now 22.240 + in maintenance mode.</para> 22.241 + 22.242 + <para id="x_386">The usual way people refer to these different concurrent 22.243 + directions of development is as <quote>branches</quote>. 22.244 + However, we've already seen numerous times that Mercurial treats 22.245 + <emphasis>all of history</emphasis> as a series of branches and 22.246 + merges. Really, what we have here is two ideas that are 22.247 + peripherally related, but which happen to share a name.</para> 22.248 + <itemizedlist> 22.249 + <listitem><para id="x_387"><quote>Big picture</quote> branches represent 22.250 + the sweep of a project's evolution; people give them names, 22.251 + and talk about them in conversation.</para> 22.252 + </listitem> 22.253 + <listitem><para id="x_388"><quote>Little picture</quote> branches are 22.254 + artefacts of the day-to-day activity of developing and 22.255 + merging changes. They expose the narrative of how the code 22.256 + was developed.</para> 22.257 + </listitem></itemizedlist> 22.258 + 22.259 + </sect1> 22.260 + <sect1> 22.261 + <title>Managing big-picture branches in repositories</title> 22.262 + 22.263 + <para id="x_389">The easiest way to isolate a <quote>big picture</quote> 22.264 + branch in Mercurial is in a dedicated repository. If you have 22.265 + an existing shared repository&emdash;let's call it 22.266 + <literal>myproject</literal>&emdash;that reaches a 22.267 + <quote>1.0</quote> milestone, you can start to prepare for 22.268 + future maintenance releases on top of version 1.0 by tagging the 22.269 + revision from which you prepared the 1.0 release.</para> 22.270 + 22.271 + &interaction.branch-repo.tag; 22.272 + 22.273 + <para id="x_38a">You can then clone a new shared 22.274 + <literal>myproject-1.0.1</literal> repository as of that 22.275 + tag.</para> 22.276 + 22.277 + &interaction.branch-repo.clone; 22.278 + 22.279 + <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought 22.280 + to go into an upcoming 1.0.1 minor release, they clone the 22.281 + <literal>myproject-1.0.1</literal> repository, make their 22.282 + changes, and push them back.</para> 22.283 + 22.284 + &interaction.branch-repo.bugfix; 22.285 + 22.286 + <para id="x_38c">Meanwhile, development for 22.287 + the next major release can continue, isolated and unabated, in 22.288 + the <literal>myproject</literal> repository.</para> 22.289 + 22.290 + &interaction.branch-repo.new; 22.291 + 22.292 + </sect1> 22.293 + <sect1> 22.294 + <title>Don't repeat yourself: merging across branches</title> 22.295 + 22.296 + <para id="x_38d">In many cases, if you have a bug to fix on a maintenance 22.297 + branch, the chances are good that the bug exists on your 22.298 + project's main branch (and possibly other maintenance branches, 22.299 + too). It's a rare developer who wants to fix the same bug 22.300 + multiple times, so let's look at a few ways that Mercurial can 22.301 + help you to manage these bugfixes without duplicating your 22.302 + work.</para> 22.303 + 22.304 + <para id="x_38e">In the simplest instance, all you need to do is pull changes 22.305 + from your maintenance branch into your local clone of the target 22.306 + branch.</para> 22.307 + 22.308 + &interaction.branch-repo.pull; 22.309 + 22.310 + <para id="x_38f">You'll then need to merge the heads of the two branches, and 22.311 + push back to the main branch.</para> 22.312 + 22.313 + &interaction.branch-repo.merge; 22.314 + 22.315 + </sect1> 22.316 + <sect1> 22.317 + <title>Naming branches within one repository</title> 22.318 + 22.319 + <para id="x_390">In most instances, isolating branches in repositories is the 22.320 + right approach. Its simplicity makes it easy to understand; and 22.321 + so it's hard to make mistakes. There's a one-to-one 22.322 + relationship between branches you're working in and directories 22.323 + on your system. This lets you use normal (non-Mercurial-aware) 22.324 + tools to work on files within a branch/repository.</para> 22.325 + 22.326 + <para id="x_391">If you're more in the <quote>power user</quote> category 22.327 + (<emphasis>and</emphasis> your collaborators are too), there is 22.328 + an alternative way of handling branches that you can consider. 22.329 + I've already mentioned the human-level distinction between 22.330 + <quote>small picture</quote> and <quote>big picture</quote> 22.331 + branches. While Mercurial works with multiple <quote>small 22.332 + picture</quote> branches in a repository all the time (for 22.333 + example after you pull changes in, but before you merge them), 22.334 + it can <emphasis>also</emphasis> work with multiple <quote>big 22.335 + picture</quote> branches.</para> 22.336 + 22.337 + <para id="x_392">The key to working this way is that Mercurial lets you 22.338 + assign a persistent <emphasis>name</emphasis> to a branch. 22.339 + There always exists a branch named <literal>default</literal>. 22.340 + Even before you start naming branches yourself, you can find 22.341 + traces of the <literal>default</literal> branch if you look for 22.342 + them.</para> 22.343 + 22.344 + <para id="x_393">As an example, when you run the <command role="hg-cmd">hg 22.345 + commit</command> command, and it pops up your editor so that 22.346 + you can enter a commit message, look for a line that contains 22.347 + the text <quote><literal>HG: branch default</literal></quote> at 22.348 + the bottom. This is telling you that your commit will occur on 22.349 + the branch named <literal>default</literal>.</para> 22.350 + 22.351 + <para id="x_394">To start working with named branches, use the <command 22.352 + role="hg-cmd">hg branches</command> command. This command 22.353 + lists the named branches already present in your repository, 22.354 + telling you which changeset is the tip of each.</para> 22.355 + 22.356 + &interaction.branch-named.branches; 22.357 + 22.358 + <para id="x_395">Since you haven't created any named branches yet, the only 22.359 + one that exists is <literal>default</literal>.</para> 22.360 + 22.361 + <para id="x_396">To find out what the <quote>current</quote> branch is, run 22.362 + the <command role="hg-cmd">hg branch</command> command, giving 22.363 + it no arguments. This tells you what branch the parent of the 22.364 + current changeset is on.</para> 22.365 + 22.366 + &interaction.branch-named.branch; 22.367 + 22.368 + <para id="x_397">To create a new branch, run the <command role="hg-cmd">hg 22.369 + branch</command> command again. This time, give it one 22.370 + argument: the name of the branch you want to create.</para> 22.371 + 22.372 + &interaction.branch-named.create; 22.373 + 22.374 + <para id="x_398">After you've created a branch, you might wonder what effect 22.375 + the <command role="hg-cmd">hg branch</command> command has had. 22.376 + What do the <command role="hg-cmd">hg status</command> and 22.377 + <command role="hg-cmd">hg tip</command> commands report?</para> 22.378 + 22.379 + &interaction.branch-named.status; 22.380 + 22.381 + <para id="x_399">Nothing has changed in the 22.382 + working directory, and there's been no new history created. As 22.383 + this suggests, running the <command role="hg-cmd">hg 22.384 + branch</command> command has no permanent effect; it only 22.385 + tells Mercurial what branch name to use the 22.386 + <emphasis>next</emphasis> time you commit a changeset.</para> 22.387 + 22.388 + <para id="x_39a">When you commit a change, Mercurial records the name of the 22.389 + branch on which you committed. Once you've switched from the 22.390 + <literal>default</literal> branch to another and committed, 22.391 + you'll see the name of the new branch show up in the output of 22.392 + <command role="hg-cmd">hg log</command>, <command 22.393 + role="hg-cmd">hg tip</command>, and other commands that 22.394 + display the same kind of output.</para> 22.395 + 22.396 + &interaction.branch-named.commit; 22.397 + 22.398 + <para id="x_39b">The <command role="hg-cmd">hg log</command>-like commands 22.399 + will print the branch name of every changeset that's not on the 22.400 + <literal>default</literal> branch. As a result, if you never 22.401 + use named branches, you'll never see this information.</para> 22.402 + 22.403 + <para id="x_39c">Once you've named a branch and committed a change with that 22.404 + name, every subsequent commit that descends from that change 22.405 + will inherit the same branch name. You can change the name of a 22.406 + branch at any time, using the <command role="hg-cmd">hg 22.407 + branch</command> command.</para> 22.408 + 22.409 + &interaction.branch-named.rebranch; 22.410 + 22.411 + <para id="x_39d">In practice, this is something you won't do very often, as 22.412 + branch names tend to have fairly long lifetimes. (This isn't a 22.413 + rule, just an observation.)</para> 22.414 + 22.415 + </sect1> 22.416 + <sect1> 22.417 + <title>Dealing with multiple named branches in a 22.418 + repository</title> 22.419 + 22.420 + <para id="x_39e">If you have more than one named branch in a repository, 22.421 + Mercurial will remember the branch that your working directory 22.422 + on when you start a command like <command role="hg-cmd">hg 22.423 + update</command> or <command role="hg-cmd">hg pull 22.424 + -u</command>. It will update the working directory to the tip 22.425 + of this branch, no matter what the <quote>repo-wide</quote> tip 22.426 + is. To update to a revision that's on a different named branch, 22.427 + you may need to use the <option role="hg-opt-update">-C</option> 22.428 + option to <command role="hg-cmd">hg update</command>.</para> 22.429 + 22.430 + <para id="x_39f">This behaviour is a little subtle, so let's see it in 22.431 + action. First, let's remind ourselves what branch we're 22.432 + currently on, and what branches are in our repository.</para> 22.433 + 22.434 + &interaction.branch-named.parents; 22.435 + 22.436 + <para id="x_3a0">We're on the <literal>bar</literal> branch, but there also 22.437 + exists an older <command role="hg-cmd">hg foo</command> 22.438 + branch.</para> 22.439 + 22.440 + <para id="x_3a1">We can <command role="hg-cmd">hg update</command> back and 22.441 + forth between the tips of the <literal>foo</literal> and 22.442 + <literal>bar</literal> branches without needing to use the 22.443 + <option role="hg-opt-update">-C</option> option, because this 22.444 + only involves going backwards and forwards linearly through our 22.445 + change history.</para> 22.446 + 22.447 + &interaction.branch-named.update-switchy; 22.448 + 22.449 + <para id="x_3a2">If we go back to the <literal>foo</literal> branch and then 22.450 + run <command role="hg-cmd">hg update</command>, it will keep us 22.451 + on <literal>foo</literal>, not move us to the tip of 22.452 + <literal>bar</literal>.</para> 22.453 + 22.454 + &interaction.branch-named.update-nothing; 22.455 + 22.456 + <para id="x_3a3">Committing a new change on the <literal>foo</literal> branch 22.457 + introduces a new head.</para> 22.458 + 22.459 + &interaction.branch-named.foo-commit; 22.460 + 22.461 + </sect1> 22.462 + <sect1> 22.463 + <title>Branch names and merging</title> 22.464 + 22.465 + <para id="x_3a4">As you've probably noticed, merges in Mercurial are not 22.466 + symmetrical. Let's say our repository has two heads, 17 and 23. 22.467 + If I <command role="hg-cmd">hg update</command> to 17 and then 22.468 + <command role="hg-cmd">hg merge</command> with 23, Mercurial 22.469 + records 17 as the first parent of the merge, and 23 as the 22.470 + second. Whereas if I <command role="hg-cmd">hg update</command> 22.471 + to 23 and then <command role="hg-cmd">hg merge</command> with 22.472 + 17, it records 23 as the first parent, and 17 as the 22.473 + second.</para> 22.474 + 22.475 + <para id="x_3a5">This affects Mercurial's choice of branch name when you 22.476 + merge. After a merge, Mercurial will retain the branch name of 22.477 + the first parent when you commit the result of the merge. If 22.478 + your first parent's branch name is <literal>foo</literal>, and 22.479 + you merge with <literal>bar</literal>, the branch name will 22.480 + still be <literal>foo</literal> after you merge.</para> 22.481 + 22.482 + <para id="x_3a6">It's not unusual for a repository to contain multiple heads, 22.483 + each with the same branch name. Let's say I'm working on the 22.484 + <literal>foo</literal> branch, and so are you. We commit 22.485 + different changes; I pull your changes; I now have two heads, 22.486 + each claiming to be on the <literal>foo</literal> branch. The 22.487 + result of a merge will be a single head on the 22.488 + <literal>foo</literal> branch, as you might hope.</para> 22.489 + 22.490 + <para id="x_3a7">But if I'm working on the <literal>bar</literal> branch, and 22.491 + I merge work from the <literal>foo</literal> branch, the result 22.492 + will remain on the <literal>bar</literal> branch.</para> 22.493 + 22.494 + &interaction.branch-named.merge; 22.495 + 22.496 + <para id="x_3a8">To give a more concrete example, if I'm working on the 22.497 + <literal>bleeding-edge</literal> branch, and I want to bring in 22.498 + the latest fixes from the <literal>stable</literal> branch, 22.499 + Mercurial will choose the <quote>right</quote> 22.500 + (<literal>bleeding-edge</literal>) branch name when I pull and 22.501 + merge from <literal>stable</literal>.</para> 22.502 + 22.503 + </sect1> 22.504 + <sect1> 22.505 + <title>Branch naming is generally useful</title> 22.506 + 22.507 + <para id="x_3a9">You shouldn't think of named branches as applicable only to 22.508 + situations where you have multiple long-lived branches 22.509 + cohabiting in a single repository. They're very useful even in 22.510 + the one-branch-per-repository case.</para> 22.511 + 22.512 + <para id="x_3aa">In the simplest case, giving a name to each branch gives you 22.513 + a permanent record of which branch a changeset originated on. 22.514 + This gives you more context when you're trying to follow the 22.515 + history of a long-lived branchy project.</para> 22.516 + 22.517 + <para id="x_3ab">If you're working with shared repositories, you can set up a 22.518 + <literal role="hook">pretxnchangegroup</literal> hook on each 22.519 + that will block incoming changes that have the 22.520 + <quote>wrong</quote> branch name. This provides a simple, but 22.521 + effective, defence against people accidentally pushing changes 22.522 + from a <quote>bleeding edge</quote> branch to a 22.523 + <quote>stable</quote> branch. Such a hook might look like this 22.524 + inside the shared repo's <filename role="special"> 22.525 + /.hgrc</filename>.</para> 22.526 + <programlisting>[hooks] 22.527 +pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting> 22.528 + 22.529 + </sect1> 22.530 +</chapter> 22.531 + 22.532 +<!-- 22.533 +local variables: 22.534 +sgml-parent-document: ("00book.xml" "book" "chapter") 22.535 +end: 22.536 +-->
23.1 --- a/en/ch07-filenames.xml Fri Mar 20 15:40:06 2009 +0800 23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 23.3 @@ -1,408 +0,0 @@ 23.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 23.5 - 23.6 -<chapter id="chap.names"> 23.7 - <?dbhtml filename="file-names-and-pattern-matching.html"?> 23.8 - <title>File names and pattern matching</title> 23.9 - 23.10 - <para>Mercurial provides mechanisms that let you work with file 23.11 - names in a consistent and expressive way.</para> 23.12 - 23.13 - <sect1> 23.14 - <title>Simple file naming</title> 23.15 - 23.16 - <para>Mercurial uses a unified piece of machinery <quote>under the 23.17 - hood</quote> to handle file names. Every command behaves 23.18 - uniformly with respect to file names. The way in which commands 23.19 - work with file names is as follows.</para> 23.20 - 23.21 - <para>If you explicitly name real files on the command line, 23.22 - Mercurial works with exactly those files, as you would expect. 23.23 - &interaction.filenames.files;</para> 23.24 - 23.25 - <para>When you provide a directory name, Mercurial will interpret 23.26 - this as <quote>operate on every file in this directory and its 23.27 - subdirectories</quote>. Mercurial traverses the files and 23.28 - subdirectories in a directory in alphabetical order. When it 23.29 - encounters a subdirectory, it will traverse that subdirectory 23.30 - before continuing with the current directory.</para> 23.31 - 23.32 - &interaction.filenames.dirs; 23.33 - 23.34 - </sect1> 23.35 - <sect1> 23.36 - <title>Running commands without any file names</title> 23.37 - 23.38 - <para>Mercurial's commands that work with file names have useful 23.39 - default behaviours when you invoke them without providing any 23.40 - file names or patterns. What kind of behaviour you should 23.41 - expect depends on what the command does. Here are a few rules 23.42 - of thumb you can use to predict what a command is likely to do 23.43 - if you don't give it any names to work with.</para> 23.44 - <itemizedlist> 23.45 - <listitem><para>Most commands will operate on the entire working 23.46 - directory. This is what the <command role="hg-cmd">hg 23.47 - add</command> command does, for example.</para> 23.48 - </listitem> 23.49 - <listitem><para>If the command has effects that are difficult or 23.50 - impossible to reverse, it will force you to explicitly 23.51 - provide at least one name or pattern (see below). This 23.52 - protects you from accidentally deleting files by running 23.53 - <command role="hg-cmd">hg remove</command> with no 23.54 - arguments, for example.</para> 23.55 - </listitem></itemizedlist> 23.56 - 23.57 - <para>It's easy to work around these default behaviours if they 23.58 - don't suit you. If a command normally operates on the whole 23.59 - working directory, you can invoke it on just the current 23.60 - directory and its subdirectories by giving it the name 23.61 - <quote><filename class="directory">.</filename></quote>.</para> 23.62 - 23.63 - &interaction.filenames.wdir-subdir; 23.64 - 23.65 - <para>Along the same lines, some commands normally print file 23.66 - names relative to the root of the repository, even if you're 23.67 - invoking them from a subdirectory. Such a command will print 23.68 - file names relative to your subdirectory if you give it explicit 23.69 - names. Here, we're going to run <command role="hg-cmd">hg 23.70 - status</command> from a subdirectory, and get it to operate on 23.71 - the entire working directory while printing file names relative 23.72 - to our subdirectory, by passing it the output of the <command 23.73 - role="hg-cmd">hg root</command> command.</para> 23.74 - 23.75 - &interaction.filenames.wdir-relname; 23.76 - 23.77 - </sect1> 23.78 - <sect1> 23.79 - <title>Telling you what's going on</title> 23.80 - 23.81 - <para>The <command role="hg-cmd">hg add</command> example in the 23.82 - preceding section illustrates something else that's helpful 23.83 - about Mercurial commands. If a command operates on a file that 23.84 - you didn't name explicitly on the command line, it will usually 23.85 - print the name of the file, so that you will not be surprised 23.86 - what's going on.</para> 23.87 - 23.88 - <para>The principle here is of <emphasis>least 23.89 - surprise</emphasis>. If you've exactly named a file on the 23.90 - command line, there's no point in repeating it back at you. If 23.91 - Mercurial is acting on a file <emphasis>implicitly</emphasis>, 23.92 - because you provided no names, or a directory, or a pattern (see 23.93 - below), it's safest to tell you what it's doing.</para> 23.94 - 23.95 - <para>For commands that behave this way, you can silence them 23.96 - using the <option role="hg-opt-global">-q</option> option. You 23.97 - can also get them to print the name of every file, even those 23.98 - you've named explicitly, using the <option 23.99 - role="hg-opt-global">-v</option> option.</para> 23.100 - 23.101 - </sect1> 23.102 - <sect1> 23.103 - <title>Using patterns to identify files</title> 23.104 - 23.105 - <para>In addition to working with file and directory names, 23.106 - Mercurial lets you use <emphasis>patterns</emphasis> to identify 23.107 - files. Mercurial's pattern handling is expressive.</para> 23.108 - 23.109 - <para>On Unix-like systems (Linux, MacOS, etc.), the job of 23.110 - matching file names to patterns normally falls to the shell. On 23.111 - these systems, you must explicitly tell Mercurial that a name is 23.112 - a pattern. On Windows, the shell does not expand patterns, so 23.113 - Mercurial will automatically identify names that are patterns, 23.114 - and expand them for you.</para> 23.115 - 23.116 - <para>To provide a pattern in place of a regular name on the 23.117 - command line, the mechanism is simple:</para> 23.118 - <programlisting>syntax:patternbody</programlisting> 23.119 - <para>That is, a pattern is identified by a short text string that 23.120 - says what kind of pattern this is, followed by a colon, followed 23.121 - by the actual pattern.</para> 23.122 - 23.123 - <para>Mercurial supports two kinds of pattern syntax. The most 23.124 - frequently used is called <literal>glob</literal>; this is the 23.125 - same kind of pattern matching used by the Unix shell, and should 23.126 - be familiar to Windows command prompt users, too.</para> 23.127 - 23.128 - <para>When Mercurial does automatic pattern matching on Windows, 23.129 - it uses <literal>glob</literal> syntax. You can thus omit the 23.130 - <quote><literal>glob:</literal></quote> prefix on Windows, but 23.131 - it's safe to use it, too.</para> 23.132 - 23.133 - <para>The <literal>re</literal> syntax is more powerful; it lets 23.134 - you specify patterns using regular expressions, also known as 23.135 - regexps.</para> 23.136 - 23.137 - <para>By the way, in the examples that follow, notice that I'm 23.138 - careful to wrap all of my patterns in quote characters, so that 23.139 - they won't get expanded by the shell before Mercurial sees 23.140 - them.</para> 23.141 - 23.142 - <sect2> 23.143 - <title>Shell-style <literal>glob</literal> patterns</title> 23.144 - 23.145 - <para>This is an overview of the kinds of patterns you can use 23.146 - when you're matching on glob patterns.</para> 23.147 - 23.148 - <para>The <quote><literal>*</literal></quote> character matches 23.149 - any string, within a single directory.</para> 23.150 - 23.151 - &interaction.filenames.glob.star; 23.152 - 23.153 - <para>The <quote><literal>**</literal></quote> pattern matches 23.154 - any string, and crosses directory boundaries. It's not a 23.155 - standard Unix glob token, but it's accepted by several popular 23.156 - Unix shells, and is very useful.</para> 23.157 - 23.158 - &interaction.filenames.glob.starstar; 23.159 - 23.160 - <para>The <quote><literal>?</literal></quote> pattern matches 23.161 - any single character.</para> 23.162 - 23.163 - &interaction.filenames.glob.question; 23.164 - 23.165 - <para>The <quote><literal>[</literal></quote> character begins a 23.166 - <emphasis>character class</emphasis>. This matches any single 23.167 - character within the class. The class ends with a 23.168 - <quote><literal>]</literal></quote> character. A class may 23.169 - contain multiple <emphasis>range</emphasis>s of the form 23.170 - <quote><literal>a-f</literal></quote>, which is shorthand for 23.171 - <quote><literal>abcdef</literal></quote>.</para> 23.172 - 23.173 - &interaction.filenames.glob.range; 23.174 - 23.175 - <para>If the first character after the 23.176 - <quote><literal>[</literal></quote> in a character class is a 23.177 - <quote><literal>!</literal></quote>, it 23.178 - <emphasis>negates</emphasis> the class, making it match any 23.179 - single character not in the class.</para> 23.180 - 23.181 - <para>A <quote><literal>{</literal></quote> begins a group of 23.182 - subpatterns, where the whole group matches if any subpattern 23.183 - in the group matches. The <quote><literal>,</literal></quote> 23.184 - character separates subpatterns, and 23.185 - <quote><literal>}</literal></quote> ends the group.</para> 23.186 - 23.187 - &interaction.filenames.glob.group; 23.188 - 23.189 - <sect3> 23.190 - <title>Watch out!</title> 23.191 - 23.192 - <para>Don't forget that if you want to match a pattern in any 23.193 - directory, you should not be using the 23.194 - <quote><literal>*</literal></quote> match-any token, as this 23.195 - will only match within one directory. Instead, use the 23.196 - <quote><literal>**</literal></quote> token. This small 23.197 - example illustrates the difference between the two.</para> 23.198 - 23.199 - &interaction.filenames.glob.star-starstar; 23.200 - 23.201 - </sect3> 23.202 - </sect2> 23.203 - <sect2> 23.204 - <title>Regular expression matching with <literal>re</literal> 23.205 - patterns</title> 23.206 - 23.207 - <para>Mercurial accepts the same regular expression syntax as 23.208 - the Python programming language (it uses Python's regexp 23.209 - engine internally). This is based on the Perl language's 23.210 - regexp syntax, which is the most popular dialect in use (it's 23.211 - also used in Java, for example).</para> 23.212 - 23.213 - <para>I won't discuss Mercurial's regexp dialect in any detail 23.214 - here, as regexps are not often used. Perl-style regexps are 23.215 - in any case already exhaustively documented on a multitude of 23.216 - web sites, and in many books. Instead, I will focus here on a 23.217 - few things you should know if you find yourself needing to use 23.218 - regexps with Mercurial.</para> 23.219 - 23.220 - <para>A regexp is matched against an entire file name, relative 23.221 - to the root of the repository. In other words, even if you're 23.222 - already in subbdirectory <filename 23.223 - class="directory">foo</filename>, if you want to match files 23.224 - under this directory, your pattern must start with 23.225 - <quote><literal>foo/</literal></quote>.</para> 23.226 - 23.227 - <para>One thing to note, if you're familiar with Perl-style 23.228 - regexps, is that Mercurial's are <emphasis>rooted</emphasis>. 23.229 - That is, a regexp starts matching against the beginning of a 23.230 - string; it doesn't look for a match anywhere within the 23.231 - string. To match anywhere in a string, start your pattern 23.232 - with <quote><literal>.*</literal></quote>.</para> 23.233 - 23.234 - </sect2> 23.235 - </sect1> 23.236 - <sect1> 23.237 - <title>Filtering files</title> 23.238 - 23.239 - <para>Not only does Mercurial give you a variety of ways to 23.240 - specify files; it lets you further winnow those files using 23.241 - <emphasis>filters</emphasis>. Commands that work with file 23.242 - names accept two filtering options.</para> 23.243 - <itemizedlist> 23.244 - <listitem><para><option role="hg-opt-global">-I</option>, or 23.245 - <option role="hg-opt-global">--include</option>, lets you 23.246 - specify a pattern that file names must match in order to be 23.247 - processed.</para> 23.248 - </listitem> 23.249 - <listitem><para><option role="hg-opt-global">-X</option>, or 23.250 - <option role="hg-opt-global">--exclude</option>, gives you a 23.251 - way to <emphasis>avoid</emphasis> processing files, if they 23.252 - match this pattern.</para> 23.253 - </listitem></itemizedlist> 23.254 - <para>You can provide multiple <option 23.255 - role="hg-opt-global">-I</option> and <option 23.256 - role="hg-opt-global">-X</option> options on the command line, 23.257 - and intermix them as you please. Mercurial interprets the 23.258 - patterns you provide using glob syntax by default (but you can 23.259 - use regexps if you need to).</para> 23.260 - 23.261 - <para>You can read a <option role="hg-opt-global">-I</option> 23.262 - filter as <quote>process only the files that match this 23.263 - filter</quote>.</para> 23.264 - 23.265 - &interaction.filenames.filter.include; 23.266 - 23.267 - <para>The <option role="hg-opt-global">-X</option> filter is best 23.268 - read as <quote>process only the files that don't match this 23.269 - pattern</quote>.</para> 23.270 - 23.271 - &interaction.filenames.filter.exclude; 23.272 - 23.273 - </sect1> 23.274 - <sect1> 23.275 - <title>Ignoring unwanted files and directories</title> 23.276 - 23.277 - <para>XXX.</para> 23.278 - 23.279 - </sect1> 23.280 - <sect1 id="sec.names.case"> 23.281 - <title>Case sensitivity</title> 23.282 - 23.283 - <para>If you're working in a mixed development environment that 23.284 - contains both Linux (or other Unix) systems and Macs or Windows 23.285 - systems, you should keep in the back of your mind the knowledge 23.286 - that they treat the case (<quote>N</quote> versus 23.287 - <quote>n</quote>) of file names in incompatible ways. This is 23.288 - not very likely to affect you, and it's easy to deal with if it 23.289 - does, but it could surprise you if you don't know about 23.290 - it.</para> 23.291 - 23.292 - <para>Operating systems and filesystems differ in the way they 23.293 - handle the <emphasis>case</emphasis> of characters in file and 23.294 - directory names. There are three common ways to handle case in 23.295 - names.</para> 23.296 - <itemizedlist> 23.297 - <listitem><para>Completely case insensitive. Uppercase and 23.298 - lowercase versions of a letter are treated as identical, 23.299 - both when creating a file and during subsequent accesses. 23.300 - This is common on older DOS-based systems.</para> 23.301 - </listitem> 23.302 - <listitem><para>Case preserving, but insensitive. When a file 23.303 - or directory is created, the case of its name is stored, and 23.304 - can be retrieved and displayed by the operating system. 23.305 - When an existing file is being looked up, its case is 23.306 - ignored. This is the standard arrangement on Windows and 23.307 - MacOS. The names <filename>foo</filename> and 23.308 - <filename>FoO</filename> identify the same file. This 23.309 - treatment of uppercase and lowercase letters as 23.310 - interchangeable is also referred to as <emphasis>case 23.311 - folding</emphasis>.</para> 23.312 - </listitem> 23.313 - <listitem><para>Case sensitive. The case of a name is 23.314 - significant at all times. The names <filename>foo</filename> 23.315 - and {FoO} identify different files. This is the way Linux 23.316 - and Unix systems normally work.</para> 23.317 - </listitem></itemizedlist> 23.318 - 23.319 - <para>On Unix-like systems, it is possible to have any or all of 23.320 - the above ways of handling case in action at once. For example, 23.321 - if you use a USB thumb drive formatted with a FAT32 filesystem 23.322 - on a Linux system, Linux will handle names on that filesystem in 23.323 - a case preserving, but insensitive, way.</para> 23.324 - 23.325 - <sect2> 23.326 - <title>Safe, portable repository storage</title> 23.327 - 23.328 - <para>Mercurial's repository storage mechanism is <emphasis>case 23.329 - safe</emphasis>. It translates file names so that they can 23.330 - be safely stored on both case sensitive and case insensitive 23.331 - filesystems. This means that you can use normal file copying 23.332 - tools to transfer a Mercurial repository onto, for example, a 23.333 - USB thumb drive, and safely move that drive and repository 23.334 - back and forth between a Mac, a PC running Windows, and a 23.335 - Linux box.</para> 23.336 - 23.337 - </sect2> 23.338 - <sect2> 23.339 - <title>Detecting case conflicts</title> 23.340 - 23.341 - <para>When operating in the working directory, Mercurial honours 23.342 - the naming policy of the filesystem where the working 23.343 - directory is located. If the filesystem is case preserving, 23.344 - but insensitive, Mercurial will treat names that differ only 23.345 - in case as the same.</para> 23.346 - 23.347 - <para>An important aspect of this approach is that it is 23.348 - possible to commit a changeset on a case sensitive (typically 23.349 - Linux or Unix) filesystem that will cause trouble for users on 23.350 - case insensitive (usually Windows and MacOS) users. If a 23.351 - Linux user commits changes to two files, one named 23.352 - <filename>myfile.c</filename> and the other named 23.353 - <filename>MyFile.C</filename>, they will be stored correctly 23.354 - in the repository. And in the working directories of other 23.355 - Linux users, they will be correctly represented as separate 23.356 - files.</para> 23.357 - 23.358 - <para>If a Windows or Mac user pulls this change, they will not 23.359 - initially have a problem, because Mercurial's repository 23.360 - storage mechanism is case safe. However, once they try to 23.361 - <command role="hg-cmd">hg update</command> the working 23.362 - directory to that changeset, or <command role="hg-cmd">hg 23.363 - merge</command> with that changeset, Mercurial will spot the 23.364 - conflict between the two file names that the filesystem would 23.365 - treat as the same, and forbid the update or merge from 23.366 - occurring.</para> 23.367 - 23.368 - </sect2> 23.369 - <sect2> 23.370 - <title>Fixing a case conflict</title> 23.371 - 23.372 - <para>If you are using Windows or a Mac in a mixed environment 23.373 - where some of your collaborators are using Linux or Unix, and 23.374 - Mercurial reports a case folding conflict when you try to 23.375 - <command role="hg-cmd">hg update</command> or <command 23.376 - role="hg-cmd">hg merge</command>, the procedure to fix the 23.377 - problem is simple.</para> 23.378 - 23.379 - <para>Just find a nearby Linux or Unix box, clone the problem 23.380 - repository onto it, and use Mercurial's <command 23.381 - role="hg-cmd">hg rename</command> command to change the 23.382 - names of any offending files or directories so that they will 23.383 - no longer cause case folding conflicts. Commit this change, 23.384 - <command role="hg-cmd">hg pull</command> or <command 23.385 - role="hg-cmd">hg push</command> it across to your Windows or 23.386 - MacOS system, and <command role="hg-cmd">hg update</command> 23.387 - to the revision with the non-conflicting names.</para> 23.388 - 23.389 - <para>The changeset with case-conflicting names will remain in 23.390 - your project's history, and you still won't be able to 23.391 - <command role="hg-cmd">hg update</command> your working 23.392 - directory to that changeset on a Windows or MacOS system, but 23.393 - you can continue development unimpeded.</para> 23.394 - 23.395 - <note> 23.396 - <para> Prior to version 0.9.3, Mercurial did not use a case 23.397 - safe repository storage mechanism, and did not detect case 23.398 - folding conflicts. If you are using an older version of 23.399 - Mercurial on Windows or MacOS, I strongly recommend that you 23.400 - upgrade.</para> 23.401 - </note> 23.402 - 23.403 - </sect2> 23.404 - </sect1> 23.405 -</chapter> 23.406 - 23.407 -<!-- 23.408 -local variables: 23.409 -sgml-parent-document: ("00book.xml" "book" "chapter") 23.410 -end: 23.411 --->
24.1 --- a/en/ch08-branch.xml Fri Mar 20 15:40:06 2009 +0800 24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 24.3 @@ -1,533 +0,0 @@ 24.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 24.5 - 24.6 -<chapter id="chap.branch"> 24.7 - <?dbhtml filename="managing-releases-and-branchy-development.html"?> 24.8 - <title>Managing releases and branchy development</title> 24.9 - 24.10 - <para>Mercurial provides several mechanisms for you to manage a 24.11 - project that is making progress on multiple fronts at once. To 24.12 - understand these mechanisms, let's first take a brief look at a 24.13 - fairly normal software project structure.</para> 24.14 - 24.15 - <para>Many software projects issue periodic <quote>major</quote> 24.16 - releases that contain substantial new features. In parallel, they 24.17 - may issue <quote>minor</quote> releases. These are usually 24.18 - identical to the major releases off which they're based, but with 24.19 - a few bugs fixed.</para> 24.20 - 24.21 - <para>In this chapter, we'll start by talking about how to keep 24.22 - records of project milestones such as releases. We'll then 24.23 - continue on to talk about the flow of work between different 24.24 - phases of a project, and how Mercurial can help you to isolate and 24.25 - manage this work.</para> 24.26 - 24.27 - <sect1> 24.28 - <title>Giving a persistent name to a revision</title> 24.29 - 24.30 - <para>Once you decide that you'd like to call a particular 24.31 - revision a <quote>release</quote>, it's a good idea to record 24.32 - the identity of that revision. This will let you reproduce that 24.33 - release at a later date, for whatever purpose you might need at 24.34 - the time (reproducing a bug, porting to a new platform, etc). 24.35 - &interaction.tag.init;</para> 24.36 - 24.37 - <para>Mercurial lets you give a permanent name to any revision 24.38 - using the <command role="hg-cmd">hg tag</command> command. Not 24.39 - surprisingly, these names are called <quote>tags</quote>.</para> 24.40 - 24.41 - &interaction.tag.tag; 24.42 - 24.43 - <para>A tag is nothing more than a <quote>symbolic name</quote> 24.44 - for a revision. Tags exist purely for your convenience, so that 24.45 - you have a handy permanent way to refer to a revision; Mercurial 24.46 - doesn't interpret the tag names you use in any way. Neither 24.47 - does Mercurial place any restrictions on the name of a tag, 24.48 - beyond a few that are necessary to ensure that a tag can be 24.49 - parsed unambiguously. A tag name cannot contain any of the 24.50 - following characters:</para> 24.51 - <itemizedlist> 24.52 - <listitem><para>Colon (ASCII 58, 24.53 - <quote><literal>:</literal></quote>)</para> 24.54 - </listitem> 24.55 - <listitem><para>Carriage return (ASCII 13, 24.56 - <quote><literal>\r</literal></quote>)</para> 24.57 - </listitem> 24.58 - <listitem><para>Newline (ASCII 10, 24.59 - <quote><literal>\n</literal></quote>)</para> 24.60 - </listitem></itemizedlist> 24.61 - 24.62 - <para>You can use the <command role="hg-cmd">hg tags</command> 24.63 - command to display the tags present in your repository. In the 24.64 - output, each tagged revision is identified first by its name, 24.65 - then by revision number, and finally by the unique hash of the 24.66 - revision.</para> 24.67 - 24.68 - &interaction.tag.tags; 24.69 - 24.70 - <para>Notice that <literal>tip</literal> is listed in the output 24.71 - of <command role="hg-cmd">hg tags</command>. The 24.72 - <literal>tip</literal> tag is a special <quote>floating</quote> 24.73 - tag, which always identifies the newest revision in the 24.74 - repository.</para> 24.75 - 24.76 - <para>In the output of the <command role="hg-cmd">hg 24.77 - tags</command> command, tags are listed in reverse order, by 24.78 - revision number. This usually means that recent tags are listed 24.79 - before older tags. It also means that <literal>tip</literal> is 24.80 - always going to be the first tag listed in the output of 24.81 - <command role="hg-cmd">hg tags</command>.</para> 24.82 - 24.83 - <para>When you run <command role="hg-cmd">hg log</command>, if it 24.84 - displays a revision that has tags associated with it, it will 24.85 - print those tags.</para> 24.86 - 24.87 - &interaction.tag.log; 24.88 - 24.89 - <para>Any time you need to provide a revision ID to a Mercurial 24.90 - command, the command will accept a tag name in its place. 24.91 - Internally, Mercurial will translate your tag name into the 24.92 - corresponding revision ID, then use that.</para> 24.93 - 24.94 - &interaction.tag.log.v1.0; 24.95 - 24.96 - <para>There's no limit on the number of tags you can have in a 24.97 - repository, or on the number of tags that a single revision can 24.98 - have. As a practical matter, it's not a great idea to have 24.99 - <quote>too many</quote> (a number which will vary from project 24.100 - to project), simply because tags are supposed to help you to 24.101 - find revisions. If you have lots of tags, the ease of using 24.102 - them to identify revisions diminishes rapidly.</para> 24.103 - 24.104 - <para>For example, if your project has milestones as frequent as 24.105 - every few days, it's perfectly reasonable to tag each one of 24.106 - those. But if you have a continuous build system that makes 24.107 - sure every revision can be built cleanly, you'd be introducing a 24.108 - lot of noise if you were to tag every clean build. Instead, you 24.109 - could tag failed builds (on the assumption that they're rare!), 24.110 - or simply not use tags to track buildability.</para> 24.111 - 24.112 - <para>If you want to remove a tag that you no longer want, use 24.113 - <command role="hg-cmd">hg tag --remove</command>.</para> 24.114 - 24.115 - &interaction.tag.remove; 24.116 - 24.117 - <para>You can also modify a tag at any time, so that it identifies 24.118 - a different revision, by simply issuing a new <command 24.119 - role="hg-cmd">hg tag</command> command. You'll have to use the 24.120 - <option role="hg-opt-tag">-f</option> option to tell Mercurial 24.121 - that you <emphasis>really</emphasis> want to update the 24.122 - tag.</para> 24.123 - 24.124 - &interaction.tag.replace; 24.125 - 24.126 - <para>There will still be a permanent record of the previous 24.127 - identity of the tag, but Mercurial will no longer use it. 24.128 - There's thus no penalty to tagging the wrong revision; all you 24.129 - have to do is turn around and tag the correct revision once you 24.130 - discover your error.</para> 24.131 - 24.132 - <para>Mercurial stores tags in a normal revision-controlled file 24.133 - in your repository. If you've created any tags, you'll find 24.134 - them in a file named <filename 24.135 - role="special">.hgtags</filename>. When you run the <command 24.136 - role="hg-cmd">hg tag</command> command, Mercurial modifies 24.137 - this file, then automatically commits the change to it. This 24.138 - means that every time you run <command role="hg-cmd">hg 24.139 - tag</command>, you'll see a corresponding changeset in the 24.140 - output of <command role="hg-cmd">hg log</command>.</para> 24.141 - 24.142 - &interaction.tag.tip; 24.143 - 24.144 - <sect2> 24.145 - <title>Handling tag conflicts during a merge</title> 24.146 - 24.147 - <para>You won't often need to care about the <filename 24.148 - role="special">.hgtags</filename> file, but it sometimes 24.149 - makes its presence known during a merge. The format of the 24.150 - file is simple: it consists of a series of lines. Each line 24.151 - starts with a changeset hash, followed by a space, followed by 24.152 - the name of a tag.</para> 24.153 - 24.154 - <para>If you're resolving a conflict in the <filename 24.155 - role="special">.hgtags</filename> file during a merge, 24.156 - there's one twist to modifying the <filename 24.157 - role="special">.hgtags</filename> file: when Mercurial is 24.158 - parsing the tags in a repository, it 24.159 - <emphasis>never</emphasis> reads the working copy of the 24.160 - <filename role="special">.hgtags</filename> file. Instead, it 24.161 - reads the <emphasis>most recently committed</emphasis> 24.162 - revision of the file.</para> 24.163 - 24.164 - <para>An unfortunate consequence of this design is that you 24.165 - can't actually verify that your merged <filename 24.166 - role="special">.hgtags</filename> file is correct until 24.167 - <emphasis>after</emphasis> you've committed a change. So if 24.168 - you find yourself resolving a conflict on <filename 24.169 - role="special">.hgtags</filename> during a merge, be sure to 24.170 - run <command role="hg-cmd">hg tags</command> after you commit. 24.171 - If it finds an error in the <filename 24.172 - role="special">.hgtags</filename> file, it will report the 24.173 - location of the error, which you can then fix and commit. You 24.174 - should then run <command role="hg-cmd">hg tags</command> 24.175 - again, just to be sure that your fix is correct.</para> 24.176 - 24.177 - </sect2> 24.178 - <sect2> 24.179 - <title>Tags and cloning</title> 24.180 - 24.181 - <para>You may have noticed that the <command role="hg-cmd">hg 24.182 - clone</command> command has a <option 24.183 - role="hg-opt-clone">-r</option> option that lets you clone 24.184 - an exact copy of the repository as of a particular changeset. 24.185 - The new clone will not contain any project history that comes 24.186 - after the revision you specified. This has an interaction 24.187 - with tags that can surprise the unwary.</para> 24.188 - 24.189 - <para>Recall that a tag is stored as a revision to the <filename 24.190 - role="special">.hgtags</filename> file, so that when you 24.191 - create a tag, the changeset in which it's recorded necessarily 24.192 - refers to an older changeset. When you run <command 24.193 - role="hg-cmd">hg clone -r foo</command> to clone a 24.194 - repository as of tag <literal>foo</literal>, the new clone 24.195 - <emphasis>will not contain the history that created the 24.196 - tag</emphasis> that you used to clone the repository. The 24.197 - result is that you'll get exactly the right subset of the 24.198 - project's history in the new repository, but 24.199 - <emphasis>not</emphasis> the tag you might have 24.200 - expected.</para> 24.201 - 24.202 - </sect2> 24.203 - <sect2> 24.204 - <title>When permanent tags are too much</title> 24.205 - 24.206 - <para>Since Mercurial's tags are revision controlled and carried 24.207 - around with a project's history, everyone you work with will 24.208 - see the tags you create. But giving names to revisions has 24.209 - uses beyond simply noting that revision 24.210 - <literal>4237e45506ee</literal> is really 24.211 - <literal>v2.0.2</literal>. If you're trying to track down a 24.212 - subtle bug, you might want a tag to remind you of something 24.213 - like <quote>Anne saw the symptoms with this 24.214 - revision</quote>.</para> 24.215 - 24.216 - <para>For cases like this, what you might want to use are 24.217 - <emphasis>local</emphasis> tags. You can create a local tag 24.218 - with the <option role="hg-opt-tag">-l</option> option to the 24.219 - <command role="hg-cmd">hg tag</command> command. This will 24.220 - store the tag in a file called <filename 24.221 - role="special">.hg/localtags</filename>. Unlike <filename 24.222 - role="special">.hgtags</filename>, <filename 24.223 - role="special">.hg/localtags</filename> is not revision 24.224 - controlled. Any tags you create using <option 24.225 - role="hg-opt-tag">-l</option> remain strictly local to the 24.226 - repository you're currently working in.</para> 24.227 - 24.228 - </sect2> 24.229 - </sect1> 24.230 - <sect1> 24.231 - <title>The flow of changes&emdash;big picture vs. little</title> 24.232 - 24.233 - <para>To return to the outline I sketched at the beginning of a 24.234 - chapter, let's think about a project that has multiple 24.235 - concurrent pieces of work under development at once.</para> 24.236 - 24.237 - <para>There might be a push for a new <quote>main</quote> release; 24.238 - a new minor bugfix release to the last main release; and an 24.239 - unexpected <quote>hot fix</quote> to an old release that is now 24.240 - in maintenance mode.</para> 24.241 - 24.242 - <para>The usual way people refer to these different concurrent 24.243 - directions of development is as <quote>branches</quote>. 24.244 - However, we've already seen numerous times that Mercurial treats 24.245 - <emphasis>all of history</emphasis> as a series of branches and 24.246 - merges. Really, what we have here is two ideas that are 24.247 - peripherally related, but which happen to share a name.</para> 24.248 - <itemizedlist> 24.249 - <listitem><para><quote>Big picture</quote> branches represent 24.250 - the sweep of a project's evolution; people give them names, 24.251 - and talk about them in conversation.</para> 24.252 - </listitem> 24.253 - <listitem><para><quote>Little picture</quote> branches are 24.254 - artefacts of the day-to-day activity of developing and 24.255 - merging changes. They expose the narrative of how the code 24.256 - was developed.</para> 24.257 - </listitem></itemizedlist> 24.258 - 24.259 - </sect1> 24.260 - <sect1> 24.261 - <title>Managing big-picture branches in repositories</title> 24.262 - 24.263 - <para>The easiest way to isolate a <quote>big picture</quote> 24.264 - branch in Mercurial is in a dedicated repository. If you have 24.265 - an existing shared repository&emdash;let's call it 24.266 - <literal>myproject</literal>&emdash;that reaches a 24.267 - <quote>1.0</quote> milestone, you can start to prepare for 24.268 - future maintenance releases on top of version 1.0 by tagging the 24.269 - revision from which you prepared the 1.0 release.</para> 24.270 - 24.271 - &interaction.branch-repo.tag; 24.272 - 24.273 - <para>You can then clone a new shared 24.274 - <literal>myproject-1.0.1</literal> repository as of that 24.275 - tag.</para> 24.276 - 24.277 - &interaction.branch-repo.clone; 24.278 - 24.279 - <para>Afterwards, if someone needs to work on a bug fix that ought 24.280 - to go into an upcoming 1.0.1 minor release, they clone the 24.281 - <literal>myproject-1.0.1</literal> repository, make their 24.282 - changes, and push them back.</para> 24.283 - 24.284 - &interaction.branch-repo.bugfix; 24.285 - 24.286 - <para>Meanwhile, development for 24.287 - the next major release can continue, isolated and unabated, in 24.288 - the <literal>myproject</literal> repository.</para> 24.289 - 24.290 - &interaction.branch-repo.new; 24.291 - 24.292 - </sect1> 24.293 - <sect1> 24.294 - <title>Don't repeat yourself: merging across branches</title> 24.295 - 24.296 - <para>In many cases, if you have a bug to fix on a maintenance 24.297 - branch, the chances are good that the bug exists on your 24.298 - project's main branch (and possibly other maintenance branches, 24.299 - too). It's a rare developer who wants to fix the same bug 24.300 - multiple times, so let's look at a few ways that Mercurial can 24.301 - help you to manage these bugfixes without duplicating your 24.302 - work.</para> 24.303 - 24.304 - <para>In the simplest instance, all you need to do is pull changes 24.305 - from your maintenance branch into your local clone of the target 24.306 - branch.</para> 24.307 - 24.308 - &interaction.branch-repo.pull; 24.309 - 24.310 - <para>You'll then need to merge the heads of the two branches, and 24.311 - push back to the main branch.</para> 24.312 - 24.313 - &interaction.branch-repo.merge; 24.314 - 24.315 - </sect1> 24.316 - <sect1> 24.317 - <title>Naming branches within one repository</title> 24.318 - 24.319 - <para>In most instances, isolating branches in repositories is the 24.320 - right approach. Its simplicity makes it easy to understand; and 24.321 - so it's hard to make mistakes. There's a one-to-one 24.322 - relationship between branches you're working in and directories 24.323 - on your system. This lets you use normal (non-Mercurial-aware) 24.324 - tools to work on files within a branch/repository.</para> 24.325 - 24.326 - <para>If you're more in the <quote>power user</quote> category 24.327 - (<emphasis>and</emphasis> your collaborators are too), there is 24.328 - an alternative way of handling branches that you can consider. 24.329 - I've already mentioned the human-level distinction between 24.330 - <quote>small picture</quote> and <quote>big picture</quote> 24.331 - branches. While Mercurial works with multiple <quote>small 24.332 - picture</quote> branches in a repository all the time (for 24.333 - example after you pull changes in, but before you merge them), 24.334 - it can <emphasis>also</emphasis> work with multiple <quote>big 24.335 - picture</quote> branches.</para> 24.336 - 24.337 - <para>The key to working this way is that Mercurial lets you 24.338 - assign a persistent <emphasis>name</emphasis> to a branch. 24.339 - There always exists a branch named <literal>default</literal>. 24.340 - Even before you start naming branches yourself, you can find 24.341 - traces of the <literal>default</literal> branch if you look for 24.342 - them.</para> 24.343 - 24.344 - <para>As an example, when you run the <command role="hg-cmd">hg 24.345 - commit</command> command, and it pops up your editor so that 24.346 - you can enter a commit message, look for a line that contains 24.347 - the text <quote><literal>HG: branch default</literal></quote> at 24.348 - the bottom. This is telling you that your commit will occur on 24.349 - the branch named <literal>default</literal>.</para> 24.350 - 24.351 - <para>To start working with named branches, use the <command 24.352 - role="hg-cmd">hg branches</command> command. This command 24.353 - lists the named branches already present in your repository, 24.354 - telling you which changeset is the tip of each.</para> 24.355 - 24.356 - &interaction.branch-named.branches; 24.357 - 24.358 - <para>Since you haven't created any named branches yet, the only 24.359 - one that exists is <literal>default</literal>.</para> 24.360 - 24.361 - <para>To find out what the <quote>current</quote> branch is, run 24.362 - the <command role="hg-cmd">hg branch</command> command, giving 24.363 - it no arguments. This tells you what branch the parent of the 24.364 - current changeset is on.</para> 24.365 - 24.366 - &interaction.branch-named.branch; 24.367 - 24.368 - <para>To create a new branch, run the <command role="hg-cmd">hg 24.369 - branch</command> command again. This time, give it one 24.370 - argument: the name of the branch you want to create.</para> 24.371 - 24.372 - &interaction.branch-named.create; 24.373 - 24.374 - <para>After you've created a branch, you might wonder what effect 24.375 - the <command role="hg-cmd">hg branch</command> command has had. 24.376 - What do the <command role="hg-cmd">hg status</command> and 24.377 - <command role="hg-cmd">hg tip</command> commands report?</para> 24.378 - 24.379 - &interaction.branch-named.status; 24.380 - 24.381 - <para>Nothing has changed in the 24.382 - working directory, and there's been no new history created. As 24.383 - this suggests, running the <command role="hg-cmd">hg 24.384 - branch</command> command has no permanent effect; it only 24.385 - tells Mercurial what branch name to use the 24.386 - <emphasis>next</emphasis> time you commit a changeset.</para> 24.387 - 24.388 - <para>When you commit a change, Mercurial records the name of the 24.389 - branch on which you committed. Once you've switched from the 24.390 - <literal>default</literal> branch to another and committed, 24.391 - you'll see the name of the new branch show up in the output of 24.392 - <command role="hg-cmd">hg log</command>, <command 24.393 - role="hg-cmd">hg tip</command>, and other commands that 24.394 - display the same kind of output.</para> 24.395 - 24.396 - &interaction.branch-named.commit; 24.397 - 24.398 - <para>The <command role="hg-cmd">hg log</command>-like commands 24.399 - will print the branch name of every changeset that's not on the 24.400 - <literal>default</literal> branch. As a result, if you never 24.401 - use named branches, you'll never see this information.</para> 24.402 - 24.403 - <para>Once you've named a branch and committed a change with that 24.404 - name, every subsequent commit that descends from that change 24.405 - will inherit the same branch name. You can change the name of a 24.406 - branch at any time, using the <command role="hg-cmd">hg 24.407 - branch</command> command.</para> 24.408 - 24.409 - &interaction.branch-named.rebranch; 24.410 - 24.411 - <para>In practice, this is something you won't do very often, as 24.412 - branch names tend to have fairly long lifetimes. (This isn't a 24.413 - rule, just an observation.)</para> 24.414 - 24.415 - </sect1> 24.416 - <sect1> 24.417 - <title>Dealing with multiple named branches in a 24.418 - repository</title> 24.419 - 24.420 - <para>If you have more than one named branch in a repository, 24.421 - Mercurial will remember the branch that your working directory 24.422 - on when you start a command like <command role="hg-cmd">hg 24.423 - update</command> or <command role="hg-cmd">hg pull 24.424 - -u</command>. It will update the working directory to the tip 24.425 - of this branch, no matter what the <quote>repo-wide</quote> tip 24.426 - is. To update to a revision that's on a different named branch, 24.427 - you may need to use the <option role="hg-opt-update">-C</option> 24.428 - option to <command role="hg-cmd">hg update</command>.</para> 24.429 - 24.430 - <para>This behaviour is a little subtle, so let's see it in 24.431 - action. First, let's remind ourselves what branch we're 24.432 - currently on, and what branches are in our repository.</para> 24.433 - 24.434 - &interaction.branch-named.parents; 24.435 - 24.436 - <para>We're on the <literal>bar</literal> branch, but there also 24.437 - exists an older <command role="hg-cmd">hg foo</command> 24.438 - branch.</para> 24.439 - 24.440 - <para>We can <command role="hg-cmd">hg update</command> back and 24.441 - forth between the tips of the <literal>foo</literal> and 24.442 - <literal>bar</literal> branches without needing to use the 24.443 - <option role="hg-opt-update">-C</option> option, because this 24.444 - only involves going backwards and forwards linearly through our 24.445 - change history.</para> 24.446 - 24.447 - &interaction.branch-named.update-switchy; 24.448 - 24.449 - <para>If we go back to the <literal>foo</literal> branch and then 24.450 - run <command role="hg-cmd">hg update</command>, it will keep us 24.451 - on <literal>foo</literal>, not move us to the tip of 24.452 - <literal>bar</literal>.</para> 24.453 - 24.454 - &interaction.branch-named.update-nothing; 24.455 - 24.456 - <para>Committing a new change on the <literal>foo</literal> branch 24.457 - introduces a new head.</para> 24.458 - 24.459 - &interaction.branch-named.foo-commit; 24.460 - 24.461 - </sect1> 24.462 - <sect1> 24.463 - <title>Branch names and merging</title> 24.464 - 24.465 - <para>As you've probably noticed, merges in Mercurial are not 24.466 - symmetrical. Let's say our repository has two heads, 17 and 23. 24.467 - If I <command role="hg-cmd">hg update</command> to 17 and then 24.468 - <command role="hg-cmd">hg merge</command> with 23, Mercurial 24.469 - records 17 as the first parent of the merge, and 23 as the 24.470 - second. Whereas if I <command role="hg-cmd">hg update</command> 24.471 - to 23 and then <command role="hg-cmd">hg merge</command> with 24.472 - 17, it records 23 as the first parent, and 17 as the 24.473 - second.</para> 24.474 - 24.475 - <para>This affects Mercurial's choice of branch name when you 24.476 - merge. After a merge, Mercurial will retain the branch name of 24.477 - the first parent when you commit the result of the merge. If 24.478 - your first parent's branch name is <literal>foo</literal>, and 24.479 - you merge with <literal>bar</literal>, the branch name will 24.480 - still be <literal>foo</literal> after you merge.</para> 24.481 - 24.482 - <para>It's not unusual for a repository to contain multiple heads, 24.483 - each with the same branch name. Let's say I'm working on the 24.484 - <literal>foo</literal> branch, and so are you. We commit 24.485 - different changes; I pull your changes; I now have two heads, 24.486 - each claiming to be on the <literal>foo</literal> branch. The 24.487 - result of a merge will be a single head on the 24.488 - <literal>foo</literal> branch, as you might hope.</para> 24.489 - 24.490 - <para>But if I'm working on the <literal>bar</literal> branch, and 24.491 - I merge work from the <literal>foo</literal> branch, the result 24.492 - will remain on the <literal>bar</literal> branch.</para> 24.493 - 24.494 - &interaction.branch-named.merge; 24.495 - 24.496 - <para>To give a more concrete example, if I'm working on the 24.497 - <literal>bleeding-edge</literal> branch, and I want to bring in 24.498 - the latest fixes from the <literal>stable</literal> branch, 24.499 - Mercurial will choose the <quote>right</quote> 24.500 - (<literal>bleeding-edge</literal>) branch name when I pull and 24.501 - merge from <literal>stable</literal>.</para> 24.502 - 24.503 - </sect1> 24.504 - <sect1> 24.505 - <title>Branch naming is generally useful</title> 24.506 - 24.507 - <para>You shouldn't think of named branches as applicable only to 24.508 - situations where you have multiple long-lived branches 24.509 - cohabiting in a single repository. They're very useful even in 24.510 - the one-branch-per-repository case.</para> 24.511 - 24.512 - <para>In the simplest case, giving a name to each branch gives you 24.513 - a permanent record of which branch a changeset originated on. 24.514 - This gives you more context when you're trying to follow the 24.515 - history of a long-lived branchy project.</para> 24.516 - 24.517 - <para>If you're working with shared repositories, you can set up a 24.518 - <literal role="hook">pretxnchangegroup</literal> hook on each 24.519 - that will block incoming changes that have the 24.520 - <quote>wrong</quote> branch name. This provides a simple, but 24.521 - effective, defence against people accidentally pushing changes 24.522 - from a <quote>bleeding edge</quote> branch to a 24.523 - <quote>stable</quote> branch. Such a hook might look like this 24.524 - inside the shared repo's <filename role="special"> 24.525 - /.hgrc</filename>.</para> 24.526 - <programlisting>[hooks] 24.527 -pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting> 24.528 - 24.529 - </sect1> 24.530 -</chapter> 24.531 - 24.532 -<!-- 24.533 -local variables: 24.534 -sgml-parent-document: ("00book.xml" "book" "chapter") 24.535 -end: 24.536 --->
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/en/ch08-undo.xml Fri Mar 20 16:43:35 2009 +0800 25.3 @@ -0,0 +1,1083 @@ 25.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 25.5 + 25.6 +<chapter id="chap.undo"> 25.7 + <?dbhtml filename="finding-and-fixing-mistakes.html"?> 25.8 + <title>Finding and fixing mistakes</title> 25.9 + 25.10 + <para>To err might be human, but to really handle the consequences 25.11 + well takes a top-notch revision control system. In this chapter, 25.12 + we'll discuss some of the techniques you can use when you find 25.13 + that a problem has crept into your project. Mercurial has some 25.14 + highly capable features that will help you to isolate the sources 25.15 + of problems, and to handle them appropriately.</para> 25.16 + 25.17 + <sect1> 25.18 + <title>Erasing local history</title> 25.19 + 25.20 + <sect2> 25.21 + <title>The accidental commit</title> 25.22 + 25.23 + <para>I have the occasional but persistent problem of typing 25.24 + rather more quickly than I can think, which sometimes results 25.25 + in me committing a changeset that is either incomplete or 25.26 + plain wrong. In my case, the usual kind of incomplete 25.27 + changeset is one in which I've created a new source file, but 25.28 + forgotten to <command role="hg-cmd">hg add</command> it. A 25.29 + <quote>plain wrong</quote> changeset is not as common, but no 25.30 + less annoying.</para> 25.31 + 25.32 + </sect2> 25.33 + <sect2 id="sec.undo.rollback"> 25.34 + <title>Rolling back a transaction</title> 25.35 + 25.36 + <para>In section <xref linkend="sec.concepts.txn"/>, I mentioned 25.37 + that Mercurial treats each modification of a repository as a 25.38 + <emphasis>transaction</emphasis>. Every time you commit a 25.39 + changeset or pull changes from another repository, Mercurial 25.40 + remembers what you did. You can undo, or <emphasis>roll 25.41 + back</emphasis>, exactly one of these actions using the 25.42 + <command role="hg-cmd">hg rollback</command> command. (See 25.43 + section <xref linkend="sec.undo.rollback-after-push"/> for an 25.44 + important caveat about the use of this command.)</para> 25.45 + 25.46 + <para>Here's a mistake that I often find myself making: 25.47 + committing a change in which I've created a new file, but 25.48 + forgotten to <command role="hg-cmd">hg add</command> 25.49 + it.</para> 25.50 + 25.51 + &interaction.rollback.commit; 25.52 + 25.53 + <para>Looking at the output of <command role="hg-cmd">hg 25.54 + status</command> after the commit immediately confirms the 25.55 + error.</para> 25.56 + 25.57 + &interaction.rollback.status; 25.58 + 25.59 + <para>The commit captured the changes to the file 25.60 + <filename>a</filename>, but not the new file 25.61 + <filename>b</filename>. If I were to push this changeset to a 25.62 + repository that I shared with a colleague, the chances are 25.63 + high that something in <filename>a</filename> would refer to 25.64 + <filename>b</filename>, which would not be present in their 25.65 + repository when they pulled my changes. I would thus become 25.66 + the object of some indignation.</para> 25.67 + 25.68 + <para>However, luck is with me&emdash;I've caught my error 25.69 + before I pushed the changeset. I use the <command 25.70 + role="hg-cmd">hg rollback</command> command, and Mercurial 25.71 + makes that last changeset vanish.</para> 25.72 + 25.73 + &interaction.rollback.rollback; 25.74 + 25.75 + <para>Notice that the changeset is no longer present in the 25.76 + repository's history, and the working directory once again 25.77 + thinks that the file <filename>a</filename> is modified. The 25.78 + commit and rollback have left the working directory exactly as 25.79 + it was prior to the commit; the changeset has been completely 25.80 + erased. I can now safely <command role="hg-cmd">hg 25.81 + add</command> the file <filename>b</filename>, and rerun my 25.82 + commit.</para> 25.83 + 25.84 + &interaction.rollback.add; 25.85 + 25.86 + </sect2> 25.87 + <sect2> 25.88 + <title>The erroneous pull</title> 25.89 + 25.90 + <para>It's common practice with Mercurial to maintain separate 25.91 + development branches of a project in different repositories. 25.92 + Your development team might have one shared repository for 25.93 + your project's <quote>0.9</quote> release, and another, 25.94 + containing different changes, for the <quote>1.0</quote> 25.95 + release.</para> 25.96 + 25.97 + <para>Given this, you can imagine that the consequences could be 25.98 + messy if you had a local <quote>0.9</quote> repository, and 25.99 + accidentally pulled changes from the shared <quote>1.0</quote> 25.100 + repository into it. At worst, you could be paying 25.101 + insufficient attention, and push those changes into the shared 25.102 + <quote>0.9</quote> tree, confusing your entire team (but don't 25.103 + worry, we'll return to this horror scenario later). However, 25.104 + it's more likely that you'll notice immediately, because 25.105 + Mercurial will display the URL it's pulling from, or you will 25.106 + see it pull a suspiciously large number of changes into the 25.107 + repository.</para> 25.108 + 25.109 + <para>The <command role="hg-cmd">hg rollback</command> command 25.110 + will work nicely to expunge all of the changesets that you 25.111 + just pulled. Mercurial groups all changes from one <command 25.112 + role="hg-cmd">hg pull</command> into a single transaction, 25.113 + so one <command role="hg-cmd">hg rollback</command> is all you 25.114 + need to undo this mistake.</para> 25.115 + 25.116 + </sect2> 25.117 + <sect2 id="sec.undo.rollback-after-push"> 25.118 + <title>Rolling back is useless once you've pushed</title> 25.119 + 25.120 + <para>The value of the <command role="hg-cmd">hg 25.121 + rollback</command> command drops to zero once you've pushed 25.122 + your changes to another repository. Rolling back a change 25.123 + makes it disappear entirely, but <emphasis>only</emphasis> in 25.124 + the repository in which you perform the <command 25.125 + role="hg-cmd">hg rollback</command>. Because a rollback 25.126 + eliminates history, there's no way for the disappearance of a 25.127 + change to propagate between repositories.</para> 25.128 + 25.129 + <para>If you've pushed a change to another 25.130 + repository&emdash;particularly if it's a shared 25.131 + repository&emdash;it has essentially <quote>escaped into the 25.132 + wild,</quote> and you'll have to recover from your mistake 25.133 + in a different way. What will happen if you push a changeset 25.134 + somewhere, then roll it back, then pull from the repository 25.135 + you pushed to, is that the changeset will reappear in your 25.136 + repository.</para> 25.137 + 25.138 + <para>(If you absolutely know for sure that the change you want 25.139 + to roll back is the most recent change in the repository that 25.140 + you pushed to, <emphasis>and</emphasis> you know that nobody 25.141 + else could have pulled it from that repository, you can roll 25.142 + back the changeset there, too, but you really should really 25.143 + not rely on this working reliably. If you do this, sooner or 25.144 + later a change really will make it into a repository that you 25.145 + don't directly control (or have forgotten about), and come 25.146 + back to bite you.)</para> 25.147 + 25.148 + </sect2> 25.149 + <sect2> 25.150 + <title>You can only roll back once</title> 25.151 + 25.152 + <para>Mercurial stores exactly one transaction in its 25.153 + transaction log; that transaction is the most recent one that 25.154 + occurred in the repository. This means that you can only roll 25.155 + back one transaction. If you expect to be able to roll back 25.156 + one transaction, then its predecessor, this is not the 25.157 + behaviour you will get.</para> 25.158 + 25.159 + &interaction.rollback.twice; 25.160 + 25.161 + <para>Once you've rolled back one transaction in a repository, 25.162 + you can't roll back again in that repository until you perform 25.163 + another commit or pull.</para> 25.164 + 25.165 + </sect2> 25.166 + </sect1> 25.167 + <sect1> 25.168 + <title>Reverting the mistaken change</title> 25.169 + 25.170 + <para>If you make a modification to a file, and decide that you 25.171 + really didn't want to change the file at all, and you haven't 25.172 + yet committed your changes, the <command role="hg-cmd">hg 25.173 + revert</command> command is the one you'll need. It looks at 25.174 + the changeset that's the parent of the working directory, and 25.175 + restores the contents of the file to their state as of that 25.176 + changeset. (That's a long-winded way of saying that, in the 25.177 + normal case, it undoes your modifications.)</para> 25.178 + 25.179 + <para>Let's illustrate how the <command role="hg-cmd">hg 25.180 + revert</command> command works with yet another small example. 25.181 + We'll begin by modifying a file that Mercurial is already 25.182 + tracking.</para> 25.183 + 25.184 + &interaction.daily.revert.modify; 25.185 + 25.186 + <para>If we don't 25.187 + want that change, we can simply <command role="hg-cmd">hg 25.188 + revert</command> the file.</para> 25.189 + 25.190 + &interaction.daily.revert.unmodify; 25.191 + 25.192 + <para>The <command role="hg-cmd">hg revert</command> command 25.193 + provides us with an extra degree of safety by saving our 25.194 + modified file with a <filename>.orig</filename> 25.195 + extension.</para> 25.196 + 25.197 + &interaction.daily.revert.status; 25.198 + 25.199 + <para>Here is a summary of the cases that the <command 25.200 + role="hg-cmd">hg revert</command> command can deal with. We 25.201 + will describe each of these in more detail in the section that 25.202 + follows.</para> 25.203 + <itemizedlist> 25.204 + <listitem><para>If you modify a file, it will restore the file 25.205 + to its unmodified state.</para> 25.206 + </listitem> 25.207 + <listitem><para>If you <command role="hg-cmd">hg add</command> a 25.208 + file, it will undo the <quote>added</quote> state of the 25.209 + file, but leave the file itself untouched.</para> 25.210 + </listitem> 25.211 + <listitem><para>If you delete a file without telling Mercurial, 25.212 + it will restore the file to its unmodified contents.</para> 25.213 + </listitem> 25.214 + <listitem><para>If you use the <command role="hg-cmd">hg 25.215 + remove</command> command to remove a file, it will undo 25.216 + the <quote>removed</quote> state of the file, and restore 25.217 + the file to its unmodified contents.</para> 25.218 + </listitem></itemizedlist> 25.219 + 25.220 + <sect2 id="sec.undo.mgmt"> 25.221 + <title>File management errors</title> 25.222 + 25.223 + <para>The <command role="hg-cmd">hg revert</command> command is 25.224 + useful for more than just modified files. It lets you reverse 25.225 + the results of all of Mercurial's file management 25.226 + commands&emdash;<command role="hg-cmd">hg add</command>, 25.227 + <command role="hg-cmd">hg remove</command>, and so on.</para> 25.228 + 25.229 + <para>If you <command role="hg-cmd">hg add</command> a file, 25.230 + then decide that in fact you don't want Mercurial to track it, 25.231 + use <command role="hg-cmd">hg revert</command> to undo the 25.232 + add. Don't worry; Mercurial will not modify the file in any 25.233 + way. It will just <quote>unmark</quote> the file.</para> 25.234 + 25.235 + &interaction.daily.revert.add; 25.236 + 25.237 + <para>Similarly, if you ask Mercurial to <command 25.238 + role="hg-cmd">hg remove</command> a file, you can use 25.239 + <command role="hg-cmd">hg revert</command> to restore it to 25.240 + the contents it had as of the parent of the working directory. 25.241 + &interaction.daily.revert.remove; This works just as 25.242 + well for a file that you deleted by hand, without telling 25.243 + Mercurial (recall that in Mercurial terminology, this kind of 25.244 + file is called <quote>missing</quote>).</para> 25.245 + 25.246 + &interaction.daily.revert.missing; 25.247 + 25.248 + <para>If you revert a <command role="hg-cmd">hg copy</command>, 25.249 + the copied-to file remains in your working directory 25.250 + afterwards, untracked. Since a copy doesn't affect the 25.251 + copied-from file in any way, Mercurial doesn't do anything 25.252 + with the copied-from file.</para> 25.253 + 25.254 + &interaction.daily.revert.copy; 25.255 + 25.256 + <sect3> 25.257 + <title>A slightly special case: reverting a rename</title> 25.258 + 25.259 + <para>If you <command role="hg-cmd">hg rename</command> a 25.260 + file, there is one small detail that you should remember. 25.261 + When you <command role="hg-cmd">hg revert</command> a 25.262 + rename, it's not enough to provide the name of the 25.263 + renamed-to file, as you can see here.</para> 25.264 + 25.265 + &interaction.daily.revert.rename; 25.266 + 25.267 + <para>As you can see from the output of <command 25.268 + role="hg-cmd">hg status</command>, the renamed-to file is 25.269 + no longer identified as added, but the 25.270 + renamed-<emphasis>from</emphasis> file is still removed! 25.271 + This is counter-intuitive (at least to me), but at least 25.272 + it's easy to deal with.</para> 25.273 + 25.274 + &interaction.daily.revert.rename-orig; 25.275 + 25.276 + <para>So remember, to revert a <command role="hg-cmd">hg 25.277 + rename</command>, you must provide 25.278 + <emphasis>both</emphasis> the source and destination 25.279 + names.</para> 25.280 + 25.281 + <para>% TODO: the output doesn't look like it will be 25.282 + removed!</para> 25.283 + 25.284 + <para>(By the way, if you rename a file, then modify the 25.285 + renamed-to file, then revert both components of the rename, 25.286 + when Mercurial restores the file that was removed as part of 25.287 + the rename, it will be unmodified. If you need the 25.288 + modifications in the renamed-to file to show up in the 25.289 + renamed-from file, don't forget to copy them over.)</para> 25.290 + 25.291 + <para>These fiddly aspects of reverting a rename arguably 25.292 + constitute a small bug in Mercurial.</para> 25.293 + 25.294 + </sect3> 25.295 + </sect2> 25.296 + </sect1> 25.297 + <sect1> 25.298 + <title>Dealing with committed changes</title> 25.299 + 25.300 + <para>Consider a case where you have committed a change $a$, and 25.301 + another change $b$ on top of it; you then realise that change 25.302 + $a$ was incorrect. Mercurial lets you <quote>back out</quote> 25.303 + an entire changeset automatically, and building blocks that let 25.304 + you reverse part of a changeset by hand.</para> 25.305 + 25.306 + <para>Before you read this section, here's something to keep in 25.307 + mind: the <command role="hg-cmd">hg backout</command> command 25.308 + undoes changes by <emphasis>adding</emphasis> history, not by 25.309 + modifying or erasing it. It's the right tool to use if you're 25.310 + fixing bugs, but not if you're trying to undo some change that 25.311 + has catastrophic consequences. To deal with those, see section 25.312 + <xref linkend="sec.undo.aaaiiieee"/>.</para> 25.313 + 25.314 + <sect2> 25.315 + <title>Backing out a changeset</title> 25.316 + 25.317 + <para>The <command role="hg-cmd">hg backout</command> command 25.318 + lets you <quote>undo</quote> the effects of an entire 25.319 + changeset in an automated fashion. Because Mercurial's 25.320 + history is immutable, this command <emphasis>does 25.321 + not</emphasis> get rid of the changeset you want to undo. 25.322 + Instead, it creates a new changeset that 25.323 + <emphasis>reverses</emphasis> the effect of the to-be-undone 25.324 + changeset.</para> 25.325 + 25.326 + <para>The operation of the <command role="hg-cmd">hg 25.327 + backout</command> command is a little intricate, so let's 25.328 + illustrate it with some examples. First, we'll create a 25.329 + repository with some simple changes.</para> 25.330 + 25.331 + &interaction.backout.init; 25.332 + 25.333 + <para>The <command role="hg-cmd">hg backout</command> command 25.334 + takes a single changeset ID as its argument; this is the 25.335 + changeset to back out. Normally, <command role="hg-cmd">hg 25.336 + backout</command> will drop you into a text editor to write 25.337 + a commit message, so you can record why you're backing the 25.338 + change out. In this example, we provide a commit message on 25.339 + the command line using the <option 25.340 + role="hg-opt-backout">-m</option> option.</para> 25.341 + 25.342 + </sect2> 25.343 + <sect2> 25.344 + <title>Backing out the tip changeset</title> 25.345 + 25.346 + <para>We're going to start by backing out the last changeset we 25.347 + committed.</para> 25.348 + 25.349 + &interaction.backout.simple; 25.350 + 25.351 + <para>You can see that the second line from 25.352 + <filename>myfile</filename> is no longer present. Taking a 25.353 + look at the output of <command role="hg-cmd">hg log</command> 25.354 + gives us an idea of what the <command role="hg-cmd">hg 25.355 + backout</command> command has done. 25.356 + &interaction.backout.simple.log; Notice that the new changeset 25.357 + that <command role="hg-cmd">hg backout</command> has created 25.358 + is a child of the changeset we backed out. It's easier to see 25.359 + this in figure <xref 25.360 + endterm="fig.undo.backout.caption" linkend="fig.undo.backout"/>, 25.361 + which presents a graphical 25.362 + view of the change history. As you can see, the history is 25.363 + nice and linear.</para> 25.364 + 25.365 + <informalfigure id="fig.undo.backout"> 25.366 + <mediaobject> 25.367 + <imageobject><imagedata fileref="images/undo-simple.png"/> 25.368 + </imageobject> 25.369 + <textobject><phrase>XXX add text</phrase></textobject> 25.370 + <caption><para id="fig.undo.backout.caption">Backing out 25.371 + a change using the 25.372 + <command role="hg-cmd">hg backout</command> 25.373 + command</para></caption> 25.374 + </mediaobject> 25.375 + </informalfigure> 25.376 + 25.377 + </sect2> 25.378 + <sect2> 25.379 + <title>Backing out a non-tip change</title> 25.380 + 25.381 + <para>If you want to back out a change other than the last one 25.382 + you committed, pass the <option 25.383 + role="hg-opt-backout">--merge</option> option to the 25.384 + <command role="hg-cmd">hg backout</command> command.</para> 25.385 + 25.386 + &interaction.backout.non-tip.clone; 25.387 + 25.388 + <para>This makes backing out any changeset a 25.389 + <quote>one-shot</quote> operation that's usually simple and 25.390 + fast.</para> 25.391 + 25.392 + &interaction.backout.non-tip.backout; 25.393 + 25.394 + <para>If you take a look at the contents of 25.395 + <filename>myfile</filename> after the backout finishes, you'll 25.396 + see that the first and third changes are present, but not the 25.397 + second.</para> 25.398 + 25.399 + &interaction.backout.non-tip.cat; 25.400 + 25.401 + <para>As the graphical history in figure <xref 25.402 + endterm="fig.undo.backout-non-tip.caption" 25.403 + linkend="fig.undo.backout-non-tip"/> illustrates, Mercurial 25.404 + actually commits <emphasis>two</emphasis> changes in this kind 25.405 + of situation (the box-shaped nodes are the ones that Mercurial 25.406 + commits automatically). Before Mercurial begins the backout 25.407 + process, it first remembers what the current parent of the 25.408 + working directory is. It then backs out the target changeset, 25.409 + and commits that as a changeset. Finally, it merges back to 25.410 + the previous parent of the working directory, and commits the 25.411 + result of the merge.</para> 25.412 + 25.413 + <para>% TODO: to me it looks like mercurial doesn't commit the 25.414 + second merge automatically!</para> 25.415 + 25.416 + <informalfigure id="fig.undo.backout-non-tip"> 25.417 + <mediaobject> 25.418 + <imageobject><imagedata fileref="images/undo-non-tip.png"/> 25.419 + </imageobject> 25.420 + <textobject><phrase>XXX add text</phrase></textobject> 25.421 + <caption><para id="fig.undo.backout-non-tip.caption">Automated 25.422 + backout of a non-tip change using the 25.423 + <command role="hg-cmd">hg backout</command> command</para></caption> 25.424 + </mediaobject> 25.425 + </informalfigure> 25.426 + 25.427 + <para>The result is that you end up <quote>back where you 25.428 + were</quote>, only with some extra history that undoes the 25.429 + effect of the changeset you wanted to back out.</para> 25.430 + 25.431 + <sect3> 25.432 + <title>Always use the <option 25.433 + role="hg-opt-backout">--merge</option> option</title> 25.434 + 25.435 + <para>In fact, since the <option 25.436 + role="hg-opt-backout">--merge</option> option will do the 25.437 + <quote>right thing</quote> whether or not the changeset 25.438 + you're backing out is the tip (i.e. it won't try to merge if 25.439 + it's backing out the tip, since there's no need), you should 25.440 + <emphasis>always</emphasis> use this option when you run the 25.441 + <command role="hg-cmd">hg backout</command> command.</para> 25.442 + 25.443 + </sect3> 25.444 + </sect2> 25.445 + <sect2> 25.446 + <title>Gaining more control of the backout process</title> 25.447 + 25.448 + <para>While I've recommended that you always use the <option 25.449 + role="hg-opt-backout">--merge</option> option when backing 25.450 + out a change, the <command role="hg-cmd">hg backout</command> 25.451 + command lets you decide how to merge a backout changeset. 25.452 + Taking control of the backout process by hand is something you 25.453 + will rarely need to do, but it can be useful to understand 25.454 + what the <command role="hg-cmd">hg backout</command> command 25.455 + is doing for you automatically. To illustrate this, let's 25.456 + clone our first repository, but omit the backout change that 25.457 + it contains.</para> 25.458 + 25.459 + &interaction.backout.manual.clone; 25.460 + 25.461 + <para>As with our 25.462 + earlier example, We'll commit a third changeset, then back out 25.463 + its parent, and see what happens.</para> 25.464 + 25.465 + &interaction.backout.manual.backout; 25.466 + 25.467 + <para>Our new changeset is again a descendant of the changeset 25.468 + we backout out; it's thus a new head, <emphasis>not</emphasis> 25.469 + a descendant of the changeset that was the tip. The <command 25.470 + role="hg-cmd">hg backout</command> command was quite 25.471 + explicit in telling us this.</para> 25.472 + 25.473 + &interaction.backout.manual.log; 25.474 + 25.475 + <para>Again, it's easier to see what has happened by looking at 25.476 + a graph of the revision history, in figure <xref 25.477 + endterm="fig.undo.backout-manual.caption" 25.478 + linkend="fig.undo.backout-manual"/>. This makes it clear 25.479 + that when we use <command role="hg-cmd">hg backout</command> 25.480 + to back out a change other than the tip, Mercurial adds a new 25.481 + head to the repository (the change it committed is 25.482 + box-shaped).</para> 25.483 + 25.484 + <informalfigure id="fig.undo.backout-manual"> 25.485 + <mediaobject> 25.486 + <imageobject><imagedata fileref="images/undo-manual.png"/> 25.487 + </imageobject> 25.488 + <textobject><phrase>XXX add text</phrase></textobject> 25.489 + <caption><para id="fig.undo.backout-manual.caption">Backing out a 25.490 + change using the <command role="hg-cmd">hg backout</command> 25.491 + command</para></caption> 25.492 + </mediaobject> 25.493 + </informalfigure> 25.494 + 25.495 + <para>After the <command role="hg-cmd">hg backout</command> 25.496 + command has completed, it leaves the new 25.497 + <quote>backout</quote> changeset as the parent of the working 25.498 + directory.</para> 25.499 + 25.500 + &interaction.backout.manual.parents; 25.501 + 25.502 + <para>Now we have two isolated sets of changes.</para> 25.503 + 25.504 + &interaction.backout.manual.heads; 25.505 + 25.506 + <para>Let's think about what we expect to see as the contents of 25.507 + <filename>myfile</filename> now. The first change should be 25.508 + present, because we've never backed it out. The second change 25.509 + should be missing, as that's the change we backed out. Since 25.510 + the history graph shows the third change as a separate head, 25.511 + we <emphasis>don't</emphasis> expect to see the third change 25.512 + present in <filename>myfile</filename>.</para> 25.513 + 25.514 + &interaction.backout.manual.cat; 25.515 + 25.516 + <para>To get the third change back into the file, we just do a 25.517 + normal merge of our two heads.</para> 25.518 + 25.519 + &interaction.backout.manual.merge; 25.520 + 25.521 + <para>Afterwards, the graphical history of our repository looks 25.522 + like figure 25.523 + <xref endterm="fig.undo.backout-manual-merge.caption" 25.524 + linkend="fig.undo.backout-manual-merge"/>.</para> 25.525 + 25.526 + <informalfigure id="fig.undo.backout-manual-merge"> 25.527 + <mediaobject> 25.528 + <imageobject><imagedata fileref="images/undo-manual-merge.png"/> 25.529 + </imageobject> 25.530 + <textobject><phrase>XXX add text</phrase></textobject> 25.531 + <caption><para id="fig.undo.backout-manual-merge.caption">Manually 25.532 + merging a backout change</para></caption> 25.533 + </mediaobject> 25.534 + </informalfigure> 25.535 + 25.536 + </sect2> 25.537 + <sect2> 25.538 + <title>Why <command role="hg-cmd">hg backout</command> works as 25.539 + it does</title> 25.540 + 25.541 + <para>Here's a brief description of how the <command 25.542 + role="hg-cmd">hg backout</command> command works.</para> 25.543 + <orderedlist> 25.544 + <listitem><para>It ensures that the working directory is 25.545 + <quote>clean</quote>, i.e. that the output of <command 25.546 + role="hg-cmd">hg status</command> would be empty.</para> 25.547 + </listitem> 25.548 + <listitem><para>It remembers the current parent of the working 25.549 + directory. Let's call this changeset 25.550 + <literal>orig</literal></para> 25.551 + </listitem> 25.552 + <listitem><para>It does the equivalent of a <command 25.553 + role="hg-cmd">hg update</command> to sync the working 25.554 + directory to the changeset you want to back out. Let's 25.555 + call this changeset <literal>backout</literal></para> 25.556 + </listitem> 25.557 + <listitem><para>It finds the parent of that changeset. Let's 25.558 + call that changeset <literal>parent</literal>.</para> 25.559 + </listitem> 25.560 + <listitem><para>For each file that the 25.561 + <literal>backout</literal> changeset affected, it does the 25.562 + equivalent of a <command role="hg-cmd">hg revert -r 25.563 + parent</command> on that file, to restore it to the 25.564 + contents it had before that changeset was 25.565 + committed.</para> 25.566 + </listitem> 25.567 + <listitem><para>It commits the result as a new changeset. 25.568 + This changeset has <literal>backout</literal> as its 25.569 + parent.</para> 25.570 + </listitem> 25.571 + <listitem><para>If you specify <option 25.572 + role="hg-opt-backout">--merge</option> on the command 25.573 + line, it merges with <literal>orig</literal>, and commits 25.574 + the result of the merge.</para> 25.575 + </listitem></orderedlist> 25.576 + 25.577 + <para>An alternative way to implement the <command 25.578 + role="hg-cmd">hg backout</command> command would be to 25.579 + <command role="hg-cmd">hg export</command> the 25.580 + to-be-backed-out changeset as a diff, then use the <option 25.581 + role="cmd-opt-patch">--reverse</option> option to the 25.582 + <command>patch</command> command to reverse the effect of the 25.583 + change without fiddling with the working directory. This 25.584 + sounds much simpler, but it would not work nearly as 25.585 + well.</para> 25.586 + 25.587 + <para>The reason that <command role="hg-cmd">hg 25.588 + backout</command> does an update, a commit, a merge, and 25.589 + another commit is to give the merge machinery the best chance 25.590 + to do a good job when dealing with all the changes 25.591 + <emphasis>between</emphasis> the change you're backing out and 25.592 + the current tip.</para> 25.593 + 25.594 + <para>If you're backing out a changeset that's 100 revisions 25.595 + back in your project's history, the chances that the 25.596 + <command>patch</command> command will be able to apply a 25.597 + reverse diff cleanly are not good, because intervening changes 25.598 + are likely to have <quote>broken the context</quote> that 25.599 + <command>patch</command> uses to determine whether it can 25.600 + apply a patch (if this sounds like gibberish, see <xref 25.601 + linkend="sec.mq.patch"/> for a 25.602 + discussion of the <command>patch</command> command). Also, 25.603 + Mercurial's merge machinery will handle files and directories 25.604 + being renamed, permission changes, and modifications to binary 25.605 + files, none of which <command>patch</command> can deal 25.606 + with.</para> 25.607 + 25.608 + </sect2> 25.609 + </sect1> 25.610 + <sect1 id="sec.undo.aaaiiieee"> 25.611 + <title>Changes that should never have been</title> 25.612 + 25.613 + <para>Most of the time, the <command role="hg-cmd">hg 25.614 + backout</command> command is exactly what you need if you want 25.615 + to undo the effects of a change. It leaves a permanent record 25.616 + of exactly what you did, both when committing the original 25.617 + changeset and when you cleaned up after it.</para> 25.618 + 25.619 + <para>On rare occasions, though, you may find that you've 25.620 + committed a change that really should not be present in the 25.621 + repository at all. For example, it would be very unusual, and 25.622 + usually considered a mistake, to commit a software project's 25.623 + object files as well as its source files. Object files have 25.624 + almost no intrinsic value, and they're <emphasis>big</emphasis>, 25.625 + so they increase the size of the repository and the amount of 25.626 + time it takes to clone or pull changes.</para> 25.627 + 25.628 + <para>Before I discuss the options that you have if you commit a 25.629 + <quote>brown paper bag</quote> change (the kind that's so bad 25.630 + that you want to pull a brown paper bag over your head), let me 25.631 + first discuss some approaches that probably won't work.</para> 25.632 + 25.633 + <para>Since Mercurial treats history as accumulative&emdash;every 25.634 + change builds on top of all changes that preceded it&emdash;you 25.635 + generally can't just make disastrous changes disappear. The one 25.636 + exception is when you've just committed a change, and it hasn't 25.637 + been pushed or pulled into another repository. That's when you 25.638 + can safely use the <command role="hg-cmd">hg rollback</command> 25.639 + command, as I detailed in section <xref 25.640 + linkend="sec.undo.rollback"/>.</para> 25.641 + 25.642 + <para>After you've pushed a bad change to another repository, you 25.643 + <emphasis>could</emphasis> still use <command role="hg-cmd">hg 25.644 + rollback</command> to make your local copy of the change 25.645 + disappear, but it won't have the consequences you want. The 25.646 + change will still be present in the remote repository, so it 25.647 + will reappear in your local repository the next time you 25.648 + pull.</para> 25.649 + 25.650 + <para>If a situation like this arises, and you know which 25.651 + repositories your bad change has propagated into, you can 25.652 + <emphasis>try</emphasis> to get rid of the changeefrom 25.653 + <emphasis>every</emphasis> one of those repositories. This is, 25.654 + of course, not a satisfactory solution: if you miss even a 25.655 + single repository while you're expunging, the change is still 25.656 + <quote>in the wild</quote>, and could propagate further.</para> 25.657 + 25.658 + <para>If you've committed one or more changes 25.659 + <emphasis>after</emphasis> the change that you'd like to see 25.660 + disappear, your options are further reduced. Mercurial doesn't 25.661 + provide a way to <quote>punch a hole</quote> in history, leaving 25.662 + changesets intact.</para> 25.663 + 25.664 + <para>XXX This needs filling out. The 25.665 + <literal>hg-replay</literal> script in the 25.666 + <literal>examples</literal> directory works, but doesn't handle 25.667 + merge changesets. Kind of an important omission.</para> 25.668 + 25.669 + <sect2> 25.670 + <title>Protect yourself from <quote>escaped</quote> 25.671 + changes</title> 25.672 + 25.673 + <para>If you've committed some changes to your local repository 25.674 + and they've been pushed or pulled somewhere else, this isn't 25.675 + necessarily a disaster. You can protect yourself ahead of 25.676 + time against some classes of bad changeset. This is 25.677 + particularly easy if your team usually pulls changes from a 25.678 + central repository.</para> 25.679 + 25.680 + <para>By configuring some hooks on that repository to validate 25.681 + incoming changesets (see chapter <xref linkend="chap.hook"/>), 25.682 + you can 25.683 + automatically prevent some kinds of bad changeset from being 25.684 + pushed to the central repository at all. With such a 25.685 + configuration in place, some kinds of bad changeset will 25.686 + naturally tend to <quote>die out</quote> because they can't 25.687 + propagate into the central repository. Better yet, this 25.688 + happens without any need for explicit intervention.</para> 25.689 + 25.690 + <para>For instance, an incoming change hook that verifies that a 25.691 + changeset will actually compile can prevent people from 25.692 + inadvertantly <quote>breaking the build</quote>.</para> 25.693 + 25.694 + </sect2> 25.695 + </sect1> 25.696 + <sect1 id="sec.undo.bisect"> 25.697 + <title>Finding the source of a bug</title> 25.698 + 25.699 + <para>While it's all very well to be able to back out a changeset 25.700 + that introduced a bug, this requires that you know which 25.701 + changeset to back out. Mercurial provides an invaluable 25.702 + command, called <command role="hg-cmd">hg bisect</command>, that 25.703 + helps you to automate this process and accomplish it very 25.704 + efficiently.</para> 25.705 + 25.706 + <para>The idea behind the <command role="hg-cmd">hg 25.707 + bisect</command> command is that a changeset has introduced 25.708 + some change of behaviour that you can identify with a simple 25.709 + binary test. You don't know which piece of code introduced the 25.710 + change, but you know how to test for the presence of the bug. 25.711 + The <command role="hg-cmd">hg bisect</command> command uses your 25.712 + test to direct its search for the changeset that introduced the 25.713 + code that caused the bug.</para> 25.714 + 25.715 + <para>Here are a few scenarios to help you understand how you 25.716 + might apply this command.</para> 25.717 + <itemizedlist> 25.718 + <listitem><para>The most recent version of your software has a 25.719 + bug that you remember wasn't present a few weeks ago, but 25.720 + you don't know when it was introduced. Here, your binary 25.721 + test checks for the presence of that bug.</para> 25.722 + </listitem> 25.723 + <listitem><para>You fixed a bug in a rush, and now it's time to 25.724 + close the entry in your team's bug database. The bug 25.725 + database requires a changeset ID when you close an entry, 25.726 + but you don't remember which changeset you fixed the bug in. 25.727 + Once again, your binary test checks for the presence of the 25.728 + bug.</para> 25.729 + </listitem> 25.730 + <listitem><para>Your software works correctly, but runs 15% 25.731 + slower than the last time you measured it. You want to know 25.732 + which changeset introduced the performance regression. In 25.733 + this case, your binary test measures the performance of your 25.734 + software, to see whether it's <quote>fast</quote> or 25.735 + <quote>slow</quote>.</para> 25.736 + </listitem> 25.737 + <listitem><para>The sizes of the components of your project that 25.738 + you ship exploded recently, and you suspect that something 25.739 + changed in the way you build your project.</para> 25.740 + </listitem></itemizedlist> 25.741 + 25.742 + <para>From these examples, it should be clear that the <command 25.743 + role="hg-cmd">hg bisect</command> command is not useful only 25.744 + for finding the sources of bugs. You can use it to find any 25.745 + <quote>emergent property</quote> of a repository (anything that 25.746 + you can't find from a simple text search of the files in the 25.747 + tree) for which you can write a binary test.</para> 25.748 + 25.749 + <para>We'll introduce a little bit of terminology here, just to 25.750 + make it clear which parts of the search process are your 25.751 + responsibility, and which are Mercurial's. A 25.752 + <emphasis>test</emphasis> is something that 25.753 + <emphasis>you</emphasis> run when <command role="hg-cmd">hg 25.754 + bisect</command> chooses a changeset. A 25.755 + <emphasis>probe</emphasis> is what <command role="hg-cmd">hg 25.756 + bisect</command> runs to tell whether a revision is good. 25.757 + Finally, we'll use the word <quote>bisect</quote>, as both a 25.758 + noun and a verb, to stand in for the phrase <quote>search using 25.759 + the <command role="hg-cmd">hg bisect</command> 25.760 + command</quote>.</para> 25.761 + 25.762 + <para>One simple way to automate the searching process would be 25.763 + simply to probe every changeset. However, this scales poorly. 25.764 + If it took ten minutes to test a single changeset, and you had 25.765 + 10,000 changesets in your repository, the exhaustive approach 25.766 + would take on average 35 <emphasis>days</emphasis> to find the 25.767 + changeset that introduced a bug. Even if you knew that the bug 25.768 + was introduced by one of the last 500 changesets, and limited 25.769 + your search to those, you'd still be looking at over 40 hours to 25.770 + find the changeset that introduced your bug.</para> 25.771 + 25.772 + <para>What the <command role="hg-cmd">hg bisect</command> command 25.773 + does is use its knowledge of the <quote>shape</quote> of your 25.774 + project's revision history to perform a search in time 25.775 + proportional to the <emphasis>logarithm</emphasis> of the number 25.776 + of changesets to check (the kind of search it performs is called 25.777 + a dichotomic search). With this approach, searching through 25.778 + 10,000 changesets will take less than three hours, even at ten 25.779 + minutes per test (the search will require about 14 tests). 25.780 + Limit your search to the last hundred changesets, and it will 25.781 + take only about an hour (roughly seven tests).</para> 25.782 + 25.783 + <para>The <command role="hg-cmd">hg bisect</command> command is 25.784 + aware of the <quote>branchy</quote> nature of a Mercurial 25.785 + project's revision history, so it has no problems dealing with 25.786 + branches, merges, or multiple heads in a repository. It can 25.787 + prune entire branches of history with a single probe, which is 25.788 + how it operates so efficiently.</para> 25.789 + 25.790 + <sect2> 25.791 + <title>Using the <command role="hg-cmd">hg bisect</command> 25.792 + command</title> 25.793 + 25.794 + <para>Here's an example of <command role="hg-cmd">hg 25.795 + bisect</command> in action.</para> 25.796 + 25.797 + <note> 25.798 + <para> In versions 0.9.5 and earlier of Mercurial, <command 25.799 + role="hg-cmd">hg bisect</command> was not a core command: 25.800 + it was distributed with Mercurial as an extension. This 25.801 + section describes the built-in command, not the old 25.802 + extension.</para> 25.803 + </note> 25.804 + 25.805 + <para>Now let's create a repository, so that we can try out the 25.806 + <command role="hg-cmd">hg bisect</command> command in 25.807 + isolation.</para> 25.808 + 25.809 + &interaction.bisect.init; 25.810 + 25.811 + <para>We'll simulate a project that has a bug in it in a 25.812 + simple-minded way: create trivial changes in a loop, and 25.813 + nominate one specific change that will have the 25.814 + <quote>bug</quote>. This loop creates 35 changesets, each 25.815 + adding a single file to the repository. We'll represent our 25.816 + <quote>bug</quote> with a file that contains the text <quote>i 25.817 + have a gub</quote>.</para> 25.818 + 25.819 + &interaction.bisect.commits; 25.820 + 25.821 + <para>The next thing that we'd like to do is figure out how to 25.822 + use the <command role="hg-cmd">hg bisect</command> command. 25.823 + We can use Mercurial's normal built-in help mechanism for 25.824 + this.</para> 25.825 + 25.826 + &interaction.bisect.help; 25.827 + 25.828 + <para>The <command role="hg-cmd">hg bisect</command> command 25.829 + works in steps. Each step proceeds as follows.</para> 25.830 + <orderedlist> 25.831 + <listitem><para>You run your binary test.</para> 25.832 + <itemizedlist> 25.833 + <listitem><para>If the test succeeded, you tell <command 25.834 + role="hg-cmd">hg bisect</command> by running the 25.835 + <command role="hg-cmd">hg bisect good</command> 25.836 + command.</para> 25.837 + </listitem> 25.838 + <listitem><para>If it failed, run the <command 25.839 + role="hg-cmd">hg bisect bad</command> 25.840 + command.</para></listitem></itemizedlist> 25.841 + </listitem> 25.842 + <listitem><para>The command uses your information to decide 25.843 + which changeset to test next.</para> 25.844 + </listitem> 25.845 + <listitem><para>It updates the working directory to that 25.846 + changeset, and the process begins again.</para> 25.847 + </listitem></orderedlist> 25.848 + <para>The process ends when <command role="hg-cmd">hg 25.849 + bisect</command> identifies a unique changeset that marks 25.850 + the point where your test transitioned from 25.851 + <quote>succeeding</quote> to <quote>failing</quote>.</para> 25.852 + 25.853 + <para>To start the search, we must run the <command 25.854 + role="hg-cmd">hg bisect --reset</command> command.</para> 25.855 + 25.856 + &interaction.bisect.search.init; 25.857 + 25.858 + <para>In our case, the binary test we use is simple: we check to 25.859 + see if any file in the repository contains the string <quote>i 25.860 + have a gub</quote>. If it does, this changeset contains the 25.861 + change that <quote>caused the bug</quote>. By convention, a 25.862 + changeset that has the property we're searching for is 25.863 + <quote>bad</quote>, while one that doesn't is 25.864 + <quote>good</quote>.</para> 25.865 + 25.866 + <para>Most of the time, the revision to which the working 25.867 + directory is synced (usually the tip) already exhibits the 25.868 + problem introduced by the buggy change, so we'll mark it as 25.869 + <quote>bad</quote>.</para> 25.870 + 25.871 + &interaction.bisect.search.bad-init; 25.872 + 25.873 + <para>Our next task is to nominate a changeset that we know 25.874 + <emphasis>doesn't</emphasis> have the bug; the <command 25.875 + role="hg-cmd">hg bisect</command> command will 25.876 + <quote>bracket</quote> its search between the first pair of 25.877 + good and bad changesets. In our case, we know that revision 25.878 + 10 didn't have the bug. (I'll have more words about choosing 25.879 + the first <quote>good</quote> changeset later.)</para> 25.880 + 25.881 + &interaction.bisect.search.good-init; 25.882 + 25.883 + <para>Notice that this command printed some output.</para> 25.884 + <itemizedlist> 25.885 + <listitem><para>It told us how many changesets it must 25.886 + consider before it can identify the one that introduced 25.887 + the bug, and how many tests that will require.</para> 25.888 + </listitem> 25.889 + <listitem><para>It updated the working directory to the next 25.890 + changeset to test, and told us which changeset it's 25.891 + testing.</para> 25.892 + </listitem></itemizedlist> 25.893 + 25.894 + <para>We now run our test in the working directory. We use the 25.895 + <command>grep</command> command to see if our 25.896 + <quote>bad</quote> file is present in the working directory. 25.897 + If it is, this revision is bad; if not, this revision is good. 25.898 + &interaction.bisect.search.step1;</para> 25.899 + 25.900 + <para>This test looks like a perfect candidate for automation, 25.901 + so let's turn it into a shell function.</para> 25.902 + &interaction.bisect.search.mytest; 25.903 + 25.904 + <para>We can now run an entire test step with a single command, 25.905 + <literal>mytest</literal>.</para> 25.906 + 25.907 + &interaction.bisect.search.step2; 25.908 + 25.909 + <para>A few more invocations of our canned test step command, 25.910 + and we're done.</para> 25.911 + 25.912 + &interaction.bisect.search.rest; 25.913 + 25.914 + <para>Even though we had 40 changesets to search through, the 25.915 + <command role="hg-cmd">hg bisect</command> command let us find 25.916 + the changeset that introduced our <quote>bug</quote> with only 25.917 + five tests. Because the number of tests that the <command 25.918 + role="hg-cmd">hg bisect</command> command performs grows 25.919 + logarithmically with the number of changesets to search, the 25.920 + advantage that it has over the <quote>brute force</quote> 25.921 + search approach increases with every changeset you add.</para> 25.922 + 25.923 + </sect2> 25.924 + <sect2> 25.925 + <title>Cleaning up after your search</title> 25.926 + 25.927 + <para>When you're finished using the <command role="hg-cmd">hg 25.928 + bisect</command> command in a repository, you can use the 25.929 + <command role="hg-cmd">hg bisect reset</command> command to 25.930 + drop the information it was using to drive your search. The 25.931 + command doesn't use much space, so it doesn't matter if you 25.932 + forget to run this command. However, <command 25.933 + role="hg-cmd">hg bisect</command> won't let you start a new 25.934 + search in that repository until you do a <command 25.935 + role="hg-cmd">hg bisect reset</command>.</para> 25.936 + 25.937 + &interaction.bisect.search.reset; 25.938 + 25.939 + </sect2> 25.940 + </sect1> 25.941 + <sect1> 25.942 + <title>Tips for finding bugs effectively</title> 25.943 + 25.944 + <sect2> 25.945 + <title>Give consistent input</title> 25.946 + 25.947 + <para>The <command role="hg-cmd">hg bisect</command> command 25.948 + requires that you correctly report the result of every test 25.949 + you perform. If you tell it that a test failed when it really 25.950 + succeeded, it <emphasis>might</emphasis> be able to detect the 25.951 + inconsistency. If it can identify an inconsistency in your 25.952 + reports, it will tell you that a particular changeset is both 25.953 + good and bad. However, it can't do this perfectly; it's about 25.954 + as likely to report the wrong changeset as the source of the 25.955 + bug.</para> 25.956 + 25.957 + </sect2> 25.958 + <sect2> 25.959 + <title>Automate as much as possible</title> 25.960 + 25.961 + <para>When I started using the <command role="hg-cmd">hg 25.962 + bisect</command> command, I tried a few times to run my 25.963 + tests by hand, on the command line. This is an approach that 25.964 + I, at least, am not suited to. After a few tries, I found 25.965 + that I was making enough mistakes that I was having to restart 25.966 + my searches several times before finally getting correct 25.967 + results.</para> 25.968 + 25.969 + <para>My initial problems with driving the <command 25.970 + role="hg-cmd">hg bisect</command> command by hand occurred 25.971 + even with simple searches on small repositories; if the 25.972 + problem you're looking for is more subtle, or the number of 25.973 + tests that <command role="hg-cmd">hg bisect</command> must 25.974 + perform increases, the likelihood of operator error ruining 25.975 + the search is much higher. Once I started automating my 25.976 + tests, I had much better results.</para> 25.977 + 25.978 + <para>The key to automated testing is twofold:</para> 25.979 + <itemizedlist> 25.980 + <listitem><para>always test for the same symptom, and</para> 25.981 + </listitem> 25.982 + <listitem><para>always feed consistent input to the <command 25.983 + role="hg-cmd">hg bisect</command> command.</para> 25.984 + </listitem></itemizedlist> 25.985 + <para>In my tutorial example above, the <command>grep</command> 25.986 + command tests for the symptom, and the <literal>if</literal> 25.987 + statement takes the result of this check and ensures that we 25.988 + always feed the same input to the <command role="hg-cmd">hg 25.989 + bisect</command> command. The <literal>mytest</literal> 25.990 + function marries these together in a reproducible way, so that 25.991 + every test is uniform and consistent.</para> 25.992 + 25.993 + </sect2> 25.994 + <sect2> 25.995 + <title>Check your results</title> 25.996 + 25.997 + <para>Because the output of a <command role="hg-cmd">hg 25.998 + bisect</command> search is only as good as the input you 25.999 + give it, don't take the changeset it reports as the absolute 25.1000 + truth. A simple way to cross-check its report is to manually 25.1001 + run your test at each of the following changesets:</para> 25.1002 + <itemizedlist> 25.1003 + <listitem><para>The changeset that it reports as the first bad 25.1004 + revision. Your test should still report this as 25.1005 + bad.</para> 25.1006 + </listitem> 25.1007 + <listitem><para>The parent of that changeset (either parent, 25.1008 + if it's a merge). Your test should report this changeset 25.1009 + as good.</para> 25.1010 + </listitem> 25.1011 + <listitem><para>A child of that changeset. Your test should 25.1012 + report this changeset as bad.</para> 25.1013 + </listitem></itemizedlist> 25.1014 + 25.1015 + </sect2> 25.1016 + <sect2> 25.1017 + <title>Beware interference between bugs</title> 25.1018 + 25.1019 + <para>It's possible that your search for one bug could be 25.1020 + disrupted by the presence of another. For example, let's say 25.1021 + your software crashes at revision 100, and worked correctly at 25.1022 + revision 50. Unknown to you, someone else introduced a 25.1023 + different crashing bug at revision 60, and fixed it at 25.1024 + revision 80. This could distort your results in one of 25.1025 + several ways.</para> 25.1026 + 25.1027 + <para>It is possible that this other bug completely 25.1028 + <quote>masks</quote> yours, which is to say that it occurs 25.1029 + before your bug has a chance to manifest itself. If you can't 25.1030 + avoid that other bug (for example, it prevents your project 25.1031 + from building), and so can't tell whether your bug is present 25.1032 + in a particular changeset, the <command role="hg-cmd">hg 25.1033 + bisect</command> command cannot help you directly. Instead, 25.1034 + you can mark a changeset as untested by running <command 25.1035 + role="hg-cmd">hg bisect --skip</command>.</para> 25.1036 + 25.1037 + <para>A different problem could arise if your test for a bug's 25.1038 + presence is not specific enough. If you check for <quote>my 25.1039 + program crashes</quote>, then both your crashing bug and an 25.1040 + unrelated crashing bug that masks it will look like the same 25.1041 + thing, and mislead <command role="hg-cmd">hg 25.1042 + bisect</command>.</para> 25.1043 + 25.1044 + <para>Another useful situation in which to use <command 25.1045 + role="hg-cmd">hg bisect --skip</command> is if you can't 25.1046 + test a revision because your project was in a broken and hence 25.1047 + untestable state at that revision, perhaps because someone 25.1048 + checked in a change that prevented the project from 25.1049 + building.</para> 25.1050 + 25.1051 + </sect2> 25.1052 + <sect2> 25.1053 + <title>Bracket your search lazily</title> 25.1054 + 25.1055 + <para>Choosing the first <quote>good</quote> and 25.1056 + <quote>bad</quote> changesets that will mark the end points of 25.1057 + your search is often easy, but it bears a little discussion 25.1058 + nevertheless. From the perspective of <command 25.1059 + role="hg-cmd">hg bisect</command>, the <quote>newest</quote> 25.1060 + changeset is conventionally <quote>bad</quote>, and the older 25.1061 + changeset is <quote>good</quote>.</para> 25.1062 + 25.1063 + <para>If you're having trouble remembering when a suitable 25.1064 + <quote>good</quote> change was, so that you can tell <command 25.1065 + role="hg-cmd">hg bisect</command>, you could do worse than 25.1066 + testing changesets at random. Just remember to eliminate 25.1067 + contenders that can't possibly exhibit the bug (perhaps 25.1068 + because the feature with the bug isn't present yet) and those 25.1069 + where another problem masks the bug (as I discussed 25.1070 + above).</para> 25.1071 + 25.1072 + <para>Even if you end up <quote>early</quote> by thousands of 25.1073 + changesets or months of history, you will only add a handful 25.1074 + of tests to the total number that <command role="hg-cmd">hg 25.1075 + bisect</command> must perform, thanks to its logarithmic 25.1076 + behaviour.</para> 25.1077 + 25.1078 + </sect2> 25.1079 + </sect1> 25.1080 +</chapter> 25.1081 + 25.1082 +<!-- 25.1083 +local variables: 25.1084 +sgml-parent-document: ("00book.xml" "book" "chapter") 25.1085 +end: 25.1086 +-->
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/en/ch09-hook.xml Fri Mar 20 16:43:35 2009 +0800 26.3 @@ -0,0 +1,2037 @@ 26.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 26.5 + 26.6 +<chapter id="chap.hook"> 26.7 + <?dbhtml filename="handling-repository-events-with-hooks.html"?> 26.8 + <title>Handling repository events with hooks</title> 26.9 + 26.10 + <para>Mercurial offers a powerful mechanism to let you perform 26.11 + automated actions in response to events that occur in a 26.12 + repository. In some cases, you can even control Mercurial's 26.13 + response to those events.</para> 26.14 + 26.15 + <para>The name Mercurial uses for one of these actions is a 26.16 + <emphasis>hook</emphasis>. Hooks are called 26.17 + <quote>triggers</quote> in some revision control systems, but the 26.18 + two names refer to the same idea.</para> 26.19 + 26.20 + <sect1> 26.21 + <title>An overview of hooks in Mercurial</title> 26.22 + 26.23 + <para>Here is a brief list of the hooks that Mercurial supports. 26.24 + We will revisit each of these hooks in more detail later, in 26.25 + section <xref linkend="sec.hook.ref"/>.</para> 26.26 + 26.27 + <itemizedlist> 26.28 + <listitem><para><literal role="hook">changegroup</literal>: This 26.29 + is run after a group of changesets has been brought into the 26.30 + repository from elsewhere.</para> 26.31 + </listitem> 26.32 + <listitem><para><literal role="hook">commit</literal>: This is 26.33 + run after a new changeset has been created in the local 26.34 + repository.</para> 26.35 + </listitem> 26.36 + <listitem><para><literal role="hook">incoming</literal>: This is 26.37 + run once for each new changeset that is brought into the 26.38 + repository from elsewhere. Notice the difference from 26.39 + <literal role="hook">changegroup</literal>, which is run 26.40 + once per <emphasis>group</emphasis> of changesets brought 26.41 + in.</para> 26.42 + </listitem> 26.43 + <listitem><para><literal role="hook">outgoing</literal>: This is 26.44 + run after a group of changesets has been transmitted from 26.45 + this repository.</para> 26.46 + </listitem> 26.47 + <listitem><para><literal role="hook">prechangegroup</literal>: 26.48 + This is run before starting to bring a group of changesets 26.49 + into the repository. 26.50 + </para> 26.51 + </listitem> 26.52 + <listitem><para><literal role="hook">precommit</literal>: 26.53 + Controlling. This is run before starting a commit. 26.54 + </para> 26.55 + </listitem> 26.56 + <listitem><para><literal role="hook">preoutgoing</literal>: 26.57 + Controlling. This is run before starting to transmit a group 26.58 + of changesets from this repository. 26.59 + </para> 26.60 + </listitem> 26.61 + <listitem><para><literal role="hook">pretag</literal>: 26.62 + Controlling. This is run before creating a tag. 26.63 + </para> 26.64 + </listitem> 26.65 + <listitem><para><literal 26.66 + role="hook">pretxnchangegroup</literal>: Controlling. This 26.67 + is run after a group of changesets has been brought into the 26.68 + local repository from another, but before the transaction 26.69 + completes that will make the changes permanent in the 26.70 + repository. 26.71 + </para> 26.72 + </listitem> 26.73 + <listitem><para><literal role="hook">pretxncommit</literal>: 26.74 + Controlling. This is run after a new changeset has been 26.75 + created in the local repository, but before the transaction 26.76 + completes that will make it permanent. 26.77 + </para> 26.78 + </listitem> 26.79 + <listitem><para><literal role="hook">preupdate</literal>: 26.80 + Controlling. This is run before starting an update or merge 26.81 + of the working directory. 26.82 + </para> 26.83 + </listitem> 26.84 + <listitem><para><literal role="hook">tag</literal>: This is run 26.85 + after a tag is created. 26.86 + </para> 26.87 + </listitem> 26.88 + <listitem><para><literal role="hook">update</literal>: This is 26.89 + run after an update or merge of the working directory has 26.90 + finished. 26.91 + </para> 26.92 + </listitem></itemizedlist> 26.93 + <para>Each of the hooks whose description begins with the word 26.94 + <quote>Controlling</quote> has the ability to determine whether 26.95 + an activity can proceed. If the hook succeeds, the activity may 26.96 + proceed; if it fails, the activity is either not permitted or 26.97 + undone, depending on the hook. 26.98 + </para> 26.99 + 26.100 + </sect1> 26.101 + <sect1> 26.102 + <title>Hooks and security</title> 26.103 + 26.104 + <sect2> 26.105 + <title>Hooks are run with your privileges</title> 26.106 + 26.107 + <para>When you run a Mercurial command in a repository, and the 26.108 + command causes a hook to run, that hook runs on 26.109 + <emphasis>your</emphasis> system, under 26.110 + <emphasis>your</emphasis> user account, with 26.111 + <emphasis>your</emphasis> privilege level. Since hooks are 26.112 + arbitrary pieces of executable code, you should treat them 26.113 + with an appropriate level of suspicion. Do not install a hook 26.114 + unless you are confident that you know who created it and what 26.115 + it does. 26.116 + </para> 26.117 + 26.118 + <para>In some cases, you may be exposed to hooks that you did 26.119 + not install yourself. If you work with Mercurial on an 26.120 + unfamiliar system, Mercurial will run hooks defined in that 26.121 + system's global <filename role="special">~/.hgrc</filename> 26.122 + file. 26.123 + </para> 26.124 + 26.125 + <para>If you are working with a repository owned by another 26.126 + user, Mercurial can run hooks defined in that user's 26.127 + repository, but it will still run them as <quote>you</quote>. 26.128 + For example, if you <command role="hg-cmd">hg pull</command> 26.129 + from that repository, and its <filename 26.130 + role="special">.hg/hgrc</filename> defines a local <literal 26.131 + role="hook">outgoing</literal> hook, that hook will run 26.132 + under your user account, even though you don't own that 26.133 + repository. 26.134 + </para> 26.135 + 26.136 + <note> 26.137 + <para> This only applies if you are pulling from a repository 26.138 + on a local or network filesystem. If you're pulling over 26.139 + http or ssh, any <literal role="hook">outgoing</literal> 26.140 + hook will run under whatever account is executing the server 26.141 + process, on the server. 26.142 + </para> 26.143 + </note> 26.144 + 26.145 + <para>XXX To see what hooks are defined in a repository, use the 26.146 + <command role="hg-cmd">hg config hooks</command> command. If 26.147 + you are working in one repository, but talking to another that 26.148 + you do not own (e.g. using <command role="hg-cmd">hg 26.149 + pull</command> or <command role="hg-cmd">hg 26.150 + incoming</command>), remember that it is the other 26.151 + repository's hooks you should be checking, not your own. 26.152 + </para> 26.153 + 26.154 + </sect2> 26.155 + <sect2> 26.156 + <title>Hooks do not propagate</title> 26.157 + 26.158 + <para>In Mercurial, hooks are not revision controlled, and do 26.159 + not propagate when you clone, or pull from, a repository. The 26.160 + reason for this is simple: a hook is a completely arbitrary 26.161 + piece of executable code. It runs under your user identity, 26.162 + with your privilege level, on your machine. 26.163 + </para> 26.164 + 26.165 + <para>It would be extremely reckless for any distributed 26.166 + revision control system to implement revision-controlled 26.167 + hooks, as this would offer an easily exploitable way to 26.168 + subvert the accounts of users of the revision control system. 26.169 + </para> 26.170 + 26.171 + <para>Since Mercurial does not propagate hooks, if you are 26.172 + collaborating with other people on a common project, you 26.173 + should not assume that they are using the same Mercurial hooks 26.174 + as you are, or that theirs are correctly configured. You 26.175 + should document the hooks you expect people to use. 26.176 + </para> 26.177 + 26.178 + <para>In a corporate intranet, this is somewhat easier to 26.179 + control, as you can for example provide a 26.180 + <quote>standard</quote> installation of Mercurial on an NFS 26.181 + filesystem, and use a site-wide <filename role="special">~/.hgrc</filename> file to define hooks that all users will 26.182 + see. However, this too has its limits; see below. 26.183 + </para> 26.184 + 26.185 + </sect2> 26.186 + <sect2> 26.187 + <title>Hooks can be overridden</title> 26.188 + 26.189 + <para>Mercurial allows you to override a hook definition by 26.190 + redefining the hook. You can disable it by setting its value 26.191 + to the empty string, or change its behaviour as you wish. 26.192 + </para> 26.193 + 26.194 + <para>If you deploy a system- or site-wide <filename 26.195 + role="special">~/.hgrc</filename> file that defines some 26.196 + hooks, you should thus understand that your users can disable 26.197 + or override those hooks. 26.198 + </para> 26.199 + 26.200 + </sect2> 26.201 + <sect2> 26.202 + <title>Ensuring that critical hooks are run</title> 26.203 + 26.204 + <para>Sometimes you may want to enforce a policy that you do not 26.205 + want others to be able to work around. For example, you may 26.206 + have a requirement that every changeset must pass a rigorous 26.207 + set of tests. Defining this requirement via a hook in a 26.208 + site-wide <filename role="special">~/.hgrc</filename> won't 26.209 + work for remote users on laptops, and of course local users 26.210 + can subvert it at will by overriding the hook. 26.211 + </para> 26.212 + 26.213 + <para>Instead, you can set up your policies for use of Mercurial 26.214 + so that people are expected to propagate changes through a 26.215 + well-known <quote>canonical</quote> server that you have 26.216 + locked down and configured appropriately. 26.217 + </para> 26.218 + 26.219 + <para>One way to do this is via a combination of social 26.220 + engineering and technology. Set up a restricted-access 26.221 + account; users can push changes over the network to 26.222 + repositories managed by this account, but they cannot log into 26.223 + the account and run normal shell commands. In this scenario, 26.224 + a user can commit a changeset that contains any old garbage 26.225 + they want. 26.226 + </para> 26.227 + 26.228 + <para>When someone pushes a changeset to the server that 26.229 + everyone pulls from, the server will test the changeset before 26.230 + it accepts it as permanent, and reject it if it fails to pass 26.231 + the test suite. If people only pull changes from this 26.232 + filtering server, it will serve to ensure that all changes 26.233 + that people pull have been automatically vetted. 26.234 + </para> 26.235 + 26.236 + </sect2> 26.237 + </sect1> 26.238 + <sect1> 26.239 + <title>Care with <literal>pretxn</literal> hooks in a 26.240 + shared-access repository</title> 26.241 + 26.242 + <para>If you want to use hooks to do some automated work in a 26.243 + repository that a number of people have shared access to, you 26.244 + need to be careful in how you do this. 26.245 + </para> 26.246 + 26.247 + <para>Mercurial only locks a repository when it is writing to the 26.248 + repository, and only the parts of Mercurial that write to the 26.249 + repository pay attention to locks. Write locks are necessary to 26.250 + prevent multiple simultaneous writers from scribbling on each 26.251 + other's work, corrupting the repository. 26.252 + </para> 26.253 + 26.254 + <para>Because Mercurial is careful with the order in which it 26.255 + reads and writes data, it does not need to acquire a lock when 26.256 + it wants to read data from the repository. The parts of 26.257 + Mercurial that read from the repository never pay attention to 26.258 + locks. This lockless reading scheme greatly increases 26.259 + performance and concurrency. 26.260 + </para> 26.261 + 26.262 + <para>With great performance comes a trade-off, though, one which 26.263 + has the potential to cause you trouble unless you're aware of 26.264 + it. To describe this requires a little detail about how 26.265 + Mercurial adds changesets to a repository and reads those 26.266 + changes. 26.267 + </para> 26.268 + 26.269 + <para>When Mercurial <emphasis>writes</emphasis> metadata, it 26.270 + writes it straight into the destination file. It writes file 26.271 + data first, then manifest data (which contains pointers to the 26.272 + new file data), then changelog data (which contains pointers to 26.273 + the new manifest data). Before the first write to each file, it 26.274 + stores a record of where the end of the file was in its 26.275 + transaction log. If the transaction must be rolled back, 26.276 + Mercurial simply truncates each file back to the size it was 26.277 + before the transaction began. 26.278 + </para> 26.279 + 26.280 + <para>When Mercurial <emphasis>reads</emphasis> metadata, it reads 26.281 + the changelog first, then everything else. Since a reader will 26.282 + only access parts of the manifest or file metadata that it can 26.283 + see in the changelog, it can never see partially written data. 26.284 + </para> 26.285 + 26.286 + <para>Some controlling hooks (<literal 26.287 + role="hook">pretxncommit</literal> and <literal 26.288 + role="hook">pretxnchangegroup</literal>) run when a 26.289 + transaction is almost complete. All of the metadata has been 26.290 + written, but Mercurial can still roll the transaction back and 26.291 + cause the newly-written data to disappear. 26.292 + </para> 26.293 + 26.294 + <para>If one of these hooks runs for long, it opens a window of 26.295 + time during which a reader can see the metadata for changesets 26.296 + that are not yet permanent, and should not be thought of as 26.297 + <quote>really there</quote>. The longer the hook runs, the 26.298 + longer that window is open. 26.299 + </para> 26.300 + 26.301 + <sect2> 26.302 + <title>The problem illustrated</title> 26.303 + 26.304 + <para>In principle, a good use for the <literal 26.305 + role="hook">pretxnchangegroup</literal> hook would be to 26.306 + automatically build and test incoming changes before they are 26.307 + accepted into a central repository. This could let you 26.308 + guarantee that nobody can push changes to this repository that 26.309 + <quote>break the build</quote>. But if a client can pull 26.310 + changes while they're being tested, the usefulness of the test 26.311 + is zero; an unsuspecting someone can pull untested changes, 26.312 + potentially breaking their build. 26.313 + </para> 26.314 + 26.315 + <para>The safest technological answer to this challenge is to 26.316 + set up such a <quote>gatekeeper</quote> repository as 26.317 + <emphasis>unidirectional</emphasis>. Let it take changes 26.318 + pushed in from the outside, but do not allow anyone to pull 26.319 + changes from it (use the <literal 26.320 + role="hook">preoutgoing</literal> hook to lock it down). 26.321 + Configure a <literal role="hook">changegroup</literal> hook so 26.322 + that if a build or test succeeds, the hook will push the new 26.323 + changes out to another repository that people 26.324 + <emphasis>can</emphasis> pull from. 26.325 + </para> 26.326 + 26.327 + <para>In practice, putting a centralised bottleneck like this in 26.328 + place is not often a good idea, and transaction visibility has 26.329 + nothing to do with the problem. As the size of a 26.330 + project&emdash;and the time it takes to build and 26.331 + test&emdash;grows, you rapidly run into a wall with this 26.332 + <quote>try before you buy</quote> approach, where you have 26.333 + more changesets to test than time in which to deal with them. 26.334 + The inevitable result is frustration on the part of all 26.335 + involved. 26.336 + </para> 26.337 + 26.338 + <para>An approach that scales better is to get people to build 26.339 + and test before they push, then run automated builds and tests 26.340 + centrally <emphasis>after</emphasis> a push, to be sure all is 26.341 + well. The advantage of this approach is that it does not 26.342 + impose a limit on the rate at which the repository can accept 26.343 + changes. 26.344 + </para> 26.345 + 26.346 + </sect2> 26.347 + </sect1> 26.348 + <sect1 id="sec.hook.simple"> 26.349 + <title>A short tutorial on using hooks</title> 26.350 + 26.351 + <para>It is easy to write a Mercurial hook. Let's start with a 26.352 + hook that runs when you finish a <command role="hg-cmd">hg 26.353 + commit</command>, and simply prints the hash of the changeset 26.354 + you just created. The hook is called <literal 26.355 + role="hook">commit</literal>. 26.356 + </para> 26.357 + 26.358 + <para>All hooks follow the pattern in this example.</para> 26.359 + 26.360 +&interaction.hook.simple.init; 26.361 + 26.362 + <para>You add an entry to the <literal 26.363 + role="rc-hooks">hooks</literal> section of your <filename 26.364 + role="special">~/.hgrc</filename>. On the left is the name of 26.365 + the event to trigger on; on the right is the action to take. As 26.366 + you can see, you can run an arbitrary shell command in a hook. 26.367 + Mercurial passes extra information to the hook using environment 26.368 + variables (look for <envar>HG_NODE</envar> in the example). 26.369 + </para> 26.370 + 26.371 + <sect2> 26.372 + <title>Performing multiple actions per event</title> 26.373 + 26.374 + <para>Quite often, you will want to define more than one hook 26.375 + for a particular kind of event, as shown below.</para> 26.376 + 26.377 +&interaction.hook.simple.ext; 26.378 + 26.379 + <para>Mercurial lets you do this by adding an 26.380 + <emphasis>extension</emphasis> to the end of a hook's name. 26.381 + You extend a hook's name by giving the name of the hook, 26.382 + followed by a full stop (the 26.383 + <quote><literal>.</literal></quote> character), followed by 26.384 + some more text of your choosing. For example, Mercurial will 26.385 + run both <literal>commit.foo</literal> and 26.386 + <literal>commit.bar</literal> when the 26.387 + <literal>commit</literal> event occurs. 26.388 + </para> 26.389 + 26.390 + <para>To give a well-defined order of execution when there are 26.391 + multiple hooks defined for an event, Mercurial sorts hooks by 26.392 + extension, and executes the hook commands in this sorted 26.393 + order. In the above example, it will execute 26.394 + <literal>commit.bar</literal> before 26.395 + <literal>commit.foo</literal>, and <literal>commit</literal> 26.396 + before both. 26.397 + </para> 26.398 + 26.399 + <para>It is a good idea to use a somewhat descriptive extension 26.400 + when you define a new hook. This will help you to remember 26.401 + what the hook was for. If the hook fails, you'll get an error 26.402 + message that contains the hook name and extension, so using a 26.403 + descriptive extension could give you an immediate hint as to 26.404 + why the hook failed (see section <xref 26.405 + linkend="sec.hook.perm"/> for an example). 26.406 + </para> 26.407 + 26.408 + </sect2> 26.409 + <sect2 id="sec.hook.perm"> 26.410 + <title>Controlling whether an activity can proceed</title> 26.411 + 26.412 + <para>In our earlier examples, we used the <literal 26.413 + role="hook">commit</literal> hook, which is run after a 26.414 + commit has completed. This is one of several Mercurial hooks 26.415 + that run after an activity finishes. Such hooks have no way 26.416 + of influencing the activity itself. 26.417 + </para> 26.418 + 26.419 + <para>Mercurial defines a number of events that occur before an 26.420 + activity starts; or after it starts, but before it finishes. 26.421 + Hooks that trigger on these events have the added ability to 26.422 + choose whether the activity can continue, or will abort. 26.423 + </para> 26.424 + 26.425 + <para>The <literal role="hook">pretxncommit</literal> hook runs 26.426 + after a commit has all but completed. In other words, the 26.427 + metadata representing the changeset has been written out to 26.428 + disk, but the transaction has not yet been allowed to 26.429 + complete. The <literal role="hook">pretxncommit</literal> 26.430 + hook has the ability to decide whether the transaction can 26.431 + complete, or must be rolled back. 26.432 + </para> 26.433 + 26.434 + <para>If the <literal role="hook">pretxncommit</literal> hook 26.435 + exits with a status code of zero, the transaction is allowed 26.436 + to complete; the commit finishes; and the <literal 26.437 + role="hook">commit</literal> hook is run. If the <literal 26.438 + role="hook">pretxncommit</literal> hook exits with a 26.439 + non-zero status code, the transaction is rolled back; the 26.440 + metadata representing the changeset is erased; and the 26.441 + <literal role="hook">commit</literal> hook is not run. 26.442 + </para> 26.443 + 26.444 +&interaction.hook.simple.pretxncommit; 26.445 + 26.446 + <para>The hook in the example above checks that a commit comment 26.447 + contains a bug ID. If it does, the commit can complete. If 26.448 + not, the commit is rolled back. 26.449 + </para> 26.450 + 26.451 + </sect2> 26.452 + </sect1> 26.453 + <sect1> 26.454 + <title>Writing your own hooks</title> 26.455 + 26.456 + <para>When you are writing a hook, you might find it useful to run 26.457 + Mercurial either with the <option 26.458 + role="hg-opt-global">-v</option> option, or the <envar 26.459 + role="rc-item-ui">verbose</envar> config item set to 26.460 + <quote>true</quote>. When you do so, Mercurial will print a 26.461 + message before it calls each hook. 26.462 + </para> 26.463 + 26.464 + <sect2 id="sec.hook.lang"> 26.465 + <title>Choosing how your hook should run</title> 26.466 + 26.467 + <para>You can write a hook either as a normal 26.468 + program&emdash;typically a shell script&emdash;or as a Python 26.469 + function that is executed within the Mercurial process. 26.470 + </para> 26.471 + 26.472 + <para>Writing a hook as an external program has the advantage 26.473 + that it requires no knowledge of Mercurial's internals. You 26.474 + can call normal Mercurial commands to get any added 26.475 + information you need. The trade-off is that external hooks 26.476 + are slower than in-process hooks. 26.477 + </para> 26.478 + 26.479 + <para>An in-process Python hook has complete access to the 26.480 + Mercurial API, and does not <quote>shell out</quote> to 26.481 + another process, so it is inherently faster than an external 26.482 + hook. It is also easier to obtain much of the information 26.483 + that a hook requires by using the Mercurial API than by 26.484 + running Mercurial commands. 26.485 + </para> 26.486 + 26.487 + <para>If you are comfortable with Python, or require high 26.488 + performance, writing your hooks in Python may be a good 26.489 + choice. However, when you have a straightforward hook to 26.490 + write and you don't need to care about performance (probably 26.491 + the majority of hooks), a shell script is perfectly fine. 26.492 + </para> 26.493 + 26.494 + </sect2> 26.495 + <sect2 id="sec.hook.param"> 26.496 + <title>Hook parameters</title> 26.497 + 26.498 + <para>Mercurial calls each hook with a set of well-defined 26.499 + parameters. In Python, a parameter is passed as a keyword 26.500 + argument to your hook function. For an external program, a 26.501 + parameter is passed as an environment variable. 26.502 + </para> 26.503 + 26.504 + <para>Whether your hook is written in Python or as a shell 26.505 + script, the hook-specific parameter names and values will be 26.506 + the same. A boolean parameter will be represented as a 26.507 + boolean value in Python, but as the number 1 (for 26.508 + <quote>true</quote>) or 0 (for <quote>false</quote>) as an 26.509 + environment variable for an external hook. If a hook 26.510 + parameter is named <literal>foo</literal>, the keyword 26.511 + argument for a Python hook will also be named 26.512 + <literal>foo</literal>, while the environment variable for an 26.513 + external hook will be named <literal>HG_FOO</literal>. 26.514 + </para> 26.515 + 26.516 + </sect2> 26.517 + <sect2> 26.518 + <title>Hook return values and activity control</title> 26.519 + 26.520 + <para>A hook that executes successfully must exit with a status 26.521 + of zero if external, or return boolean <quote>false</quote> if 26.522 + in-process. Failure is indicated with a non-zero exit status 26.523 + from an external hook, or an in-process hook returning boolean 26.524 + <quote>true</quote>. If an in-process hook raises an 26.525 + exception, the hook is considered to have failed. 26.526 + </para> 26.527 + 26.528 + <para>For a hook that controls whether an activity can proceed, 26.529 + zero/false means <quote>allow</quote>, while 26.530 + non-zero/true/exception means <quote>deny</quote>. 26.531 + </para> 26.532 + 26.533 + </sect2> 26.534 + <sect2> 26.535 + <title>Writing an external hook</title> 26.536 + 26.537 + <para>When you define an external hook in your <filename 26.538 + role="special">~/.hgrc</filename> and the hook is run, its 26.539 + value is passed to your shell, which interprets it. This 26.540 + means that you can use normal shell constructs in the body of 26.541 + the hook. 26.542 + </para> 26.543 + 26.544 + <para>An executable hook is always run with its current 26.545 + directory set to a repository's root directory. 26.546 + </para> 26.547 + 26.548 + <para>Each hook parameter is passed in as an environment 26.549 + variable; the name is upper-cased, and prefixed with the 26.550 + string <quote><literal>HG_</literal></quote>. 26.551 + </para> 26.552 + 26.553 + <para>With the exception of hook parameters, Mercurial does not 26.554 + set or modify any environment variables when running a hook. 26.555 + This is useful to remember if you are writing a site-wide hook 26.556 + that may be run by a number of different users with differing 26.557 + environment variables set. In multi-user situations, you 26.558 + should not rely on environment variables being set to the 26.559 + values you have in your environment when testing the hook. 26.560 + </para> 26.561 + 26.562 + </sect2> 26.563 + <sect2> 26.564 + <title>Telling Mercurial to use an in-process hook</title> 26.565 + 26.566 + <para>The <filename role="special">~/.hgrc</filename> syntax 26.567 + for defining an in-process hook is slightly different than for 26.568 + an executable hook. The value of the hook must start with the 26.569 + text <quote><literal>python:</literal></quote>, and continue 26.570 + with the fully-qualified name of a callable object to use as 26.571 + the hook's value. 26.572 + </para> 26.573 + 26.574 + <para>The module in which a hook lives is automatically imported 26.575 + when a hook is run. So long as you have the module name and 26.576 + <envar>PYTHONPATH</envar> right, it should <quote>just 26.577 + work</quote>. 26.578 + </para> 26.579 + 26.580 + <para>The following <filename role="special">~/.hgrc</filename> 26.581 + example snippet illustrates the syntax and meaning of the 26.582 + notions we just described. 26.583 + </para> 26.584 + <programlisting>[hooks] 26.585 +commit.example = python:mymodule.submodule.myhook</programlisting> 26.586 + <para>When Mercurial runs the <literal>commit.example</literal> 26.587 + hook, it imports <literal>mymodule.submodule</literal>, looks 26.588 + for the callable object named <literal>myhook</literal>, and 26.589 + calls it. 26.590 + </para> 26.591 + 26.592 + </sect2> 26.593 + <sect2> 26.594 + <title>Writing an in-process hook</title> 26.595 + 26.596 + <para>The simplest in-process hook does nothing, but illustrates 26.597 + the basic shape of the hook API: 26.598 + </para> 26.599 + <programlisting>def myhook(ui, repo, **kwargs): 26.600 + pass</programlisting> 26.601 + <para>The first argument to a Python hook is always a <literal 26.602 + role="py-mod-mercurial.ui">ui</literal> object. The second 26.603 + is a repository object; at the moment, it is always an 26.604 + instance of <literal 26.605 + role="py-mod-mercurial.localrepo">localrepository</literal>. 26.606 + Following these two arguments are other keyword arguments. 26.607 + Which ones are passed in depends on the hook being called, but 26.608 + a hook can ignore arguments it doesn't care about by dropping 26.609 + them into a keyword argument dict, as with 26.610 + <literal>**kwargs</literal> above. 26.611 + </para> 26.612 + 26.613 + </sect2> 26.614 + </sect1> 26.615 + <sect1> 26.616 + <title>Some hook examples</title> 26.617 + 26.618 + <sect2> 26.619 + <title>Writing meaningful commit messages</title> 26.620 + 26.621 + <para>It's hard to imagine a useful commit message being very 26.622 + short. The simple <literal role="hook">pretxncommit</literal> 26.623 + hook of the example below will prevent you from committing a 26.624 + changeset with a message that is less than ten bytes long. 26.625 + </para> 26.626 + 26.627 +&interaction.hook.msglen.go; 26.628 + 26.629 + </sect2> 26.630 + <sect2> 26.631 + <title>Checking for trailing whitespace</title> 26.632 + 26.633 + <para>An interesting use of a commit-related hook is to help you 26.634 + to write cleaner code. A simple example of <quote>cleaner 26.635 + code</quote> is the dictum that a change should not add any 26.636 + new lines of text that contain <quote>trailing 26.637 + whitespace</quote>. Trailing whitespace is a series of 26.638 + space and tab characters at the end of a line of text. In 26.639 + most cases, trailing whitespace is unnecessary, invisible 26.640 + noise, but it is occasionally problematic, and people often 26.641 + prefer to get rid of it. 26.642 + </para> 26.643 + 26.644 + <para>You can use either the <literal 26.645 + role="hook">precommit</literal> or <literal 26.646 + role="hook">pretxncommit</literal> hook to tell whether you 26.647 + have a trailing whitespace problem. If you use the <literal 26.648 + role="hook">precommit</literal> hook, the hook will not know 26.649 + which files you are committing, so it will have to check every 26.650 + modified file in the repository for trailing white space. If 26.651 + you want to commit a change to just the file 26.652 + <filename>foo</filename>, but the file 26.653 + <filename>bar</filename> contains trailing whitespace, doing a 26.654 + check in the <literal role="hook">precommit</literal> hook 26.655 + will prevent you from committing <filename>foo</filename> due 26.656 + to the problem with <filename>bar</filename>. This doesn't 26.657 + seem right. 26.658 + </para> 26.659 + 26.660 + <para>Should you choose the <literal 26.661 + role="hook">pretxncommit</literal> hook, the check won't 26.662 + occur until just before the transaction for the commit 26.663 + completes. This will allow you to check for problems only the 26.664 + exact files that are being committed. However, if you entered 26.665 + the commit message interactively and the hook fails, the 26.666 + transaction will roll back; you'll have to re-enter the commit 26.667 + message after you fix the trailing whitespace and run <command 26.668 + role="hg-cmd">hg commit</command> again. 26.669 + </para> 26.670 + 26.671 +&interaction.hook.ws.simple; 26.672 + 26.673 + <para>In this example, we introduce a simple <literal 26.674 + role="hook">pretxncommit</literal> hook that checks for 26.675 + trailing whitespace. This hook is short, but not very 26.676 + helpful. It exits with an error status if a change adds a 26.677 + line with trailing whitespace to any file, but does not print 26.678 + any information that might help us to identify the offending 26.679 + file or line. It also has the nice property of not paying 26.680 + attention to unmodified lines; only lines that introduce new 26.681 + trailing whitespace cause problems. 26.682 + </para> 26.683 + 26.684 + <para>The above version is much more complex, but also more 26.685 + useful. It parses a unified diff to see if any lines add 26.686 + trailing whitespace, and prints the name of the file and the 26.687 + line number of each such occurrence. Even better, if the 26.688 + change adds trailing whitespace, this hook saves the commit 26.689 + comment and prints the name of the save file before exiting 26.690 + and telling Mercurial to roll the transaction back, so you can 26.691 + use the <option role="hg-opt-commit">-l filename</option> 26.692 + option to <command role="hg-cmd">hg commit</command> to reuse 26.693 + the saved commit message once you've corrected the problem. 26.694 + </para> 26.695 + 26.696 +&interaction.hook.ws.better; 26.697 + 26.698 + <para>As a final aside, note in the example above the use of 26.699 + <command>perl</command>'s in-place editing feature to get rid 26.700 + of trailing whitespace from a file. This is concise and 26.701 + useful enough that I will reproduce it here. 26.702 + </para> 26.703 + <programlisting>perl -pi -e 's,\s+$,,' filename</programlisting> 26.704 + 26.705 + </sect2> 26.706 + </sect1> 26.707 + <sect1> 26.708 + <title>Bundled hooks</title> 26.709 + 26.710 + <para>Mercurial ships with several bundled hooks. You can find 26.711 + them in the <filename class="directory">hgext</filename> 26.712 + directory of a Mercurial source tree. If you are using a 26.713 + Mercurial binary package, the hooks will be located in the 26.714 + <filename class="directory">hgext</filename> directory of 26.715 + wherever your package installer put Mercurial. 26.716 + </para> 26.717 + 26.718 + <sect2> 26.719 + <title><literal role="hg-ext">acl</literal>&emdash;access 26.720 + control for parts of a repository</title> 26.721 + 26.722 + <para>The <literal role="hg-ext">acl</literal> extension lets 26.723 + you control which remote users are allowed to push changesets 26.724 + to a networked server. You can protect any portion of a 26.725 + repository (including the entire repo), so that a specific 26.726 + remote user can push changes that do not affect the protected 26.727 + portion. 26.728 + </para> 26.729 + 26.730 + <para>This extension implements access control based on the 26.731 + identity of the user performing a push, 26.732 + <emphasis>not</emphasis> on who committed the changesets 26.733 + they're pushing. It makes sense to use this hook only if you 26.734 + have a locked-down server environment that authenticates 26.735 + remote users, and you want to be sure that only specific users 26.736 + are allowed to push changes to that server. 26.737 + </para> 26.738 + 26.739 + <sect3> 26.740 + <title>Configuring the <literal role="hook">acl</literal> 26.741 + hook</title> 26.742 + 26.743 + <para>In order to manage incoming changesets, the <literal 26.744 + role="hg-ext">acl</literal> hook must be used as a 26.745 + <literal role="hook">pretxnchangegroup</literal> hook. This 26.746 + lets it see which files are modified by each incoming 26.747 + changeset, and roll back a group of changesets if they 26.748 + modify <quote>forbidden</quote> files. Example: 26.749 + </para> 26.750 + <programlisting>[hooks] 26.751 +pretxnchangegroup.acl = python:hgext.acl.hook</programlisting> 26.752 + 26.753 + <para>The <literal role="hg-ext">acl</literal> extension is 26.754 + configured using three sections. 26.755 + </para> 26.756 + 26.757 + <para>The <literal role="rc-acl">acl</literal> section has 26.758 + only one entry, <envar role="rc-item-acl">sources</envar>, 26.759 + which lists the sources of incoming changesets that the hook 26.760 + should pay attention to. You don't normally need to 26.761 + configure this section. 26.762 + </para> 26.763 + <itemizedlist> 26.764 + <listitem><para><envar role="rc-item-acl">serve</envar>: 26.765 + Control incoming changesets that are arriving from a 26.766 + remote repository over http or ssh. This is the default 26.767 + value of <envar role="rc-item-acl">sources</envar>, and 26.768 + usually the only setting you'll need for this 26.769 + configuration item. 26.770 + </para> 26.771 + </listitem> 26.772 + <listitem><para><envar role="rc-item-acl">pull</envar>: 26.773 + Control incoming changesets that are arriving via a pull 26.774 + from a local repository. 26.775 + </para> 26.776 + </listitem> 26.777 + <listitem><para><envar role="rc-item-acl">push</envar>: 26.778 + Control incoming changesets that are arriving via a push 26.779 + from a local repository. 26.780 + </para> 26.781 + </listitem> 26.782 + <listitem><para><envar role="rc-item-acl">bundle</envar>: 26.783 + Control incoming changesets that are arriving from 26.784 + another repository via a bundle. 26.785 + </para> 26.786 + </listitem></itemizedlist> 26.787 + 26.788 + <para>The <literal role="rc-acl.allow">acl.allow</literal> 26.789 + section controls the users that are allowed to add 26.790 + changesets to the repository. If this section is not 26.791 + present, all users that are not explicitly denied are 26.792 + allowed. If this section is present, all users that are not 26.793 + explicitly allowed are denied (so an empty section means 26.794 + that all users are denied). 26.795 + </para> 26.796 + 26.797 + <para>The <literal role="rc-acl.deny">acl.deny</literal> 26.798 + section determines which users are denied from adding 26.799 + changesets to the repository. If this section is not 26.800 + present or is empty, no users are denied. 26.801 + </para> 26.802 + 26.803 + <para>The syntaxes for the <literal 26.804 + role="rc-acl.allow">acl.allow</literal> and <literal 26.805 + role="rc-acl.deny">acl.deny</literal> sections are 26.806 + identical. On the left of each entry is a glob pattern that 26.807 + matches files or directories, relative to the root of the 26.808 + repository; on the right, a user name. 26.809 + </para> 26.810 + 26.811 + <para>In the following example, the user 26.812 + <literal>docwriter</literal> can only push changes to the 26.813 + <filename class="directory">docs</filename> subtree of the 26.814 + repository, while <literal>intern</literal> can push changes 26.815 + to any file or directory except <filename 26.816 + class="directory">source/sensitive</filename>. 26.817 + </para> 26.818 + <programlisting>[acl.allow] 26.819 +docs/** = docwriter 26.820 +[acl.deny] 26.821 +source/sensitive/** = intern</programlisting> 26.822 + 26.823 + </sect3> 26.824 + <sect3> 26.825 + <title>Testing and troubleshooting</title> 26.826 + 26.827 + <para>If you want to test the <literal 26.828 + role="hg-ext">acl</literal> hook, run it with Mercurial's 26.829 + debugging output enabled. Since you'll probably be running 26.830 + it on a server where it's not convenient (or sometimes 26.831 + possible) to pass in the <option 26.832 + role="hg-opt-global">--debug</option> option, don't forget 26.833 + that you can enable debugging output in your <filename 26.834 + role="special">~/.hgrc</filename>: 26.835 + </para> 26.836 + <programlisting>[ui] 26.837 +debug = true</programlisting> 26.838 + <para>With this enabled, the <literal 26.839 + role="hg-ext">acl</literal> hook will print enough 26.840 + information to let you figure out why it is allowing or 26.841 + forbidding pushes from specific users. 26.842 + </para> 26.843 + 26.844 + </sect3> 26.845 + </sect2> 26.846 + <sect2> 26.847 + <title><literal 26.848 + role="hg-ext">bugzilla</literal>&emdash;integration with 26.849 + Bugzilla</title> 26.850 + 26.851 + <para>The <literal role="hg-ext">bugzilla</literal> extension 26.852 + adds a comment to a Bugzilla bug whenever it finds a reference 26.853 + to that bug ID in a commit comment. You can install this hook 26.854 + on a shared server, so that any time a remote user pushes 26.855 + changes to this server, the hook gets run. 26.856 + </para> 26.857 + 26.858 + <para>It adds a comment to the bug that looks like this (you can 26.859 + configure the contents of the comment&emdash;see below): 26.860 + </para> 26.861 + <programlisting>Changeset aad8b264143a, made by Joe User 26.862 + <joe.user@domain.com> in the frobnitz repository, refers 26.863 + to this bug. For complete details, see 26.864 + http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 26.865 + Changeset description: Fix bug 10483 by guarding against some 26.866 + NULL pointers</programlisting> 26.867 + <para>The value of this hook is that it automates the process of 26.868 + updating a bug any time a changeset refers to it. If you 26.869 + configure the hook properly, it makes it easy for people to 26.870 + browse straight from a Bugzilla bug to a changeset that refers 26.871 + to that bug. 26.872 + </para> 26.873 + 26.874 + <para>You can use the code in this hook as a starting point for 26.875 + some more exotic Bugzilla integration recipes. Here are a few 26.876 + possibilities: 26.877 + </para> 26.878 + <itemizedlist> 26.879 + <listitem><para>Require that every changeset pushed to the 26.880 + server have a valid bug ID in its commit comment. In this 26.881 + case, you'd want to configure the hook as a <literal 26.882 + role="hook">pretxncommit</literal> hook. This would 26.883 + allow the hook to reject changes that didn't contain bug 26.884 + IDs. 26.885 + </para> 26.886 + </listitem> 26.887 + <listitem><para>Allow incoming changesets to automatically 26.888 + modify the <emphasis>state</emphasis> of a bug, as well as 26.889 + simply adding a comment. For example, the hook could 26.890 + recognise the string <quote>fixed bug 31337</quote> as 26.891 + indicating that it should update the state of bug 31337 to 26.892 + <quote>requires testing</quote>. 26.893 + </para> 26.894 + </listitem></itemizedlist> 26.895 + 26.896 + <sect3 id="sec.hook.bugzilla.config"> 26.897 + <title>Configuring the <literal role="hook">bugzilla</literal> 26.898 + hook</title> 26.899 + 26.900 + <para>You should configure this hook in your server's 26.901 + <filename role="special">~/.hgrc</filename> as an <literal 26.902 + role="hook">incoming</literal> hook, for example as 26.903 + follows: 26.904 + </para> 26.905 + <programlisting>[hooks] 26.906 +incoming.bugzilla = python:hgext.bugzilla.hook</programlisting> 26.907 + 26.908 + <para>Because of the specialised nature of this hook, and 26.909 + because Bugzilla was not written with this kind of 26.910 + integration in mind, configuring this hook is a somewhat 26.911 + involved process. 26.912 + </para> 26.913 + 26.914 + <para>Before you begin, you must install the MySQL bindings 26.915 + for Python on the host(s) where you'll be running the hook. 26.916 + If this is not available as a binary package for your 26.917 + system, you can download it from 26.918 + <citation>web:mysql-python</citation>. 26.919 + </para> 26.920 + 26.921 + <para>Configuration information for this hook lives in the 26.922 + <literal role="rc-bugzilla">bugzilla</literal> section of 26.923 + your <filename role="special">~/.hgrc</filename>. 26.924 + </para> 26.925 + <itemizedlist> 26.926 + <listitem><para><envar 26.927 + role="rc-item-bugzilla">version</envar>: The version 26.928 + of Bugzilla installed on the server. The database 26.929 + schema that Bugzilla uses changes occasionally, so this 26.930 + hook has to know exactly which schema to use. At the 26.931 + moment, the only version supported is 26.932 + <literal>2.16</literal>. 26.933 + </para> 26.934 + </listitem> 26.935 + <listitem><para><envar role="rc-item-bugzilla">host</envar>: 26.936 + The hostname of the MySQL server that stores your 26.937 + Bugzilla data. The database must be configured to allow 26.938 + connections from whatever host you are running the 26.939 + <literal role="hook">bugzilla</literal> hook on. 26.940 + </para> 26.941 + </listitem> 26.942 + <listitem><para><envar role="rc-item-bugzilla">user</envar>: 26.943 + The username with which to connect to the MySQL server. 26.944 + The database must be configured to allow this user to 26.945 + connect from whatever host you are running the <literal 26.946 + role="hook">bugzilla</literal> hook on. This user 26.947 + must be able to access and modify Bugzilla tables. The 26.948 + default value of this item is <literal>bugs</literal>, 26.949 + which is the standard name of the Bugzilla user in a 26.950 + MySQL database. 26.951 + </para> 26.952 + </listitem> 26.953 + <listitem><para><envar 26.954 + role="rc-item-bugzilla">password</envar>: The MySQL 26.955 + password for the user you configured above. This is 26.956 + stored as plain text, so you should make sure that 26.957 + unauthorised users cannot read the <filename 26.958 + role="special">~/.hgrc</filename> file where you 26.959 + store this information. 26.960 + </para> 26.961 + </listitem> 26.962 + <listitem><para><envar role="rc-item-bugzilla">db</envar>: 26.963 + The name of the Bugzilla database on the MySQL server. 26.964 + The default value of this item is 26.965 + <literal>bugs</literal>, which is the standard name of 26.966 + the MySQL database where Bugzilla stores its data. 26.967 + </para> 26.968 + </listitem> 26.969 + <listitem><para><envar 26.970 + role="rc-item-bugzilla">notify</envar>: If you want 26.971 + Bugzilla to send out a notification email to subscribers 26.972 + after this hook has added a comment to a bug, you will 26.973 + need this hook to run a command whenever it updates the 26.974 + database. The command to run depends on where you have 26.975 + installed Bugzilla, but it will typically look something 26.976 + like this, if you have Bugzilla installed in <filename 26.977 + class="directory">/var/www/html/bugzilla</filename>: 26.978 + </para> 26.979 + <programlisting>cd /var/www/html/bugzilla && 26.980 + ./processmail %s nobody@nowhere.com</programlisting> 26.981 + </listitem> 26.982 + <listitem><para> The Bugzilla 26.983 + <literal>processmail</literal> program expects to be 26.984 + given a bug ID (the hook replaces 26.985 + <quote><literal>%s</literal></quote> with the bug ID) 26.986 + and an email address. It also expects to be able to 26.987 + write to some files in the directory that it runs in. 26.988 + If Bugzilla and this hook are not installed on the same 26.989 + machine, you will need to find a way to run 26.990 + <literal>processmail</literal> on the server where 26.991 + Bugzilla is installed. 26.992 + </para> 26.993 + </listitem></itemizedlist> 26.994 + 26.995 + </sect3> 26.996 + <sect3> 26.997 + <title>Mapping committer names to Bugzilla user names</title> 26.998 + 26.999 + <para>By default, the <literal 26.1000 + role="hg-ext">bugzilla</literal> hook tries to use the 26.1001 + email address of a changeset's committer as the Bugzilla 26.1002 + user name with which to update a bug. If this does not suit 26.1003 + your needs, you can map committer email addresses to 26.1004 + Bugzilla user names using a <literal 26.1005 + role="rc-usermap">usermap</literal> section. 26.1006 + </para> 26.1007 + 26.1008 + <para>Each item in the <literal 26.1009 + role="rc-usermap">usermap</literal> section contains an 26.1010 + email address on the left, and a Bugzilla user name on the 26.1011 + right. 26.1012 + </para> 26.1013 + <programlisting>[usermap] 26.1014 +jane.user@example.com = jane</programlisting> 26.1015 + <para>You can either keep the <literal 26.1016 + role="rc-usermap">usermap</literal> data in a normal 26.1017 + <filename role="special">~/.hgrc</filename>, or tell the 26.1018 + <literal role="hg-ext">bugzilla</literal> hook to read the 26.1019 + information from an external <filename>usermap</filename> 26.1020 + file. In the latter case, you can store 26.1021 + <filename>usermap</filename> data by itself in (for example) 26.1022 + a user-modifiable repository. This makes it possible to let 26.1023 + your users maintain their own <envar 26.1024 + role="rc-item-bugzilla">usermap</envar> entries. The main 26.1025 + <filename role="special">~/.hgrc</filename> file might look 26.1026 + like this: 26.1027 + </para> 26.1028 + <programlisting># regular hgrc file refers to external usermap file 26.1029 +[bugzilla] 26.1030 +usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting> 26.1031 + <para>While the <filename>usermap</filename> file that it 26.1032 + refers to might look like this: 26.1033 + </para> 26.1034 + <programlisting># bugzilla-usermap.conf - inside a hg repository 26.1035 +[usermap] stephanie@example.com = steph</programlisting> 26.1036 + 26.1037 + </sect3> 26.1038 + <sect3> 26.1039 + <title>Configuring the text that gets added to a bug</title> 26.1040 + 26.1041 + <para>You can configure the text that this hook adds as a 26.1042 + comment; you specify it in the form of a Mercurial template. 26.1043 + Several <filename role="special">~/.hgrc</filename> entries 26.1044 + (still in the <literal role="rc-bugzilla">bugzilla</literal> 26.1045 + section) control this behaviour. 26.1046 + </para> 26.1047 + <itemizedlist> 26.1048 + <listitem><para><literal>strip</literal>: The number of 26.1049 + leading path elements to strip from a repository's path 26.1050 + name to construct a partial path for a URL. For example, 26.1051 + if the repositories on your server live under <filename 26.1052 + class="directory">/home/hg/repos</filename>, and you 26.1053 + have a repository whose path is <filename 26.1054 + class="directory">/home/hg/repos/app/tests</filename>, 26.1055 + then setting <literal>strip</literal> to 26.1056 + <literal>4</literal> will give a partial path of 26.1057 + <filename class="directory">app/tests</filename>. The 26.1058 + hook will make this partial path available when 26.1059 + expanding a template, as <literal>webroot</literal>. 26.1060 + </para> 26.1061 + </listitem> 26.1062 + <listitem><para><literal>template</literal>: The text of the 26.1063 + template to use. In addition to the usual 26.1064 + changeset-related variables, this template can use 26.1065 + <literal>hgweb</literal> (the value of the 26.1066 + <literal>hgweb</literal> configuration item above) and 26.1067 + <literal>webroot</literal> (the path constructed using 26.1068 + <literal>strip</literal> above). 26.1069 + </para> 26.1070 + </listitem></itemizedlist> 26.1071 + 26.1072 + <para>In addition, you can add a <envar 26.1073 + role="rc-item-web">baseurl</envar> item to the <literal 26.1074 + role="rc-web">web</literal> section of your <filename 26.1075 + role="special">~/.hgrc</filename>. The <literal 26.1076 + role="hg-ext">bugzilla</literal> hook will make this 26.1077 + available when expanding a template, as the base string to 26.1078 + use when constructing a URL that will let users browse from 26.1079 + a Bugzilla comment to view a changeset. Example: 26.1080 + </para> 26.1081 + <programlisting>[web] 26.1082 +baseurl = http://hg.domain.com/</programlisting> 26.1083 + 26.1084 + <para>Here is an example set of <literal 26.1085 + role="hg-ext">bugzilla</literal> hook config information. 26.1086 + </para> 26.1087 + 26.1088 + <programlisting>&ch10-bugzilla-config.lst;</programlisting> 26.1089 + 26.1090 + </sect3> 26.1091 + <sect3> 26.1092 + <title>Testing and troubleshooting</title> 26.1093 + 26.1094 + <para>The most common problems with configuring the <literal 26.1095 + role="hg-ext">bugzilla</literal> hook relate to running 26.1096 + Bugzilla's <filename>processmail</filename> script and 26.1097 + mapping committer names to user names. 26.1098 + </para> 26.1099 + 26.1100 + <para>Recall from section <xref 26.1101 + linkend="sec.hook.bugzilla.config"/> above that the user 26.1102 + that runs the Mercurial process on the server is also the 26.1103 + one that will run the <filename>processmail</filename> 26.1104 + script. The <filename>processmail</filename> script 26.1105 + sometimes causes Bugzilla to write to files in its 26.1106 + configuration directory, and Bugzilla's configuration files 26.1107 + are usually owned by the user that your web server runs 26.1108 + under. 26.1109 + </para> 26.1110 + 26.1111 + <para>You can cause <filename>processmail</filename> to be run 26.1112 + with the suitable user's identity using the 26.1113 + <command>sudo</command> command. Here is an example entry 26.1114 + for a <filename>sudoers</filename> file. 26.1115 + </para> 26.1116 + <programlisting>hg_user = (httpd_user) 26.1117 +NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting> 26.1118 + <para>This allows the <literal>hg_user</literal> user to run a 26.1119 + <filename>processmail-wrapper</filename> program under the 26.1120 + identity of <literal>httpd_user</literal>. 26.1121 + </para> 26.1122 + 26.1123 + <para>This indirection through a wrapper script is necessary, 26.1124 + because <filename>processmail</filename> expects to be run 26.1125 + with its current directory set to wherever you installed 26.1126 + Bugzilla; you can't specify that kind of constraint in a 26.1127 + <filename>sudoers</filename> file. The contents of the 26.1128 + wrapper script are simple: 26.1129 + </para> 26.1130 + <programlisting>#!/bin/sh 26.1131 +cd `dirname $0` && ./processmail "$1" nobody@example.com</programlisting> 26.1132 + <para>It doesn't seem to matter what email address you pass to 26.1133 + <filename>processmail</filename>. 26.1134 + </para> 26.1135 + 26.1136 + <para>If your <literal role="rc-usermap">usermap</literal> is 26.1137 + not set up correctly, users will see an error message from 26.1138 + the <literal role="hg-ext">bugzilla</literal> hook when they 26.1139 + push changes to the server. The error message will look 26.1140 + like this: 26.1141 + </para> 26.1142 + <programlisting>cannot find bugzilla user id for john.q.public@example.com</programlisting> 26.1143 + <para>What this means is that the committer's address, 26.1144 + <literal>john.q.public@example.com</literal>, is not a valid 26.1145 + Bugzilla user name, nor does it have an entry in your 26.1146 + <literal role="rc-usermap">usermap</literal> that maps it to 26.1147 + a valid Bugzilla user name. 26.1148 + </para> 26.1149 + 26.1150 + </sect3> 26.1151 + </sect2> 26.1152 + <sect2> 26.1153 + <title><literal role="hg-ext">notify</literal>&emdash;send email 26.1154 + notifications</title> 26.1155 + 26.1156 + <para>Although Mercurial's built-in web server provides RSS 26.1157 + feeds of changes in every repository, many people prefer to 26.1158 + receive change notifications via email. The <literal 26.1159 + role="hg-ext">notify</literal> hook lets you send out 26.1160 + notifications to a set of email addresses whenever changesets 26.1161 + arrive that those subscribers are interested in. 26.1162 + </para> 26.1163 + 26.1164 + <para>As with the <literal role="hg-ext">bugzilla</literal> 26.1165 + hook, the <literal role="hg-ext">notify</literal> hook is 26.1166 + template-driven, so you can customise the contents of the 26.1167 + notification messages that it sends. 26.1168 + </para> 26.1169 + 26.1170 + <para>By default, the <literal role="hg-ext">notify</literal> 26.1171 + hook includes a diff of every changeset that it sends out; you 26.1172 + can limit the size of the diff, or turn this feature off 26.1173 + entirely. It is useful for letting subscribers review changes 26.1174 + immediately, rather than clicking to follow a URL. 26.1175 + </para> 26.1176 + 26.1177 + <sect3> 26.1178 + <title>Configuring the <literal role="hg-ext">notify</literal> 26.1179 + hook</title> 26.1180 + 26.1181 + <para>You can set up the <literal 26.1182 + role="hg-ext">notify</literal> hook to send one email 26.1183 + message per incoming changeset, or one per incoming group of 26.1184 + changesets (all those that arrived in a single pull or 26.1185 + push). 26.1186 + </para> 26.1187 + <programlisting>[hooks] 26.1188 +# send one email per group of changes 26.1189 +changegroup.notify = python:hgext.notify.hook 26.1190 +# send one email per change 26.1191 +incoming.notify = python:hgext.notify.hook</programlisting> 26.1192 + 26.1193 + <para>Configuration information for this hook lives in the 26.1194 + <literal role="rc-notify">notify</literal> section of a 26.1195 + <filename role="special">~/.hgrc</filename> file. 26.1196 + </para> 26.1197 + <itemizedlist> 26.1198 + <listitem><para><envar role="rc-item-notify">test</envar>: 26.1199 + By default, this hook does not send out email at all; 26.1200 + instead, it prints the message that it 26.1201 + <emphasis>would</emphasis> send. Set this item to 26.1202 + <literal>false</literal> to allow email to be sent. The 26.1203 + reason that sending of email is turned off by default is 26.1204 + that it takes several tries to configure this extension 26.1205 + exactly as you would like, and it would be bad form to 26.1206 + spam subscribers with a number of <quote>broken</quote> 26.1207 + notifications while you debug your configuration. 26.1208 + </para> 26.1209 + </listitem> 26.1210 + <listitem><para><envar role="rc-item-notify">config</envar>: 26.1211 + The path to a configuration file that contains 26.1212 + subscription information. This is kept separate from 26.1213 + the main <filename role="special">~/.hgrc</filename> so 26.1214 + that you can maintain it in a repository of its own. 26.1215 + People can then clone that repository, update their 26.1216 + subscriptions, and push the changes back to your server. 26.1217 + </para> 26.1218 + </listitem> 26.1219 + <listitem><para><envar role="rc-item-notify">strip</envar>: 26.1220 + The number of leading path separator characters to strip 26.1221 + from a repository's path, when deciding whether a 26.1222 + repository has subscribers. For example, if the 26.1223 + repositories on your server live in <filename 26.1224 + class="directory">/home/hg/repos</filename>, and 26.1225 + <literal role="hg-ext">notify</literal> is considering a 26.1226 + repository named <filename 26.1227 + class="directory">/home/hg/repos/shared/test</filename>, 26.1228 + setting <envar role="rc-item-notify">strip</envar> to 26.1229 + <literal>4</literal> will cause <literal 26.1230 + role="hg-ext">notify</literal> to trim the path it 26.1231 + considers down to <filename 26.1232 + class="directory">shared/test</filename>, and it will 26.1233 + match subscribers against that. 26.1234 + </para> 26.1235 + </listitem> 26.1236 + <listitem><para><envar 26.1237 + role="rc-item-notify">template</envar>: The template 26.1238 + text to use when sending messages. This specifies both 26.1239 + the contents of the message header and its body. 26.1240 + </para> 26.1241 + </listitem> 26.1242 + <listitem><para><envar 26.1243 + role="rc-item-notify">maxdiff</envar>: The maximum 26.1244 + number of lines of diff data to append to the end of a 26.1245 + message. If a diff is longer than this, it is 26.1246 + truncated. By default, this is set to 300. Set this to 26.1247 + <literal>0</literal> to omit diffs from notification 26.1248 + emails. 26.1249 + </para> 26.1250 + </listitem> 26.1251 + <listitem><para><envar 26.1252 + role="rc-item-notify">sources</envar>: A list of 26.1253 + sources of changesets to consider. This lets you limit 26.1254 + <literal role="hg-ext">notify</literal> to only sending 26.1255 + out email about changes that remote users pushed into 26.1256 + this repository via a server, for example. See section 26.1257 + <xref 26.1258 + linkend="sec.hook.sources"/> for the sources you can 26.1259 + specify here. 26.1260 + </para> 26.1261 + </listitem></itemizedlist> 26.1262 + 26.1263 + <para>If you set the <envar role="rc-item-web">baseurl</envar> 26.1264 + item in the <literal role="rc-web">web</literal> section, 26.1265 + you can use it in a template; it will be available as 26.1266 + <literal>webroot</literal>. 26.1267 + </para> 26.1268 + 26.1269 + <para>Here is an example set of <literal 26.1270 + role="hg-ext">notify</literal> configuration information. 26.1271 + </para> 26.1272 + 26.1273 + <programlisting>&ch10-notify-config.lst;</programlisting> 26.1274 + 26.1275 + <para>This will produce a message that looks like the 26.1276 + following: 26.1277 + </para> 26.1278 + 26.1279 + <programlisting>&ch10-notify-config-mail.lst;</programlisting> 26.1280 + 26.1281 + </sect3> 26.1282 + <sect3> 26.1283 + <title>Testing and troubleshooting</title> 26.1284 + 26.1285 + <para>Do not forget that by default, the <literal 26.1286 + role="hg-ext">notify</literal> extension <emphasis>will not 26.1287 + send any mail</emphasis> until you explicitly configure it to do so, 26.1288 + by setting <envar role="rc-item-notify">test</envar> to 26.1289 + <literal>false</literal>. Until you do that, it simply 26.1290 + prints the message it <emphasis>would</emphasis> send. 26.1291 + </para> 26.1292 + 26.1293 + </sect3> 26.1294 + </sect2> 26.1295 + </sect1> 26.1296 + <sect1 id="sec.hook.ref"> 26.1297 + <title>Information for writers of hooks</title> 26.1298 + 26.1299 + <sect2> 26.1300 + <title>In-process hook execution</title> 26.1301 + 26.1302 + <para>An in-process hook is called with arguments of the 26.1303 + following form: 26.1304 + </para> 26.1305 + <programlisting>def myhook(ui, repo, **kwargs): pass</programlisting> 26.1306 + <para>The <literal>ui</literal> parameter is a <literal 26.1307 + role="py-mod-mercurial.ui">ui</literal> object. The 26.1308 + <literal>repo</literal> parameter is a <literal 26.1309 + role="py-mod-mercurial.localrepo">localrepository</literal> 26.1310 + object. The names and values of the 26.1311 + <literal>**kwargs</literal> parameters depend on the hook 26.1312 + being invoked, with the following common features: 26.1313 + </para> 26.1314 + <itemizedlist> 26.1315 + <listitem><para>If a parameter is named 26.1316 + <literal>node</literal> or <literal>parentN</literal>, it 26.1317 + will contain a hexadecimal changeset ID. The empty string 26.1318 + is used to represent <quote>null changeset ID</quote> 26.1319 + instead of a string of zeroes. 26.1320 + </para> 26.1321 + </listitem> 26.1322 + <listitem><para>If a parameter is named 26.1323 + <literal>url</literal>, it will contain the URL of a 26.1324 + remote repository, if that can be determined. 26.1325 + </para> 26.1326 + </listitem> 26.1327 + <listitem><para>Boolean-valued parameters are represented as 26.1328 + Python <literal>bool</literal> objects. 26.1329 + </para> 26.1330 + </listitem></itemizedlist> 26.1331 + 26.1332 + <para>An in-process hook is called without a change to the 26.1333 + process's working directory (unlike external hooks, which are 26.1334 + run in the root of the repository). It must not change the 26.1335 + process's working directory, or it will cause any calls it 26.1336 + makes into the Mercurial API to fail. 26.1337 + </para> 26.1338 + 26.1339 + <para>If a hook returns a boolean <quote>false</quote> value, it 26.1340 + is considered to have succeeded. If it returns a boolean 26.1341 + <quote>true</quote> value or raises an exception, it is 26.1342 + considered to have failed. A useful way to think of the 26.1343 + calling convention is <quote>tell me if you fail</quote>. 26.1344 + </para> 26.1345 + 26.1346 + <para>Note that changeset IDs are passed into Python hooks as 26.1347 + hexadecimal strings, not the binary hashes that Mercurial's 26.1348 + APIs normally use. To convert a hash from hex to binary, use 26.1349 + the <literal>bin</literal> function. 26.1350 + </para> 26.1351 + 26.1352 + </sect2> 26.1353 + <sect2> 26.1354 + <title>External hook execution</title> 26.1355 + 26.1356 + <para>An external hook is passed to the shell of the user 26.1357 + running Mercurial. Features of that shell, such as variable 26.1358 + substitution and command redirection, are available. The hook 26.1359 + is run in the root directory of the repository (unlike 26.1360 + in-process hooks, which are run in the same directory that 26.1361 + Mercurial was run in). 26.1362 + </para> 26.1363 + 26.1364 + <para>Hook parameters are passed to the hook as environment 26.1365 + variables. Each environment variable's name is converted in 26.1366 + upper case and prefixed with the string 26.1367 + <quote><literal>HG_</literal></quote>. For example, if the 26.1368 + name of a parameter is <quote><literal>node</literal></quote>, 26.1369 + the name of the environment variable representing that 26.1370 + parameter will be <quote><literal>HG_NODE</literal></quote>. 26.1371 + </para> 26.1372 + 26.1373 + <para>A boolean parameter is represented as the string 26.1374 + <quote><literal>1</literal></quote> for <quote>true</quote>, 26.1375 + <quote><literal>0</literal></quote> for <quote>false</quote>. 26.1376 + If an environment variable is named <envar>HG_NODE</envar>, 26.1377 + <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it 26.1378 + contains a changeset ID represented as a hexadecimal string. 26.1379 + The empty string is used to represent <quote>null changeset 26.1380 + ID</quote> instead of a string of zeroes. If an environment 26.1381 + variable is named <envar>HG_URL</envar>, it will contain the 26.1382 + URL of a remote repository, if that can be determined. 26.1383 + </para> 26.1384 + 26.1385 + <para>If a hook exits with a status of zero, it is considered to 26.1386 + have succeeded. If it exits with a non-zero status, it is 26.1387 + considered to have failed. 26.1388 + </para> 26.1389 + 26.1390 + </sect2> 26.1391 + <sect2> 26.1392 + <title>Finding out where changesets come from</title> 26.1393 + 26.1394 + <para>A hook that involves the transfer of changesets between a 26.1395 + local repository and another may be able to find out 26.1396 + information about the <quote>far side</quote>. Mercurial 26.1397 + knows <emphasis>how</emphasis> changes are being transferred, 26.1398 + and in many cases <emphasis>where</emphasis> they are being 26.1399 + transferred to or from. 26.1400 + </para> 26.1401 + 26.1402 + <sect3 id="sec.hook.sources"> 26.1403 + <title>Sources of changesets</title> 26.1404 + 26.1405 + <para>Mercurial will tell a hook what means are, or were, used 26.1406 + to transfer changesets between repositories. This is 26.1407 + provided by Mercurial in a Python parameter named 26.1408 + <literal>source</literal>, or an environment variable named 26.1409 + <envar>HG_SOURCE</envar>. 26.1410 + </para> 26.1411 + 26.1412 + <itemizedlist> 26.1413 + <listitem><para><literal>serve</literal>: Changesets are 26.1414 + transferred to or from a remote repository over http or 26.1415 + ssh. 26.1416 + </para> 26.1417 + </listitem> 26.1418 + <listitem><para><literal>pull</literal>: Changesets are 26.1419 + being transferred via a pull from one repository into 26.1420 + another. 26.1421 + </para> 26.1422 + </listitem> 26.1423 + <listitem><para><literal>push</literal>: Changesets are 26.1424 + being transferred via a push from one repository into 26.1425 + another. 26.1426 + </para> 26.1427 + </listitem> 26.1428 + <listitem><para><literal>bundle</literal>: Changesets are 26.1429 + being transferred to or from a bundle. 26.1430 + </para> 26.1431 + </listitem></itemizedlist> 26.1432 + 26.1433 + </sect3> 26.1434 + <sect3 id="sec.hook.url"> 26.1435 + <title>Where changes are going&emdash;remote repository 26.1436 + URLs</title> 26.1437 + 26.1438 + <para>When possible, Mercurial will tell a hook the location 26.1439 + of the <quote>far side</quote> of an activity that transfers 26.1440 + changeset data between repositories. This is provided by 26.1441 + Mercurial in a Python parameter named 26.1442 + <literal>url</literal>, or an environment variable named 26.1443 + <envar>HG_URL</envar>. 26.1444 + </para> 26.1445 + 26.1446 + <para>This information is not always known. If a hook is 26.1447 + invoked in a repository that is being served via http or 26.1448 + ssh, Mercurial cannot tell where the remote repository is, 26.1449 + but it may know where the client is connecting from. In 26.1450 + such cases, the URL will take one of the following forms: 26.1451 + </para> 26.1452 + <itemizedlist> 26.1453 + <listitem><para><literal>remote:ssh:1.2.3.4</literal>&emdash;remote 26.1454 + ssh client, at the IP address 26.1455 + <literal>1.2.3.4</literal>. 26.1456 + </para> 26.1457 + </listitem> 26.1458 + <listitem><para><literal>remote:http:1.2.3.4</literal>&emdash;remote 26.1459 + http client, at the IP address 26.1460 + <literal>1.2.3.4</literal>. If the client is using SSL, 26.1461 + this will be of the form 26.1462 + <literal>remote:https:1.2.3.4</literal>. 26.1463 + </para> 26.1464 + </listitem> 26.1465 + <listitem><para>Empty&emdash;no information could be 26.1466 + discovered about the remote client. 26.1467 + </para> 26.1468 + </listitem></itemizedlist> 26.1469 + 26.1470 + </sect3> 26.1471 + </sect2> 26.1472 + </sect1> 26.1473 + <sect1> 26.1474 + <title>Hook reference</title> 26.1475 + 26.1476 + <sect2 id="sec.hook.changegroup"> 26.1477 + <title><literal role="hook">changegroup</literal>&emdash;after 26.1478 + remote changesets added</title> 26.1479 + 26.1480 + <para>This hook is run after a group of pre-existing changesets 26.1481 + has been added to the repository, for example via a <command 26.1482 + role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg 26.1483 + unbundle</command>. This hook is run once per operation 26.1484 + that added one or more changesets. This is in contrast to the 26.1485 + <literal role="hook">incoming</literal> hook, which is run 26.1486 + once per changeset, regardless of whether the changesets 26.1487 + arrive in a group. 26.1488 + </para> 26.1489 + 26.1490 + <para>Some possible uses for this hook include kicking off an 26.1491 + automated build or test of the added changesets, updating a 26.1492 + bug database, or notifying subscribers that a repository 26.1493 + contains new changes. 26.1494 + </para> 26.1495 + 26.1496 + <para>Parameters to this hook: 26.1497 + </para> 26.1498 + <itemizedlist> 26.1499 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1500 + changeset ID of the first changeset in the group that was 26.1501 + added. All changesets between this and 26.1502 + <literal role="tag">tip</literal>, inclusive, were added by a single 26.1503 + <command role="hg-cmd">hg pull</command>, <command 26.1504 + role="hg-cmd">hg push</command> or <command 26.1505 + role="hg-cmd">hg unbundle</command>. 26.1506 + </para> 26.1507 + </listitem> 26.1508 + <listitem><para><literal>source</literal>: A string. The 26.1509 + source of these changes. See section <xref 26.1510 + linkend="sec.hook.sources"/> for details. 26.1511 + </para> 26.1512 + </listitem> 26.1513 + <listitem><para><literal>url</literal>: A URL. The location 26.1514 + of the remote repository, if known. See section <xref 26.1515 + linkend="sec.hook.url"/> for more 26.1516 + information. 26.1517 + </para> 26.1518 + </listitem></itemizedlist> 26.1519 + 26.1520 + <para>See also: <literal role="hook">incoming</literal> (section 26.1521 + <xref linkend="sec.hook.incoming"/>), <literal 26.1522 + role="hook">prechangegroup</literal> (section <xref 26.1523 + linkend="sec.hook.prechangegroup"/>), <literal 26.1524 + role="hook">pretxnchangegroup</literal> (section <xref 26.1525 + linkend="sec.hook.pretxnchangegroup"/>) 26.1526 + </para> 26.1527 + 26.1528 + </sect2> 26.1529 + <sect2 id="sec.hook.commit"> 26.1530 + <title><literal role="hook">commit</literal>&emdash;after a new 26.1531 + changeset is created</title> 26.1532 + 26.1533 + <para>This hook is run after a new changeset has been created. 26.1534 + </para> 26.1535 + 26.1536 + <para>Parameters to this hook: 26.1537 + </para> 26.1538 + <itemizedlist> 26.1539 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1540 + changeset ID of the newly committed changeset. 26.1541 + </para> 26.1542 + </listitem> 26.1543 + <listitem><para><literal>parent1</literal>: A changeset ID. 26.1544 + The changeset ID of the first parent of the newly 26.1545 + committed changeset. 26.1546 + </para> 26.1547 + </listitem> 26.1548 + <listitem><para><literal>parent2</literal>: A changeset ID. 26.1549 + The changeset ID of the second parent of the newly 26.1550 + committed changeset. 26.1551 + </para> 26.1552 + </listitem></itemizedlist> 26.1553 + 26.1554 + <para>See also: <literal role="hook">precommit</literal> 26.1555 + (section <xref linkend="sec.hook.precommit"/>), <literal 26.1556 + role="hook">pretxncommit</literal> (section <xref 26.1557 + linkend="sec.hook.pretxncommit"/>) 26.1558 + </para> 26.1559 + 26.1560 + </sect2> 26.1561 + <sect2 id="sec.hook.incoming"> 26.1562 + <title><literal role="hook">incoming</literal>&emdash;after one 26.1563 + remote changeset is added</title> 26.1564 + 26.1565 + <para>This hook is run after a pre-existing changeset has been 26.1566 + added to the repository, for example via a <command 26.1567 + role="hg-cmd">hg push</command>. If a group of changesets 26.1568 + was added in a single operation, this hook is called once for 26.1569 + each added changeset. 26.1570 + </para> 26.1571 + 26.1572 + <para>You can use this hook for the same purposes as the 26.1573 + <literal role="hook">changegroup</literal> hook (section <xref 26.1574 + linkend="sec.hook.changegroup"/>); it's simply 26.1575 + more convenient sometimes to run a hook once per group of 26.1576 + changesets, while other times it's handier once per changeset. 26.1577 + </para> 26.1578 + 26.1579 + <para>Parameters to this hook: 26.1580 + </para> 26.1581 + <itemizedlist> 26.1582 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1583 + ID of the newly added changeset. 26.1584 + </para> 26.1585 + </listitem> 26.1586 + <listitem><para><literal>source</literal>: A string. The 26.1587 + source of these changes. See section <xref 26.1588 + linkend="sec.hook.sources"/> for details. 26.1589 + </para> 26.1590 + </listitem> 26.1591 + <listitem><para><literal>url</literal>: A URL. The location 26.1592 + of the remote repository, if known. See section <xref 26.1593 + linkend="sec.hook.url"/> for more 26.1594 + information. 26.1595 + </para> 26.1596 + </listitem></itemizedlist> 26.1597 + 26.1598 + <para>See also: <literal role="hook">changegroup</literal> 26.1599 + (section <xref linkend="sec.hook.changegroup"/>) <literal 26.1600 + role="hook">prechangegroup</literal> (section <xref 26.1601 + linkend="sec.hook.prechangegroup"/>), <literal 26.1602 + role="hook">pretxnchangegroup</literal> (section <xref 26.1603 + linkend="sec.hook.pretxnchangegroup"/>) 26.1604 + </para> 26.1605 + 26.1606 + </sect2> 26.1607 + <sect2 id="sec.hook.outgoing"> 26.1608 + <title><literal role="hook">outgoing</literal>&emdash;after 26.1609 + changesets are propagated</title> 26.1610 + 26.1611 + <para>This hook is run after a group of changesets has been 26.1612 + propagated out of this repository, for example by a <command 26.1613 + role="hg-cmd">hg push</command> or <command role="hg-cmd">hg 26.1614 + bundle</command> command. 26.1615 + </para> 26.1616 + 26.1617 + <para>One possible use for this hook is to notify administrators 26.1618 + that changes have been pulled. 26.1619 + </para> 26.1620 + 26.1621 + <para>Parameters to this hook: 26.1622 + </para> 26.1623 + <itemizedlist> 26.1624 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1625 + changeset ID of the first changeset of the group that was 26.1626 + sent. 26.1627 + </para> 26.1628 + </listitem> 26.1629 + <listitem><para><literal>source</literal>: A string. The 26.1630 + source of the of the operation (see section <xref 26.1631 + linkend="sec.hook.sources"/>). If a remote 26.1632 + client pulled changes from this repository, 26.1633 + <literal>source</literal> will be 26.1634 + <literal>serve</literal>. If the client that obtained 26.1635 + changes from this repository was local, 26.1636 + <literal>source</literal> will be 26.1637 + <literal>bundle</literal>, <literal>pull</literal>, or 26.1638 + <literal>push</literal>, depending on the operation the 26.1639 + client performed. 26.1640 + </para> 26.1641 + </listitem> 26.1642 + <listitem><para><literal>url</literal>: A URL. The location 26.1643 + of the remote repository, if known. See section <xref 26.1644 + linkend="sec.hook.url"/> for more 26.1645 + information. 26.1646 + </para> 26.1647 + </listitem></itemizedlist> 26.1648 + 26.1649 + <para>See also: <literal role="hook">preoutgoing</literal> 26.1650 + (section <xref linkend="sec.hook.preoutgoing"/>) 26.1651 + </para> 26.1652 + 26.1653 + </sect2> 26.1654 + <sect2 id="sec.hook.prechangegroup"> 26.1655 + <title><literal 26.1656 + role="hook">prechangegroup</literal>&emdash;before starting 26.1657 + to add remote changesets</title> 26.1658 + 26.1659 + <para>This controlling hook is run before Mercurial begins to 26.1660 + add a group of changesets from another repository. 26.1661 + </para> 26.1662 + 26.1663 + <para>This hook does not have any information about the 26.1664 + changesets to be added, because it is run before transmission 26.1665 + of those changesets is allowed to begin. If this hook fails, 26.1666 + the changesets will not be transmitted. 26.1667 + </para> 26.1668 + 26.1669 + <para>One use for this hook is to prevent external changes from 26.1670 + being added to a repository. For example, you could use this 26.1671 + to <quote>freeze</quote> a server-hosted branch temporarily or 26.1672 + permanently so that users cannot push to it, while still 26.1673 + allowing a local administrator to modify the repository. 26.1674 + </para> 26.1675 + 26.1676 + <para>Parameters to this hook: 26.1677 + </para> 26.1678 + <itemizedlist> 26.1679 + <listitem><para><literal>source</literal>: A string. The 26.1680 + source of these changes. See section <xref 26.1681 + linkend="sec.hook.sources"/> for details. 26.1682 + </para> 26.1683 + </listitem> 26.1684 + <listitem><para><literal>url</literal>: A URL. The location 26.1685 + of the remote repository, if known. See section <xref 26.1686 + linkend="sec.hook.url"/> for more 26.1687 + information. 26.1688 + </para> 26.1689 + </listitem></itemizedlist> 26.1690 + 26.1691 + <para>See also: <literal role="hook">changegroup</literal> 26.1692 + (section <xref linkend="sec.hook.changegroup"/>), <literal 26.1693 + role="hook">incoming</literal> (section <xref 26.1694 + linkend="sec.hook.incoming"/>), , <literal 26.1695 + role="hook">pretxnchangegroup</literal> (section <xref 26.1696 + linkend="sec.hook.pretxnchangegroup"/>) 26.1697 + </para> 26.1698 + 26.1699 + </sect2> 26.1700 + <sect2 id="sec.hook.precommit"> 26.1701 + <title><literal role="hook">precommit</literal>&emdash;before 26.1702 + starting to commit a changeset</title> 26.1703 + 26.1704 + <para>This hook is run before Mercurial begins to commit a new 26.1705 + changeset. It is run before Mercurial has any of the metadata 26.1706 + for the commit, such as the files to be committed, the commit 26.1707 + message, or the commit date. 26.1708 + </para> 26.1709 + 26.1710 + <para>One use for this hook is to disable the ability to commit 26.1711 + new changesets, while still allowing incoming changesets. 26.1712 + Another is to run a build or test, and only allow the commit 26.1713 + to begin if the build or test succeeds. 26.1714 + </para> 26.1715 + 26.1716 + <para>Parameters to this hook: 26.1717 + </para> 26.1718 + <itemizedlist> 26.1719 + <listitem><para><literal>parent1</literal>: A changeset ID. 26.1720 + The changeset ID of the first parent of the working 26.1721 + directory. 26.1722 + </para> 26.1723 + </listitem> 26.1724 + <listitem><para><literal>parent2</literal>: A changeset ID. 26.1725 + The changeset ID of the second parent of the working 26.1726 + directory. 26.1727 + </para> 26.1728 + </listitem></itemizedlist> 26.1729 + <para>If the commit proceeds, the parents of the working 26.1730 + directory will become the parents of the new changeset. 26.1731 + </para> 26.1732 + 26.1733 + <para>See also: <literal role="hook">commit</literal> (section 26.1734 + <xref linkend="sec.hook.commit"/>), <literal 26.1735 + role="hook">pretxncommit</literal> (section <xref 26.1736 + linkend="sec.hook.pretxncommit"/>) 26.1737 + </para> 26.1738 + 26.1739 + </sect2> 26.1740 + <sect2 id="sec.hook.preoutgoing"> 26.1741 + <title><literal role="hook">preoutgoing</literal>&emdash;before 26.1742 + starting to propagate changesets</title> 26.1743 + 26.1744 + <para>This hook is invoked before Mercurial knows the identities 26.1745 + of the changesets to be transmitted. 26.1746 + </para> 26.1747 + 26.1748 + <para>One use for this hook is to prevent changes from being 26.1749 + transmitted to another repository. 26.1750 + </para> 26.1751 + 26.1752 + <para>Parameters to this hook: 26.1753 + </para> 26.1754 + <itemizedlist> 26.1755 + <listitem><para><literal>source</literal>: A string. The 26.1756 + source of the operation that is attempting to obtain 26.1757 + changes from this repository (see section <xref 26.1758 + linkend="sec.hook.sources"/>). See the documentation 26.1759 + for the <literal>source</literal> parameter to the 26.1760 + <literal role="hook">outgoing</literal> hook, in section 26.1761 + <xref linkend="sec.hook.outgoing"/>, for possible values 26.1762 + of 26.1763 + this parameter. 26.1764 + </para> 26.1765 + </listitem> 26.1766 + <listitem><para><literal>url</literal>: A URL. The location 26.1767 + of the remote repository, if known. See section <xref 26.1768 + linkend="sec.hook.url"/> for more 26.1769 + information. 26.1770 + </para> 26.1771 + </listitem></itemizedlist> 26.1772 + 26.1773 + <para>See also: <literal role="hook">outgoing</literal> (section 26.1774 + <xref linkend="sec.hook.outgoing"/>) 26.1775 + </para> 26.1776 + 26.1777 + </sect2> 26.1778 + <sect2 id="sec.hook.pretag"> 26.1779 + <title><literal role="hook">pretag</literal>&emdash;before 26.1780 + tagging a changeset</title> 26.1781 + 26.1782 + <para>This controlling hook is run before a tag is created. If 26.1783 + the hook succeeds, creation of the tag proceeds. If the hook 26.1784 + fails, the tag is not created. 26.1785 + </para> 26.1786 + 26.1787 + <para>Parameters to this hook: 26.1788 + </para> 26.1789 + <itemizedlist> 26.1790 + <listitem><para><literal>local</literal>: A boolean. Whether 26.1791 + the tag is local to this repository instance (i.e. stored 26.1792 + in <filename role="special">.hg/localtags</filename>) or 26.1793 + managed by Mercurial (stored in <filename 26.1794 + role="special">.hgtags</filename>). 26.1795 + </para> 26.1796 + </listitem> 26.1797 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1798 + ID of the changeset to be tagged. 26.1799 + </para> 26.1800 + </listitem> 26.1801 + <listitem><para><literal>tag</literal>: A string. The name of 26.1802 + the tag to be created. 26.1803 + </para> 26.1804 + </listitem></itemizedlist> 26.1805 + 26.1806 + <para>If the tag to be created is revision-controlled, the 26.1807 + <literal role="hook">precommit</literal> and <literal 26.1808 + role="hook">pretxncommit</literal> hooks (sections <xref 26.1809 + linkend="sec.hook.commit"/> and <xref 26.1810 + linkend="sec.hook.pretxncommit"/>) will also be run. 26.1811 + </para> 26.1812 + 26.1813 + <para>See also: <literal role="hook">tag</literal> (section 26.1814 + <xref linkend="sec.hook.tag"/>) 26.1815 + </para> 26.1816 + </sect2> 26.1817 + <sect2 id="sec.hook.pretxnchangegroup"> 26.1818 + <title><literal 26.1819 + role="hook">pretxnchangegroup</literal>&emdash;before 26.1820 + completing addition of remote changesets</title> 26.1821 + 26.1822 + <para>This controlling hook is run before a 26.1823 + transaction&emdash;that manages the addition of a group of new 26.1824 + changesets from outside the repository&emdash;completes. If 26.1825 + the hook succeeds, the transaction completes, and all of the 26.1826 + changesets become permanent within this repository. If the 26.1827 + hook fails, the transaction is rolled back, and the data for 26.1828 + the changesets is erased. 26.1829 + </para> 26.1830 + 26.1831 + <para>This hook can access the metadata associated with the 26.1832 + almost-added changesets, but it should not do anything 26.1833 + permanent with this data. It must also not modify the working 26.1834 + directory. 26.1835 + </para> 26.1836 + 26.1837 + <para>While this hook is running, if other Mercurial processes 26.1838 + access this repository, they will be able to see the 26.1839 + almost-added changesets as if they are permanent. This may 26.1840 + lead to race conditions if you do not take steps to avoid 26.1841 + them. 26.1842 + </para> 26.1843 + 26.1844 + <para>This hook can be used to automatically vet a group of 26.1845 + changesets. If the hook fails, all of the changesets are 26.1846 + <quote>rejected</quote> when the transaction rolls back. 26.1847 + </para> 26.1848 + 26.1849 + <para>Parameters to this hook: 26.1850 + </para> 26.1851 + <itemizedlist> 26.1852 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1853 + changeset ID of the first changeset in the group that was 26.1854 + added. All changesets between this and 26.1855 + <literal role="tag">tip</literal>, 26.1856 + inclusive, were added by a single <command 26.1857 + role="hg-cmd">hg pull</command>, <command 26.1858 + role="hg-cmd">hg push</command> or <command 26.1859 + role="hg-cmd">hg unbundle</command>. 26.1860 + </para> 26.1861 + </listitem> 26.1862 + <listitem><para><literal>source</literal>: A string. The 26.1863 + source of these changes. See section <xref 26.1864 + linkend="sec.hook.sources"/> for details. 26.1865 + </para> 26.1866 + </listitem> 26.1867 + <listitem><para><literal>url</literal>: A URL. The location 26.1868 + of the remote repository, if known. See section <xref 26.1869 + linkend="sec.hook.url"/> for more 26.1870 + information. 26.1871 + </para> 26.1872 + </listitem></itemizedlist> 26.1873 + 26.1874 + <para>See also: <literal role="hook">changegroup</literal> 26.1875 + (section <xref linkend="sec.hook.changegroup"/>), <literal 26.1876 + role="hook">incoming</literal> (section <xref 26.1877 + linkend="sec.hook.incoming"/>), <literal 26.1878 + role="hook">prechangegroup</literal> (section <xref 26.1879 + linkend="sec.hook.prechangegroup"/>) 26.1880 + </para> 26.1881 + 26.1882 + </sect2> 26.1883 + <sect2 id="sec.hook.pretxncommit"> 26.1884 + <title><literal role="hook">pretxncommit</literal>&emdash;before 26.1885 + completing commit of new changeset</title> 26.1886 + 26.1887 + <para>This controlling hook is run before a 26.1888 + transaction&emdash;that manages a new commit&emdash;completes. 26.1889 + If the hook succeeds, the transaction completes and the 26.1890 + changeset becomes permanent within this repository. If the 26.1891 + hook fails, the transaction is rolled back, and the commit 26.1892 + data is erased. 26.1893 + </para> 26.1894 + 26.1895 + <para>This hook can access the metadata associated with the 26.1896 + almost-new changeset, but it should not do anything permanent 26.1897 + with this data. It must also not modify the working 26.1898 + directory. 26.1899 + </para> 26.1900 + 26.1901 + <para>While this hook is running, if other Mercurial processes 26.1902 + access this repository, they will be able to see the 26.1903 + almost-new changeset as if it is permanent. This may lead to 26.1904 + race conditions if you do not take steps to avoid them. 26.1905 + </para> 26.1906 + 26.1907 + <para>Parameters to this hook: 26.1908 + </para> 26.1909 + <itemizedlist> 26.1910 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1911 + changeset ID of the newly committed changeset. 26.1912 + </para> 26.1913 + </listitem> 26.1914 + <listitem><para><literal>parent1</literal>: A changeset ID. 26.1915 + The changeset ID of the first parent of the newly 26.1916 + committed changeset. 26.1917 + </para> 26.1918 + </listitem> 26.1919 + <listitem><para><literal>parent2</literal>: A changeset ID. 26.1920 + The changeset ID of the second parent of the newly 26.1921 + committed changeset. 26.1922 + </para> 26.1923 + </listitem></itemizedlist> 26.1924 + 26.1925 + <para>See also: <literal role="hook">precommit</literal> 26.1926 + (section <xref linkend="sec.hook.precommit"/>) 26.1927 + </para> 26.1928 + 26.1929 + </sect2> 26.1930 + <sect2 id="sec.hook.preupdate"> 26.1931 + <title><literal role="hook">preupdate</literal>&emdash;before 26.1932 + updating or merging working directory</title> 26.1933 + 26.1934 + <para>This controlling hook is run before an update or merge of 26.1935 + the working directory begins. It is run only if Mercurial's 26.1936 + normal pre-update checks determine that the update or merge 26.1937 + can proceed. If the hook succeeds, the update or merge may 26.1938 + proceed; if it fails, the update or merge does not start. 26.1939 + </para> 26.1940 + 26.1941 + <para>Parameters to this hook: 26.1942 + </para> 26.1943 + <itemizedlist> 26.1944 + <listitem><para><literal>parent1</literal>: A changeset ID. 26.1945 + The ID of the parent that the working directory is to be 26.1946 + updated to. If the working directory is being merged, it 26.1947 + will not change this parent. 26.1948 + </para> 26.1949 + </listitem> 26.1950 + <listitem><para><literal>parent2</literal>: A changeset ID. 26.1951 + Only set if the working directory is being merged. The ID 26.1952 + of the revision that the working directory is being merged 26.1953 + with. 26.1954 + </para> 26.1955 + </listitem></itemizedlist> 26.1956 + 26.1957 + <para>See also: <literal role="hook">update</literal> (section 26.1958 + <xref linkend="sec.hook.update"/>) 26.1959 + </para> 26.1960 + 26.1961 + </sect2> 26.1962 + <sect2 id="sec.hook.tag"> 26.1963 + <title><literal role="hook">tag</literal>&emdash;after tagging a 26.1964 + changeset</title> 26.1965 + 26.1966 + <para>This hook is run after a tag has been created. 26.1967 + </para> 26.1968 + 26.1969 + <para>Parameters to this hook: 26.1970 + </para> 26.1971 + <itemizedlist> 26.1972 + <listitem><para><literal>local</literal>: A boolean. Whether 26.1973 + the new tag is local to this repository instance (i.e. 26.1974 + stored in <filename 26.1975 + role="special">.hg/localtags</filename>) or managed by 26.1976 + Mercurial (stored in <filename 26.1977 + role="special">.hgtags</filename>). 26.1978 + </para> 26.1979 + </listitem> 26.1980 + <listitem><para><literal>node</literal>: A changeset ID. The 26.1981 + ID of the changeset that was tagged. 26.1982 + </para> 26.1983 + </listitem> 26.1984 + <listitem><para><literal>tag</literal>: A string. The name of 26.1985 + the tag that was created. 26.1986 + </para> 26.1987 + </listitem></itemizedlist> 26.1988 + 26.1989 + <para>If the created tag is revision-controlled, the <literal 26.1990 + role="hook">commit</literal> hook (section <xref 26.1991 + linkend="sec.hook.commit"/>) is run before this hook. 26.1992 + </para> 26.1993 + 26.1994 + <para>See also: <literal role="hook">pretag</literal> (section 26.1995 + <xref linkend="sec.hook.pretag"/>) 26.1996 + </para> 26.1997 + 26.1998 + </sect2> 26.1999 + <sect2 id="sec.hook.update"> 26.2000 + <title><literal role="hook">update</literal>&emdash;after 26.2001 + updating or merging working directory</title> 26.2002 + 26.2003 + <para>This hook is run after an update or merge of the working 26.2004 + directory completes. Since a merge can fail (if the external 26.2005 + <command>hgmerge</command> command fails to resolve conflicts 26.2006 + in a file), this hook communicates whether the update or merge 26.2007 + completed cleanly. 26.2008 + </para> 26.2009 + 26.2010 + <itemizedlist> 26.2011 + <listitem><para><literal>error</literal>: A boolean. 26.2012 + Indicates whether the update or merge completed 26.2013 + successfully. 26.2014 + </para> 26.2015 + </listitem> 26.2016 + <listitem><para><literal>parent1</literal>: A changeset ID. 26.2017 + The ID of the parent that the working directory was 26.2018 + updated to. If the working directory was merged, it will 26.2019 + not have changed this parent. 26.2020 + </para> 26.2021 + </listitem> 26.2022 + <listitem><para><literal>parent2</literal>: A changeset ID. 26.2023 + Only set if the working directory was merged. The ID of 26.2024 + the revision that the working directory was merged with. 26.2025 + </para> 26.2026 + </listitem></itemizedlist> 26.2027 + 26.2028 + <para>See also: <literal role="hook">preupdate</literal> 26.2029 + (section <xref linkend="sec.hook.preupdate"/>) 26.2030 + </para> 26.2031 + 26.2032 + </sect2> 26.2033 + </sect1> 26.2034 +</chapter> 26.2035 + 26.2036 +<!-- 26.2037 +local variables: 26.2038 +sgml-parent-document: ("00book.xml" "book" "chapter") 26.2039 +end: 26.2040 +-->
27.1 --- a/en/ch09-undo.xml Fri Mar 20 15:40:06 2009 +0800 27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 27.3 @@ -1,1083 +0,0 @@ 27.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 27.5 - 27.6 -<chapter id="chap.undo"> 27.7 - <?dbhtml filename="finding-and-fixing-mistakes.html"?> 27.8 - <title>Finding and fixing mistakes</title> 27.9 - 27.10 - <para>To err might be human, but to really handle the consequences 27.11 - well takes a top-notch revision control system. In this chapter, 27.12 - we'll discuss some of the techniques you can use when you find 27.13 - that a problem has crept into your project. Mercurial has some 27.14 - highly capable features that will help you to isolate the sources 27.15 - of problems, and to handle them appropriately.</para> 27.16 - 27.17 - <sect1> 27.18 - <title>Erasing local history</title> 27.19 - 27.20 - <sect2> 27.21 - <title>The accidental commit</title> 27.22 - 27.23 - <para>I have the occasional but persistent problem of typing 27.24 - rather more quickly than I can think, which sometimes results 27.25 - in me committing a changeset that is either incomplete or 27.26 - plain wrong. In my case, the usual kind of incomplete 27.27 - changeset is one in which I've created a new source file, but 27.28 - forgotten to <command role="hg-cmd">hg add</command> it. A 27.29 - <quote>plain wrong</quote> changeset is not as common, but no 27.30 - less annoying.</para> 27.31 - 27.32 - </sect2> 27.33 - <sect2 id="sec.undo.rollback"> 27.34 - <title>Rolling back a transaction</title> 27.35 - 27.36 - <para>In section <xref linkend="sec.concepts.txn"/>, I mentioned 27.37 - that Mercurial treats each modification of a repository as a 27.38 - <emphasis>transaction</emphasis>. Every time you commit a 27.39 - changeset or pull changes from another repository, Mercurial 27.40 - remembers what you did. You can undo, or <emphasis>roll 27.41 - back</emphasis>, exactly one of these actions using the 27.42 - <command role="hg-cmd">hg rollback</command> command. (See 27.43 - section <xref linkend="sec.undo.rollback-after-push"/> for an 27.44 - important caveat about the use of this command.)</para> 27.45 - 27.46 - <para>Here's a mistake that I often find myself making: 27.47 - committing a change in which I've created a new file, but 27.48 - forgotten to <command role="hg-cmd">hg add</command> 27.49 - it.</para> 27.50 - 27.51 - &interaction.rollback.commit; 27.52 - 27.53 - <para>Looking at the output of <command role="hg-cmd">hg 27.54 - status</command> after the commit immediately confirms the 27.55 - error.</para> 27.56 - 27.57 - &interaction.rollback.status; 27.58 - 27.59 - <para>The commit captured the changes to the file 27.60 - <filename>a</filename>, but not the new file 27.61 - <filename>b</filename>. If I were to push this changeset to a 27.62 - repository that I shared with a colleague, the chances are 27.63 - high that something in <filename>a</filename> would refer to 27.64 - <filename>b</filename>, which would not be present in their 27.65 - repository when they pulled my changes. I would thus become 27.66 - the object of some indignation.</para> 27.67 - 27.68 - <para>However, luck is with me&emdash;I've caught my error 27.69 - before I pushed the changeset. I use the <command 27.70 - role="hg-cmd">hg rollback</command> command, and Mercurial 27.71 - makes that last changeset vanish.</para> 27.72 - 27.73 - &interaction.rollback.rollback; 27.74 - 27.75 - <para>Notice that the changeset is no longer present in the 27.76 - repository's history, and the working directory once again 27.77 - thinks that the file <filename>a</filename> is modified. The 27.78 - commit and rollback have left the working directory exactly as 27.79 - it was prior to the commit; the changeset has been completely 27.80 - erased. I can now safely <command role="hg-cmd">hg 27.81 - add</command> the file <filename>b</filename>, and rerun my 27.82 - commit.</para> 27.83 - 27.84 - &interaction.rollback.add; 27.85 - 27.86 - </sect2> 27.87 - <sect2> 27.88 - <title>The erroneous pull</title> 27.89 - 27.90 - <para>It's common practice with Mercurial to maintain separate 27.91 - development branches of a project in different repositories. 27.92 - Your development team might have one shared repository for 27.93 - your project's <quote>0.9</quote> release, and another, 27.94 - containing different changes, for the <quote>1.0</quote> 27.95 - release.</para> 27.96 - 27.97 - <para>Given this, you can imagine that the consequences could be 27.98 - messy if you had a local <quote>0.9</quote> repository, and 27.99 - accidentally pulled changes from the shared <quote>1.0</quote> 27.100 - repository into it. At worst, you could be paying 27.101 - insufficient attention, and push those changes into the shared 27.102 - <quote>0.9</quote> tree, confusing your entire team (but don't 27.103 - worry, we'll return to this horror scenario later). However, 27.104 - it's more likely that you'll notice immediately, because 27.105 - Mercurial will display the URL it's pulling from, or you will 27.106 - see it pull a suspiciously large number of changes into the 27.107 - repository.</para> 27.108 - 27.109 - <para>The <command role="hg-cmd">hg rollback</command> command 27.110 - will work nicely to expunge all of the changesets that you 27.111 - just pulled. Mercurial groups all changes from one <command 27.112 - role="hg-cmd">hg pull</command> into a single transaction, 27.113 - so one <command role="hg-cmd">hg rollback</command> is all you 27.114 - need to undo this mistake.</para> 27.115 - 27.116 - </sect2> 27.117 - <sect2 id="sec.undo.rollback-after-push"> 27.118 - <title>Rolling back is useless once you've pushed</title> 27.119 - 27.120 - <para>The value of the <command role="hg-cmd">hg 27.121 - rollback</command> command drops to zero once you've pushed 27.122 - your changes to another repository. Rolling back a change 27.123 - makes it disappear entirely, but <emphasis>only</emphasis> in 27.124 - the repository in which you perform the <command 27.125 - role="hg-cmd">hg rollback</command>. Because a rollback 27.126 - eliminates history, there's no way for the disappearance of a 27.127 - change to propagate between repositories.</para> 27.128 - 27.129 - <para>If you've pushed a change to another 27.130 - repository&emdash;particularly if it's a shared 27.131 - repository&emdash;it has essentially <quote>escaped into the 27.132 - wild,</quote> and you'll have to recover from your mistake 27.133 - in a different way. What will happen if you push a changeset 27.134 - somewhere, then roll it back, then pull from the repository 27.135 - you pushed to, is that the changeset will reappear in your 27.136 - repository.</para> 27.137 - 27.138 - <para>(If you absolutely know for sure that the change you want 27.139 - to roll back is the most recent change in the repository that 27.140 - you pushed to, <emphasis>and</emphasis> you know that nobody 27.141 - else could have pulled it from that repository, you can roll 27.142 - back the changeset there, too, but you really should really 27.143 - not rely on this working reliably. If you do this, sooner or 27.144 - later a change really will make it into a repository that you 27.145 - don't directly control (or have forgotten about), and come 27.146 - back to bite you.)</para> 27.147 - 27.148 - </sect2> 27.149 - <sect2> 27.150 - <title>You can only roll back once</title> 27.151 - 27.152 - <para>Mercurial stores exactly one transaction in its 27.153 - transaction log; that transaction is the most recent one that 27.154 - occurred in the repository. This means that you can only roll 27.155 - back one transaction. If you expect to be able to roll back 27.156 - one transaction, then its predecessor, this is not the 27.157 - behaviour you will get.</para> 27.158 - 27.159 - &interaction.rollback.twice; 27.160 - 27.161 - <para>Once you've rolled back one transaction in a repository, 27.162 - you can't roll back again in that repository until you perform 27.163 - another commit or pull.</para> 27.164 - 27.165 - </sect2> 27.166 - </sect1> 27.167 - <sect1> 27.168 - <title>Reverting the mistaken change</title> 27.169 - 27.170 - <para>If you make a modification to a file, and decide that you 27.171 - really didn't want to change the file at all, and you haven't 27.172 - yet committed your changes, the <command role="hg-cmd">hg 27.173 - revert</command> command is the one you'll need. It looks at 27.174 - the changeset that's the parent of the working directory, and 27.175 - restores the contents of the file to their state as of that 27.176 - changeset. (That's a long-winded way of saying that, in the 27.177 - normal case, it undoes your modifications.)</para> 27.178 - 27.179 - <para>Let's illustrate how the <command role="hg-cmd">hg 27.180 - revert</command> command works with yet another small example. 27.181 - We'll begin by modifying a file that Mercurial is already 27.182 - tracking.</para> 27.183 - 27.184 - &interaction.daily.revert.modify; 27.185 - 27.186 - <para>If we don't 27.187 - want that change, we can simply <command role="hg-cmd">hg 27.188 - revert</command> the file.</para> 27.189 - 27.190 - &interaction.daily.revert.unmodify; 27.191 - 27.192 - <para>The <command role="hg-cmd">hg revert</command> command 27.193 - provides us with an extra degree of safety by saving our 27.194 - modified file with a <filename>.orig</filename> 27.195 - extension.</para> 27.196 - 27.197 - &interaction.daily.revert.status; 27.198 - 27.199 - <para>Here is a summary of the cases that the <command 27.200 - role="hg-cmd">hg revert</command> command can deal with. We 27.201 - will describe each of these in more detail in the section that 27.202 - follows.</para> 27.203 - <itemizedlist> 27.204 - <listitem><para>If you modify a file, it will restore the file 27.205 - to its unmodified state.</para> 27.206 - </listitem> 27.207 - <listitem><para>If you <command role="hg-cmd">hg add</command> a 27.208 - file, it will undo the <quote>added</quote> state of the 27.209 - file, but leave the file itself untouched.</para> 27.210 - </listitem> 27.211 - <listitem><para>If you delete a file without telling Mercurial, 27.212 - it will restore the file to its unmodified contents.</para> 27.213 - </listitem> 27.214 - <listitem><para>If you use the <command role="hg-cmd">hg 27.215 - remove</command> command to remove a file, it will undo 27.216 - the <quote>removed</quote> state of the file, and restore 27.217 - the file to its unmodified contents.</para> 27.218 - </listitem></itemizedlist> 27.219 - 27.220 - <sect2 id="sec.undo.mgmt"> 27.221 - <title>File management errors</title> 27.222 - 27.223 - <para>The <command role="hg-cmd">hg revert</command> command is 27.224 - useful for more than just modified files. It lets you reverse 27.225 - the results of all of Mercurial's file management 27.226 - commands&emdash;<command role="hg-cmd">hg add</command>, 27.227 - <command role="hg-cmd">hg remove</command>, and so on.</para> 27.228 - 27.229 - <para>If you <command role="hg-cmd">hg add</command> a file, 27.230 - then decide that in fact you don't want Mercurial to track it, 27.231 - use <command role="hg-cmd">hg revert</command> to undo the 27.232 - add. Don't worry; Mercurial will not modify the file in any 27.233 - way. It will just <quote>unmark</quote> the file.</para> 27.234 - 27.235 - &interaction.daily.revert.add; 27.236 - 27.237 - <para>Similarly, if you ask Mercurial to <command 27.238 - role="hg-cmd">hg remove</command> a file, you can use 27.239 - <command role="hg-cmd">hg revert</command> to restore it to 27.240 - the contents it had as of the parent of the working directory. 27.241 - &interaction.daily.revert.remove; This works just as 27.242 - well for a file that you deleted by hand, without telling 27.243 - Mercurial (recall that in Mercurial terminology, this kind of 27.244 - file is called <quote>missing</quote>).</para> 27.245 - 27.246 - &interaction.daily.revert.missing; 27.247 - 27.248 - <para>If you revert a <command role="hg-cmd">hg copy</command>, 27.249 - the copied-to file remains in your working directory 27.250 - afterwards, untracked. Since a copy doesn't affect the 27.251 - copied-from file in any way, Mercurial doesn't do anything 27.252 - with the copied-from file.</para> 27.253 - 27.254 - &interaction.daily.revert.copy; 27.255 - 27.256 - <sect3> 27.257 - <title>A slightly special case: reverting a rename</title> 27.258 - 27.259 - <para>If you <command role="hg-cmd">hg rename</command> a 27.260 - file, there is one small detail that you should remember. 27.261 - When you <command role="hg-cmd">hg revert</command> a 27.262 - rename, it's not enough to provide the name of the 27.263 - renamed-to file, as you can see here.</para> 27.264 - 27.265 - &interaction.daily.revert.rename; 27.266 - 27.267 - <para>As you can see from the output of <command 27.268 - role="hg-cmd">hg status</command>, the renamed-to file is 27.269 - no longer identified as added, but the 27.270 - renamed-<emphasis>from</emphasis> file is still removed! 27.271 - This is counter-intuitive (at least to me), but at least 27.272 - it's easy to deal with.</para> 27.273 - 27.274 - &interaction.daily.revert.rename-orig; 27.275 - 27.276 - <para>So remember, to revert a <command role="hg-cmd">hg 27.277 - rename</command>, you must provide 27.278 - <emphasis>both</emphasis> the source and destination 27.279 - names.</para> 27.280 - 27.281 - <para>% TODO: the output doesn't look like it will be 27.282 - removed!</para> 27.283 - 27.284 - <para>(By the way, if you rename a file, then modify the 27.285 - renamed-to file, then revert both components of the rename, 27.286 - when Mercurial restores the file that was removed as part of 27.287 - the rename, it will be unmodified. If you need the 27.288 - modifications in the renamed-to file to show up in the 27.289 - renamed-from file, don't forget to copy them over.)</para> 27.290 - 27.291 - <para>These fiddly aspects of reverting a rename arguably 27.292 - constitute a small bug in Mercurial.</para> 27.293 - 27.294 - </sect3> 27.295 - </sect2> 27.296 - </sect1> 27.297 - <sect1> 27.298 - <title>Dealing with committed changes</title> 27.299 - 27.300 - <para>Consider a case where you have committed a change $a$, and 27.301 - another change $b$ on top of it; you then realise that change 27.302 - $a$ was incorrect. Mercurial lets you <quote>back out</quote> 27.303 - an entire changeset automatically, and building blocks that let 27.304 - you reverse part of a changeset by hand.</para> 27.305 - 27.306 - <para>Before you read this section, here's something to keep in 27.307 - mind: the <command role="hg-cmd">hg backout</command> command 27.308 - undoes changes by <emphasis>adding</emphasis> history, not by 27.309 - modifying or erasing it. It's the right tool to use if you're 27.310 - fixing bugs, but not if you're trying to undo some change that 27.311 - has catastrophic consequences. To deal with those, see section 27.312 - <xref linkend="sec.undo.aaaiiieee"/>.</para> 27.313 - 27.314 - <sect2> 27.315 - <title>Backing out a changeset</title> 27.316 - 27.317 - <para>The <command role="hg-cmd">hg backout</command> command 27.318 - lets you <quote>undo</quote> the effects of an entire 27.319 - changeset in an automated fashion. Because Mercurial's 27.320 - history is immutable, this command <emphasis>does 27.321 - not</emphasis> get rid of the changeset you want to undo. 27.322 - Instead, it creates a new changeset that 27.323 - <emphasis>reverses</emphasis> the effect of the to-be-undone 27.324 - changeset.</para> 27.325 - 27.326 - <para>The operation of the <command role="hg-cmd">hg 27.327 - backout</command> command is a little intricate, so let's 27.328 - illustrate it with some examples. First, we'll create a 27.329 - repository with some simple changes.</para> 27.330 - 27.331 - &interaction.backout.init; 27.332 - 27.333 - <para>The <command role="hg-cmd">hg backout</command> command 27.334 - takes a single changeset ID as its argument; this is the 27.335 - changeset to back out. Normally, <command role="hg-cmd">hg 27.336 - backout</command> will drop you into a text editor to write 27.337 - a commit message, so you can record why you're backing the 27.338 - change out. In this example, we provide a commit message on 27.339 - the command line using the <option 27.340 - role="hg-opt-backout">-m</option> option.</para> 27.341 - 27.342 - </sect2> 27.343 - <sect2> 27.344 - <title>Backing out the tip changeset</title> 27.345 - 27.346 - <para>We're going to start by backing out the last changeset we 27.347 - committed.</para> 27.348 - 27.349 - &interaction.backout.simple; 27.350 - 27.351 - <para>You can see that the second line from 27.352 - <filename>myfile</filename> is no longer present. Taking a 27.353 - look at the output of <command role="hg-cmd">hg log</command> 27.354 - gives us an idea of what the <command role="hg-cmd">hg 27.355 - backout</command> command has done. 27.356 - &interaction.backout.simple.log; Notice that the new changeset 27.357 - that <command role="hg-cmd">hg backout</command> has created 27.358 - is a child of the changeset we backed out. It's easier to see 27.359 - this in figure <xref 27.360 - endterm="fig.undo.backout.caption" linkend="fig.undo.backout"/>, 27.361 - which presents a graphical 27.362 - view of the change history. As you can see, the history is 27.363 - nice and linear.</para> 27.364 - 27.365 - <informalfigure id="fig.undo.backout"> 27.366 - <mediaobject> 27.367 - <imageobject><imagedata fileref="images/undo-simple.png"/> 27.368 - </imageobject> 27.369 - <textobject><phrase>XXX add text</phrase></textobject> 27.370 - <caption><para id="fig.undo.backout.caption">Backing out 27.371 - a change using the 27.372 - <command role="hg-cmd">hg backout</command> 27.373 - command</para></caption> 27.374 - </mediaobject> 27.375 - </informalfigure> 27.376 - 27.377 - </sect2> 27.378 - <sect2> 27.379 - <title>Backing out a non-tip change</title> 27.380 - 27.381 - <para>If you want to back out a change other than the last one 27.382 - you committed, pass the <option 27.383 - role="hg-opt-backout">--merge</option> option to the 27.384 - <command role="hg-cmd">hg backout</command> command.</para> 27.385 - 27.386 - &interaction.backout.non-tip.clone; 27.387 - 27.388 - <para>This makes backing out any changeset a 27.389 - <quote>one-shot</quote> operation that's usually simple and 27.390 - fast.</para> 27.391 - 27.392 - &interaction.backout.non-tip.backout; 27.393 - 27.394 - <para>If you take a look at the contents of 27.395 - <filename>myfile</filename> after the backout finishes, you'll 27.396 - see that the first and third changes are present, but not the 27.397 - second.</para> 27.398 - 27.399 - &interaction.backout.non-tip.cat; 27.400 - 27.401 - <para>As the graphical history in figure <xref 27.402 - endterm="fig.undo.backout-non-tip.caption" 27.403 - linkend="fig.undo.backout-non-tip"/> illustrates, Mercurial 27.404 - actually commits <emphasis>two</emphasis> changes in this kind 27.405 - of situation (the box-shaped nodes are the ones that Mercurial 27.406 - commits automatically). Before Mercurial begins the backout 27.407 - process, it first remembers what the current parent of the 27.408 - working directory is. It then backs out the target changeset, 27.409 - and commits that as a changeset. Finally, it merges back to 27.410 - the previous parent of the working directory, and commits the 27.411 - result of the merge.</para> 27.412 - 27.413 - <para>% TODO: to me it looks like mercurial doesn't commit the 27.414 - second merge automatically!</para> 27.415 - 27.416 - <informalfigure id="fig.undo.backout-non-tip"> 27.417 - <mediaobject> 27.418 - <imageobject><imagedata fileref="images/undo-non-tip.png"/> 27.419 - </imageobject> 27.420 - <textobject><phrase>XXX add text</phrase></textobject> 27.421 - <caption><para id="fig.undo.backout-non-tip.caption">Automated 27.422 - backout of a non-tip change using the 27.423 - <command role="hg-cmd">hg backout</command> command</para></caption> 27.424 - </mediaobject> 27.425 - </informalfigure> 27.426 - 27.427 - <para>The result is that you end up <quote>back where you 27.428 - were</quote>, only with some extra history that undoes the 27.429 - effect of the changeset you wanted to back out.</para> 27.430 - 27.431 - <sect3> 27.432 - <title>Always use the <option 27.433 - role="hg-opt-backout">--merge</option> option</title> 27.434 - 27.435 - <para>In fact, since the <option 27.436 - role="hg-opt-backout">--merge</option> option will do the 27.437 - <quote>right thing</quote> whether or not the changeset 27.438 - you're backing out is the tip (i.e. it won't try to merge if 27.439 - it's backing out the tip, since there's no need), you should 27.440 - <emphasis>always</emphasis> use this option when you run the 27.441 - <command role="hg-cmd">hg backout</command> command.</para> 27.442 - 27.443 - </sect3> 27.444 - </sect2> 27.445 - <sect2> 27.446 - <title>Gaining more control of the backout process</title> 27.447 - 27.448 - <para>While I've recommended that you always use the <option 27.449 - role="hg-opt-backout">--merge</option> option when backing 27.450 - out a change, the <command role="hg-cmd">hg backout</command> 27.451 - command lets you decide how to merge a backout changeset. 27.452 - Taking control of the backout process by hand is something you 27.453 - will rarely need to do, but it can be useful to understand 27.454 - what the <command role="hg-cmd">hg backout</command> command 27.455 - is doing for you automatically. To illustrate this, let's 27.456 - clone our first repository, but omit the backout change that 27.457 - it contains.</para> 27.458 - 27.459 - &interaction.backout.manual.clone; 27.460 - 27.461 - <para>As with our 27.462 - earlier example, We'll commit a third changeset, then back out 27.463 - its parent, and see what happens.</para> 27.464 - 27.465 - &interaction.backout.manual.backout; 27.466 - 27.467 - <para>Our new changeset is again a descendant of the changeset 27.468 - we backout out; it's thus a new head, <emphasis>not</emphasis> 27.469 - a descendant of the changeset that was the tip. The <command 27.470 - role="hg-cmd">hg backout</command> command was quite 27.471 - explicit in telling us this.</para> 27.472 - 27.473 - &interaction.backout.manual.log; 27.474 - 27.475 - <para>Again, it's easier to see what has happened by looking at 27.476 - a graph of the revision history, in figure <xref 27.477 - endterm="fig.undo.backout-manual.caption" 27.478 - linkend="fig.undo.backout-manual"/>. This makes it clear 27.479 - that when we use <command role="hg-cmd">hg backout</command> 27.480 - to back out a change other than the tip, Mercurial adds a new 27.481 - head to the repository (the change it committed is 27.482 - box-shaped).</para> 27.483 - 27.484 - <informalfigure id="fig.undo.backout-manual"> 27.485 - <mediaobject> 27.486 - <imageobject><imagedata fileref="images/undo-manual.png"/> 27.487 - </imageobject> 27.488 - <textobject><phrase>XXX add text</phrase></textobject> 27.489 - <caption><para id="fig.undo.backout-manual.caption">Backing out a 27.490 - change using the <command role="hg-cmd">hg backout</command> 27.491 - command</para></caption> 27.492 - </mediaobject> 27.493 - </informalfigure> 27.494 - 27.495 - <para>After the <command role="hg-cmd">hg backout</command> 27.496 - command has completed, it leaves the new 27.497 - <quote>backout</quote> changeset as the parent of the working 27.498 - directory.</para> 27.499 - 27.500 - &interaction.backout.manual.parents; 27.501 - 27.502 - <para>Now we have two isolated sets of changes.</para> 27.503 - 27.504 - &interaction.backout.manual.heads; 27.505 - 27.506 - <para>Let's think about what we expect to see as the contents of 27.507 - <filename>myfile</filename> now. The first change should be 27.508 - present, because we've never backed it out. The second change 27.509 - should be missing, as that's the change we backed out. Since 27.510 - the history graph shows the third change as a separate head, 27.511 - we <emphasis>don't</emphasis> expect to see the third change 27.512 - present in <filename>myfile</filename>.</para> 27.513 - 27.514 - &interaction.backout.manual.cat; 27.515 - 27.516 - <para>To get the third change back into the file, we just do a 27.517 - normal merge of our two heads.</para> 27.518 - 27.519 - &interaction.backout.manual.merge; 27.520 - 27.521 - <para>Afterwards, the graphical history of our repository looks 27.522 - like figure 27.523 - <xref endterm="fig.undo.backout-manual-merge.caption" 27.524 - linkend="fig.undo.backout-manual-merge"/>.</para> 27.525 - 27.526 - <informalfigure id="fig.undo.backout-manual-merge"> 27.527 - <mediaobject> 27.528 - <imageobject><imagedata fileref="images/undo-manual-merge.png"/> 27.529 - </imageobject> 27.530 - <textobject><phrase>XXX add text</phrase></textobject> 27.531 - <caption><para id="fig.undo.backout-manual-merge.caption">Manually 27.532 - merging a backout change</para></caption> 27.533 - </mediaobject> 27.534 - </informalfigure> 27.535 - 27.536 - </sect2> 27.537 - <sect2> 27.538 - <title>Why <command role="hg-cmd">hg backout</command> works as 27.539 - it does</title> 27.540 - 27.541 - <para>Here's a brief description of how the <command 27.542 - role="hg-cmd">hg backout</command> command works.</para> 27.543 - <orderedlist> 27.544 - <listitem><para>It ensures that the working directory is 27.545 - <quote>clean</quote>, i.e. that the output of <command 27.546 - role="hg-cmd">hg status</command> would be empty.</para> 27.547 - </listitem> 27.548 - <listitem><para>It remembers the current parent of the working 27.549 - directory. Let's call this changeset 27.550 - <literal>orig</literal></para> 27.551 - </listitem> 27.552 - <listitem><para>It does the equivalent of a <command 27.553 - role="hg-cmd">hg update</command> to sync the working 27.554 - directory to the changeset you want to back out. Let's 27.555 - call this changeset <literal>backout</literal></para> 27.556 - </listitem> 27.557 - <listitem><para>It finds the parent of that changeset. Let's 27.558 - call that changeset <literal>parent</literal>.</para> 27.559 - </listitem> 27.560 - <listitem><para>For each file that the 27.561 - <literal>backout</literal> changeset affected, it does the 27.562 - equivalent of a <command role="hg-cmd">hg revert -r 27.563 - parent</command> on that file, to restore it to the 27.564 - contents it had before that changeset was 27.565 - committed.</para> 27.566 - </listitem> 27.567 - <listitem><para>It commits the result as a new changeset. 27.568 - This changeset has <literal>backout</literal> as its 27.569 - parent.</para> 27.570 - </listitem> 27.571 - <listitem><para>If you specify <option 27.572 - role="hg-opt-backout">--merge</option> on the command 27.573 - line, it merges with <literal>orig</literal>, and commits 27.574 - the result of the merge.</para> 27.575 - </listitem></orderedlist> 27.576 - 27.577 - <para>An alternative way to implement the <command 27.578 - role="hg-cmd">hg backout</command> command would be to 27.579 - <command role="hg-cmd">hg export</command> the 27.580 - to-be-backed-out changeset as a diff, then use the <option 27.581 - role="cmd-opt-patch">--reverse</option> option to the 27.582 - <command>patch</command> command to reverse the effect of the 27.583 - change without fiddling with the working directory. This 27.584 - sounds much simpler, but it would not work nearly as 27.585 - well.</para> 27.586 - 27.587 - <para>The reason that <command role="hg-cmd">hg 27.588 - backout</command> does an update, a commit, a merge, and 27.589 - another commit is to give the merge machinery the best chance 27.590 - to do a good job when dealing with all the changes 27.591 - <emphasis>between</emphasis> the change you're backing out and 27.592 - the current tip.</para> 27.593 - 27.594 - <para>If you're backing out a changeset that's 100 revisions 27.595 - back in your project's history, the chances that the 27.596 - <command>patch</command> command will be able to apply a 27.597 - reverse diff cleanly are not good, because intervening changes 27.598 - are likely to have <quote>broken the context</quote> that 27.599 - <command>patch</command> uses to determine whether it can 27.600 - apply a patch (if this sounds like gibberish, see <xref 27.601 - linkend="sec.mq.patch"/> for a 27.602 - discussion of the <command>patch</command> command). Also, 27.603 - Mercurial's merge machinery will handle files and directories 27.604 - being renamed, permission changes, and modifications to binary 27.605 - files, none of which <command>patch</command> can deal 27.606 - with.</para> 27.607 - 27.608 - </sect2> 27.609 - </sect1> 27.610 - <sect1 id="sec.undo.aaaiiieee"> 27.611 - <title>Changes that should never have been</title> 27.612 - 27.613 - <para>Most of the time, the <command role="hg-cmd">hg 27.614 - backout</command> command is exactly what you need if you want 27.615 - to undo the effects of a change. It leaves a permanent record 27.616 - of exactly what you did, both when committing the original 27.617 - changeset and when you cleaned up after it.</para> 27.618 - 27.619 - <para>On rare occasions, though, you may find that you've 27.620 - committed a change that really should not be present in the 27.621 - repository at all. For example, it would be very unusual, and 27.622 - usually considered a mistake, to commit a software project's 27.623 - object files as well as its source files. Object files have 27.624 - almost no intrinsic value, and they're <emphasis>big</emphasis>, 27.625 - so they increase the size of the repository and the amount of 27.626 - time it takes to clone or pull changes.</para> 27.627 - 27.628 - <para>Before I discuss the options that you have if you commit a 27.629 - <quote>brown paper bag</quote> change (the kind that's so bad 27.630 - that you want to pull a brown paper bag over your head), let me 27.631 - first discuss some approaches that probably won't work.</para> 27.632 - 27.633 - <para>Since Mercurial treats history as accumulative&emdash;every 27.634 - change builds on top of all changes that preceded it&emdash;you 27.635 - generally can't just make disastrous changes disappear. The one 27.636 - exception is when you've just committed a change, and it hasn't 27.637 - been pushed or pulled into another repository. That's when you 27.638 - can safely use the <command role="hg-cmd">hg rollback</command> 27.639 - command, as I detailed in section <xref 27.640 - linkend="sec.undo.rollback"/>.</para> 27.641 - 27.642 - <para>After you've pushed a bad change to another repository, you 27.643 - <emphasis>could</emphasis> still use <command role="hg-cmd">hg 27.644 - rollback</command> to make your local copy of the change 27.645 - disappear, but it won't have the consequences you want. The 27.646 - change will still be present in the remote repository, so it 27.647 - will reappear in your local repository the next time you 27.648 - pull.</para> 27.649 - 27.650 - <para>If a situation like this arises, and you know which 27.651 - repositories your bad change has propagated into, you can 27.652 - <emphasis>try</emphasis> to get rid of the changeefrom 27.653 - <emphasis>every</emphasis> one of those repositories. This is, 27.654 - of course, not a satisfactory solution: if you miss even a 27.655 - single repository while you're expunging, the change is still 27.656 - <quote>in the wild</quote>, and could propagate further.</para> 27.657 - 27.658 - <para>If you've committed one or more changes 27.659 - <emphasis>after</emphasis> the change that you'd like to see 27.660 - disappear, your options are further reduced. Mercurial doesn't 27.661 - provide a way to <quote>punch a hole</quote> in history, leaving 27.662 - changesets intact.</para> 27.663 - 27.664 - <para>XXX This needs filling out. The 27.665 - <literal>hg-replay</literal> script in the 27.666 - <literal>examples</literal> directory works, but doesn't handle 27.667 - merge changesets. Kind of an important omission.</para> 27.668 - 27.669 - <sect2> 27.670 - <title>Protect yourself from <quote>escaped</quote> 27.671 - changes</title> 27.672 - 27.673 - <para>If you've committed some changes to your local repository 27.674 - and they've been pushed or pulled somewhere else, this isn't 27.675 - necessarily a disaster. You can protect yourself ahead of 27.676 - time against some classes of bad changeset. This is 27.677 - particularly easy if your team usually pulls changes from a 27.678 - central repository.</para> 27.679 - 27.680 - <para>By configuring some hooks on that repository to validate 27.681 - incoming changesets (see chapter <xref linkend="chap.hook"/>), 27.682 - you can 27.683 - automatically prevent some kinds of bad changeset from being 27.684 - pushed to the central repository at all. With such a 27.685 - configuration in place, some kinds of bad changeset will 27.686 - naturally tend to <quote>die out</quote> because they can't 27.687 - propagate into the central repository. Better yet, this 27.688 - happens without any need for explicit intervention.</para> 27.689 - 27.690 - <para>For instance, an incoming change hook that verifies that a 27.691 - changeset will actually compile can prevent people from 27.692 - inadvertantly <quote>breaking the build</quote>.</para> 27.693 - 27.694 - </sect2> 27.695 - </sect1> 27.696 - <sect1 id="sec.undo.bisect"> 27.697 - <title>Finding the source of a bug</title> 27.698 - 27.699 - <para>While it's all very well to be able to back out a changeset 27.700 - that introduced a bug, this requires that you know which 27.701 - changeset to back out. Mercurial provides an invaluable 27.702 - command, called <command role="hg-cmd">hg bisect</command>, that 27.703 - helps you to automate this process and accomplish it very 27.704 - efficiently.</para> 27.705 - 27.706 - <para>The idea behind the <command role="hg-cmd">hg 27.707 - bisect</command> command is that a changeset has introduced 27.708 - some change of behaviour that you can identify with a simple 27.709 - binary test. You don't know which piece of code introduced the 27.710 - change, but you know how to test for the presence of the bug. 27.711 - The <command role="hg-cmd">hg bisect</command> command uses your 27.712 - test to direct its search for the changeset that introduced the 27.713 - code that caused the bug.</para> 27.714 - 27.715 - <para>Here are a few scenarios to help you understand how you 27.716 - might apply this command.</para> 27.717 - <itemizedlist> 27.718 - <listitem><para>The most recent version of your software has a 27.719 - bug that you remember wasn't present a few weeks ago, but 27.720 - you don't know when it was introduced. Here, your binary 27.721 - test checks for the presence of that bug.</para> 27.722 - </listitem> 27.723 - <listitem><para>You fixed a bug in a rush, and now it's time to 27.724 - close the entry in your team's bug database. The bug 27.725 - database requires a changeset ID when you close an entry, 27.726 - but you don't remember which changeset you fixed the bug in. 27.727 - Once again, your binary test checks for the presence of the 27.728 - bug.</para> 27.729 - </listitem> 27.730 - <listitem><para>Your software works correctly, but runs 15% 27.731 - slower than the last time you measured it. You want to know 27.732 - which changeset introduced the performance regression. In 27.733 - this case, your binary test measures the performance of your 27.734 - software, to see whether it's <quote>fast</quote> or 27.735 - <quote>slow</quote>.</para> 27.736 - </listitem> 27.737 - <listitem><para>The sizes of the components of your project that 27.738 - you ship exploded recently, and you suspect that something 27.739 - changed in the way you build your project.</para> 27.740 - </listitem></itemizedlist> 27.741 - 27.742 - <para>From these examples, it should be clear that the <command 27.743 - role="hg-cmd">hg bisect</command> command is not useful only 27.744 - for finding the sources of bugs. You can use it to find any 27.745 - <quote>emergent property</quote> of a repository (anything that 27.746 - you can't find from a simple text search of the files in the 27.747 - tree) for which you can write a binary test.</para> 27.748 - 27.749 - <para>We'll introduce a little bit of terminology here, just to 27.750 - make it clear which parts of the search process are your 27.751 - responsibility, and which are Mercurial's. A 27.752 - <emphasis>test</emphasis> is something that 27.753 - <emphasis>you</emphasis> run when <command role="hg-cmd">hg 27.754 - bisect</command> chooses a changeset. A 27.755 - <emphasis>probe</emphasis> is what <command role="hg-cmd">hg 27.756 - bisect</command> runs to tell whether a revision is good. 27.757 - Finally, we'll use the word <quote>bisect</quote>, as both a 27.758 - noun and a verb, to stand in for the phrase <quote>search using 27.759 - the <command role="hg-cmd">hg bisect</command> 27.760 - command</quote>.</para> 27.761 - 27.762 - <para>One simple way to automate the searching process would be 27.763 - simply to probe every changeset. However, this scales poorly. 27.764 - If it took ten minutes to test a single changeset, and you had 27.765 - 10,000 changesets in your repository, the exhaustive approach 27.766 - would take on average 35 <emphasis>days</emphasis> to find the 27.767 - changeset that introduced a bug. Even if you knew that the bug 27.768 - was introduced by one of the last 500 changesets, and limited 27.769 - your search to those, you'd still be looking at over 40 hours to 27.770 - find the changeset that introduced your bug.</para> 27.771 - 27.772 - <para>What the <command role="hg-cmd">hg bisect</command> command 27.773 - does is use its knowledge of the <quote>shape</quote> of your 27.774 - project's revision history to perform a search in time 27.775 - proportional to the <emphasis>logarithm</emphasis> of the number 27.776 - of changesets to check (the kind of search it performs is called 27.777 - a dichotomic search). With this approach, searching through 27.778 - 10,000 changesets will take less than three hours, even at ten 27.779 - minutes per test (the search will require about 14 tests). 27.780 - Limit your search to the last hundred changesets, and it will 27.781 - take only about an hour (roughly seven tests).</para> 27.782 - 27.783 - <para>The <command role="hg-cmd">hg bisect</command> command is 27.784 - aware of the <quote>branchy</quote> nature of a Mercurial 27.785 - project's revision history, so it has no problems dealing with 27.786 - branches, merges, or multiple heads in a repository. It can 27.787 - prune entire branches of history with a single probe, which is 27.788 - how it operates so efficiently.</para> 27.789 - 27.790 - <sect2> 27.791 - <title>Using the <command role="hg-cmd">hg bisect</command> 27.792 - command</title> 27.793 - 27.794 - <para>Here's an example of <command role="hg-cmd">hg 27.795 - bisect</command> in action.</para> 27.796 - 27.797 - <note> 27.798 - <para> In versions 0.9.5 and earlier of Mercurial, <command 27.799 - role="hg-cmd">hg bisect</command> was not a core command: 27.800 - it was distributed with Mercurial as an extension. This 27.801 - section describes the built-in command, not the old 27.802 - extension.</para> 27.803 - </note> 27.804 - 27.805 - <para>Now let's create a repository, so that we can try out the 27.806 - <command role="hg-cmd">hg bisect</command> command in 27.807 - isolation.</para> 27.808 - 27.809 - &interaction.bisect.init; 27.810 - 27.811 - <para>We'll simulate a project that has a bug in it in a 27.812 - simple-minded way: create trivial changes in a loop, and 27.813 - nominate one specific change that will have the 27.814 - <quote>bug</quote>. This loop creates 35 changesets, each 27.815 - adding a single file to the repository. We'll represent our 27.816 - <quote>bug</quote> with a file that contains the text <quote>i 27.817 - have a gub</quote>.</para> 27.818 - 27.819 - &interaction.bisect.commits; 27.820 - 27.821 - <para>The next thing that we'd like to do is figure out how to 27.822 - use the <command role="hg-cmd">hg bisect</command> command. 27.823 - We can use Mercurial's normal built-in help mechanism for 27.824 - this.</para> 27.825 - 27.826 - &interaction.bisect.help; 27.827 - 27.828 - <para>The <command role="hg-cmd">hg bisect</command> command 27.829 - works in steps. Each step proceeds as follows.</para> 27.830 - <orderedlist> 27.831 - <listitem><para>You run your binary test.</para> 27.832 - <itemizedlist> 27.833 - <listitem><para>If the test succeeded, you tell <command 27.834 - role="hg-cmd">hg bisect</command> by running the 27.835 - <command role="hg-cmd">hg bisect good</command> 27.836 - command.</para> 27.837 - </listitem> 27.838 - <listitem><para>If it failed, run the <command 27.839 - role="hg-cmd">hg bisect bad</command> 27.840 - command.</para></listitem></itemizedlist> 27.841 - </listitem> 27.842 - <listitem><para>The command uses your information to decide 27.843 - which changeset to test next.</para> 27.844 - </listitem> 27.845 - <listitem><para>It updates the working directory to that 27.846 - changeset, and the process begins again.</para> 27.847 - </listitem></orderedlist> 27.848 - <para>The process ends when <command role="hg-cmd">hg 27.849 - bisect</command> identifies a unique changeset that marks 27.850 - the point where your test transitioned from 27.851 - <quote>succeeding</quote> to <quote>failing</quote>.</para> 27.852 - 27.853 - <para>To start the search, we must run the <command 27.854 - role="hg-cmd">hg bisect --reset</command> command.</para> 27.855 - 27.856 - &interaction.bisect.search.init; 27.857 - 27.858 - <para>In our case, the binary test we use is simple: we check to 27.859 - see if any file in the repository contains the string <quote>i 27.860 - have a gub</quote>. If it does, this changeset contains the 27.861 - change that <quote>caused the bug</quote>. By convention, a 27.862 - changeset that has the property we're searching for is 27.863 - <quote>bad</quote>, while one that doesn't is 27.864 - <quote>good</quote>.</para> 27.865 - 27.866 - <para>Most of the time, the revision to which the working 27.867 - directory is synced (usually the tip) already exhibits the 27.868 - problem introduced by the buggy change, so we'll mark it as 27.869 - <quote>bad</quote>.</para> 27.870 - 27.871 - &interaction.bisect.search.bad-init; 27.872 - 27.873 - <para>Our next task is to nominate a changeset that we know 27.874 - <emphasis>doesn't</emphasis> have the bug; the <command 27.875 - role="hg-cmd">hg bisect</command> command will 27.876 - <quote>bracket</quote> its search between the first pair of 27.877 - good and bad changesets. In our case, we know that revision 27.878 - 10 didn't have the bug. (I'll have more words about choosing 27.879 - the first <quote>good</quote> changeset later.)</para> 27.880 - 27.881 - &interaction.bisect.search.good-init; 27.882 - 27.883 - <para>Notice that this command printed some output.</para> 27.884 - <itemizedlist> 27.885 - <listitem><para>It told us how many changesets it must 27.886 - consider before it can identify the one that introduced 27.887 - the bug, and how many tests that will require.</para> 27.888 - </listitem> 27.889 - <listitem><para>It updated the working directory to the next 27.890 - changeset to test, and told us which changeset it's 27.891 - testing.</para> 27.892 - </listitem></itemizedlist> 27.893 - 27.894 - <para>We now run our test in the working directory. We use the 27.895 - <command>grep</command> command to see if our 27.896 - <quote>bad</quote> file is present in the working directory. 27.897 - If it is, this revision is bad; if not, this revision is good. 27.898 - &interaction.bisect.search.step1;</para> 27.899 - 27.900 - <para>This test looks like a perfect candidate for automation, 27.901 - so let's turn it into a shell function.</para> 27.902 - &interaction.bisect.search.mytest; 27.903 - 27.904 - <para>We can now run an entire test step with a single command, 27.905 - <literal>mytest</literal>.</para> 27.906 - 27.907 - &interaction.bisect.search.step2; 27.908 - 27.909 - <para>A few more invocations of our canned test step command, 27.910 - and we're done.</para> 27.911 - 27.912 - &interaction.bisect.search.rest; 27.913 - 27.914 - <para>Even though we had 40 changesets to search through, the 27.915 - <command role="hg-cmd">hg bisect</command> command let us find 27.916 - the changeset that introduced our <quote>bug</quote> with only 27.917 - five tests. Because the number of tests that the <command 27.918 - role="hg-cmd">hg bisect</command> command performs grows 27.919 - logarithmically with the number of changesets to search, the 27.920 - advantage that it has over the <quote>brute force</quote> 27.921 - search approach increases with every changeset you add.</para> 27.922 - 27.923 - </sect2> 27.924 - <sect2> 27.925 - <title>Cleaning up after your search</title> 27.926 - 27.927 - <para>When you're finished using the <command role="hg-cmd">hg 27.928 - bisect</command> command in a repository, you can use the 27.929 - <command role="hg-cmd">hg bisect reset</command> command to 27.930 - drop the information it was using to drive your search. The 27.931 - command doesn't use much space, so it doesn't matter if you 27.932 - forget to run this command. However, <command 27.933 - role="hg-cmd">hg bisect</command> won't let you start a new 27.934 - search in that repository until you do a <command 27.935 - role="hg-cmd">hg bisect reset</command>.</para> 27.936 - 27.937 - &interaction.bisect.search.reset; 27.938 - 27.939 - </sect2> 27.940 - </sect1> 27.941 - <sect1> 27.942 - <title>Tips for finding bugs effectively</title> 27.943 - 27.944 - <sect2> 27.945 - <title>Give consistent input</title> 27.946 - 27.947 - <para>The <command role="hg-cmd">hg bisect</command> command 27.948 - requires that you correctly report the result of every test 27.949 - you perform. If you tell it that a test failed when it really 27.950 - succeeded, it <emphasis>might</emphasis> be able to detect the 27.951 - inconsistency. If it can identify an inconsistency in your 27.952 - reports, it will tell you that a particular changeset is both 27.953 - good and bad. However, it can't do this perfectly; it's about 27.954 - as likely to report the wrong changeset as the source of the 27.955 - bug.</para> 27.956 - 27.957 - </sect2> 27.958 - <sect2> 27.959 - <title>Automate as much as possible</title> 27.960 - 27.961 - <para>When I started using the <command role="hg-cmd">hg 27.962 - bisect</command> command, I tried a few times to run my 27.963 - tests by hand, on the command line. This is an approach that 27.964 - I, at least, am not suited to. After a few tries, I found 27.965 - that I was making enough mistakes that I was having to restart 27.966 - my searches several times before finally getting correct 27.967 - results.</para> 27.968 - 27.969 - <para>My initial problems with driving the <command 27.970 - role="hg-cmd">hg bisect</command> command by hand occurred 27.971 - even with simple searches on small repositories; if the 27.972 - problem you're looking for is more subtle, or the number of 27.973 - tests that <command role="hg-cmd">hg bisect</command> must 27.974 - perform increases, the likelihood of operator error ruining 27.975 - the search is much higher. Once I started automating my 27.976 - tests, I had much better results.</para> 27.977 - 27.978 - <para>The key to automated testing is twofold:</para> 27.979 - <itemizedlist> 27.980 - <listitem><para>always test for the same symptom, and</para> 27.981 - </listitem> 27.982 - <listitem><para>always feed consistent input to the <command 27.983 - role="hg-cmd">hg bisect</command> command.</para> 27.984 - </listitem></itemizedlist> 27.985 - <para>In my tutorial example above, the <command>grep</command> 27.986 - command tests for the symptom, and the <literal>if</literal> 27.987 - statement takes the result of this check and ensures that we 27.988 - always feed the same input to the <command role="hg-cmd">hg 27.989 - bisect</command> command. The <literal>mytest</literal> 27.990 - function marries these together in a reproducible way, so that 27.991 - every test is uniform and consistent.</para> 27.992 - 27.993 - </sect2> 27.994 - <sect2> 27.995 - <title>Check your results</title> 27.996 - 27.997 - <para>Because the output of a <command role="hg-cmd">hg 27.998 - bisect</command> search is only as good as the input you 27.999 - give it, don't take the changeset it reports as the absolute 27.1000 - truth. A simple way to cross-check its report is to manually 27.1001 - run your test at each of the following changesets:</para> 27.1002 - <itemizedlist> 27.1003 - <listitem><para>The changeset that it reports as the first bad 27.1004 - revision. Your test should still report this as 27.1005 - bad.</para> 27.1006 - </listitem> 27.1007 - <listitem><para>The parent of that changeset (either parent, 27.1008 - if it's a merge). Your test should report this changeset 27.1009 - as good.</para> 27.1010 - </listitem> 27.1011 - <listitem><para>A child of that changeset. Your test should 27.1012 - report this changeset as bad.</para> 27.1013 - </listitem></itemizedlist> 27.1014 - 27.1015 - </sect2> 27.1016 - <sect2> 27.1017 - <title>Beware interference between bugs</title> 27.1018 - 27.1019 - <para>It's possible that your search for one bug could be 27.1020 - disrupted by the presence of another. For example, let's say 27.1021 - your software crashes at revision 100, and worked correctly at 27.1022 - revision 50. Unknown to you, someone else introduced a 27.1023 - different crashing bug at revision 60, and fixed it at 27.1024 - revision 80. This could distort your results in one of 27.1025 - several ways.</para> 27.1026 - 27.1027 - <para>It is possible that this other bug completely 27.1028 - <quote>masks</quote> yours, which is to say that it occurs 27.1029 - before your bug has a chance to manifest itself. If you can't 27.1030 - avoid that other bug (for example, it prevents your project 27.1031 - from building), and so can't tell whether your bug is present 27.1032 - in a particular changeset, the <command role="hg-cmd">hg 27.1033 - bisect</command> command cannot help you directly. Instead, 27.1034 - you can mark a changeset as untested by running <command 27.1035 - role="hg-cmd">hg bisect --skip</command>.</para> 27.1036 - 27.1037 - <para>A different problem could arise if your test for a bug's 27.1038 - presence is not specific enough. If you check for <quote>my 27.1039 - program crashes</quote>, then both your crashing bug and an 27.1040 - unrelated crashing bug that masks it will look like the same 27.1041 - thing, and mislead <command role="hg-cmd">hg 27.1042 - bisect</command>.</para> 27.1043 - 27.1044 - <para>Another useful situation in which to use <command 27.1045 - role="hg-cmd">hg bisect --skip</command> is if you can't 27.1046 - test a revision because your project was in a broken and hence 27.1047 - untestable state at that revision, perhaps because someone 27.1048 - checked in a change that prevented the project from 27.1049 - building.</para> 27.1050 - 27.1051 - </sect2> 27.1052 - <sect2> 27.1053 - <title>Bracket your search lazily</title> 27.1054 - 27.1055 - <para>Choosing the first <quote>good</quote> and 27.1056 - <quote>bad</quote> changesets that will mark the end points of 27.1057 - your search is often easy, but it bears a little discussion 27.1058 - nevertheless. From the perspective of <command 27.1059 - role="hg-cmd">hg bisect</command>, the <quote>newest</quote> 27.1060 - changeset is conventionally <quote>bad</quote>, and the older 27.1061 - changeset is <quote>good</quote>.</para> 27.1062 - 27.1063 - <para>If you're having trouble remembering when a suitable 27.1064 - <quote>good</quote> change was, so that you can tell <command 27.1065 - role="hg-cmd">hg bisect</command>, you could do worse than 27.1066 - testing changesets at random. Just remember to eliminate 27.1067 - contenders that can't possibly exhibit the bug (perhaps 27.1068 - because the feature with the bug isn't present yet) and those 27.1069 - where another problem masks the bug (as I discussed 27.1070 - above).</para> 27.1071 - 27.1072 - <para>Even if you end up <quote>early</quote> by thousands of 27.1073 - changesets or months of history, you will only add a handful 27.1074 - of tests to the total number that <command role="hg-cmd">hg 27.1075 - bisect</command> must perform, thanks to its logarithmic 27.1076 - behaviour.</para> 27.1077 - 27.1078 - </sect2> 27.1079 - </sect1> 27.1080 -</chapter> 27.1081 - 27.1082 -<!-- 27.1083 -local variables: 27.1084 -sgml-parent-document: ("00book.xml" "book" "chapter") 27.1085 -end: 27.1086 --->
28.1 --- a/en/ch10-hook.xml Fri Mar 20 15:40:06 2009 +0800 28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 28.3 @@ -1,2037 +0,0 @@ 28.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 28.5 - 28.6 -<chapter id="chap.hook"> 28.7 - <?dbhtml filename="handling-repository-events-with-hooks.html"?> 28.8 - <title>Handling repository events with hooks</title> 28.9 - 28.10 - <para>Mercurial offers a powerful mechanism to let you perform 28.11 - automated actions in response to events that occur in a 28.12 - repository. In some cases, you can even control Mercurial's 28.13 - response to those events.</para> 28.14 - 28.15 - <para>The name Mercurial uses for one of these actions is a 28.16 - <emphasis>hook</emphasis>. Hooks are called 28.17 - <quote>triggers</quote> in some revision control systems, but the 28.18 - two names refer to the same idea.</para> 28.19 - 28.20 - <sect1> 28.21 - <title>An overview of hooks in Mercurial</title> 28.22 - 28.23 - <para>Here is a brief list of the hooks that Mercurial supports. 28.24 - We will revisit each of these hooks in more detail later, in 28.25 - section <xref linkend="sec.hook.ref"/>.</para> 28.26 - 28.27 - <itemizedlist> 28.28 - <listitem><para><literal role="hook">changegroup</literal>: This 28.29 - is run after a group of changesets has been brought into the 28.30 - repository from elsewhere.</para> 28.31 - </listitem> 28.32 - <listitem><para><literal role="hook">commit</literal>: This is 28.33 - run after a new changeset has been created in the local 28.34 - repository.</para> 28.35 - </listitem> 28.36 - <listitem><para><literal role="hook">incoming</literal>: This is 28.37 - run once for each new changeset that is brought into the 28.38 - repository from elsewhere. Notice the difference from 28.39 - <literal role="hook">changegroup</literal>, which is run 28.40 - once per <emphasis>group</emphasis> of changesets brought 28.41 - in.</para> 28.42 - </listitem> 28.43 - <listitem><para><literal role="hook">outgoing</literal>: This is 28.44 - run after a group of changesets has been transmitted from 28.45 - this repository.</para> 28.46 - </listitem> 28.47 - <listitem><para><literal role="hook">prechangegroup</literal>: 28.48 - This is run before starting to bring a group of changesets 28.49 - into the repository. 28.50 - </para> 28.51 - </listitem> 28.52 - <listitem><para><literal role="hook">precommit</literal>: 28.53 - Controlling. This is run before starting a commit. 28.54 - </para> 28.55 - </listitem> 28.56 - <listitem><para><literal role="hook">preoutgoing</literal>: 28.57 - Controlling. This is run before starting to transmit a group 28.58 - of changesets from this repository. 28.59 - </para> 28.60 - </listitem> 28.61 - <listitem><para><literal role="hook">pretag</literal>: 28.62 - Controlling. This is run before creating a tag. 28.63 - </para> 28.64 - </listitem> 28.65 - <listitem><para><literal 28.66 - role="hook">pretxnchangegroup</literal>: Controlling. This 28.67 - is run after a group of changesets has been brought into the 28.68 - local repository from another, but before the transaction 28.69 - completes that will make the changes permanent in the 28.70 - repository. 28.71 - </para> 28.72 - </listitem> 28.73 - <listitem><para><literal role="hook">pretxncommit</literal>: 28.74 - Controlling. This is run after a new changeset has been 28.75 - created in the local repository, but before the transaction 28.76 - completes that will make it permanent. 28.77 - </para> 28.78 - </listitem> 28.79 - <listitem><para><literal role="hook">preupdate</literal>: 28.80 - Controlling. This is run before starting an update or merge 28.81 - of the working directory. 28.82 - </para> 28.83 - </listitem> 28.84 - <listitem><para><literal role="hook">tag</literal>: This is run 28.85 - after a tag is created. 28.86 - </para> 28.87 - </listitem> 28.88 - <listitem><para><literal role="hook">update</literal>: This is 28.89 - run after an update or merge of the working directory has 28.90 - finished. 28.91 - </para> 28.92 - </listitem></itemizedlist> 28.93 - <para>Each of the hooks whose description begins with the word 28.94 - <quote>Controlling</quote> has the ability to determine whether 28.95 - an activity can proceed. If the hook succeeds, the activity may 28.96 - proceed; if it fails, the activity is either not permitted or 28.97 - undone, depending on the hook. 28.98 - </para> 28.99 - 28.100 - </sect1> 28.101 - <sect1> 28.102 - <title>Hooks and security</title> 28.103 - 28.104 - <sect2> 28.105 - <title>Hooks are run with your privileges</title> 28.106 - 28.107 - <para>When you run a Mercurial command in a repository, and the 28.108 - command causes a hook to run, that hook runs on 28.109 - <emphasis>your</emphasis> system, under 28.110 - <emphasis>your</emphasis> user account, with 28.111 - <emphasis>your</emphasis> privilege level. Since hooks are 28.112 - arbitrary pieces of executable code, you should treat them 28.113 - with an appropriate level of suspicion. Do not install a hook 28.114 - unless you are confident that you know who created it and what 28.115 - it does. 28.116 - </para> 28.117 - 28.118 - <para>In some cases, you may be exposed to hooks that you did 28.119 - not install yourself. If you work with Mercurial on an 28.120 - unfamiliar system, Mercurial will run hooks defined in that 28.121 - system's global <filename role="special">~/.hgrc</filename> 28.122 - file. 28.123 - </para> 28.124 - 28.125 - <para>If you are working with a repository owned by another 28.126 - user, Mercurial can run hooks defined in that user's 28.127 - repository, but it will still run them as <quote>you</quote>. 28.128 - For example, if you <command role="hg-cmd">hg pull</command> 28.129 - from that repository, and its <filename 28.130 - role="special">.hg/hgrc</filename> defines a local <literal 28.131 - role="hook">outgoing</literal> hook, that hook will run 28.132 - under your user account, even though you don't own that 28.133 - repository. 28.134 - </para> 28.135 - 28.136 - <note> 28.137 - <para> This only applies if you are pulling from a repository 28.138 - on a local or network filesystem. If you're pulling over 28.139 - http or ssh, any <literal role="hook">outgoing</literal> 28.140 - hook will run under whatever account is executing the server 28.141 - process, on the server. 28.142 - </para> 28.143 - </note> 28.144 - 28.145 - <para>XXX To see what hooks are defined in a repository, use the 28.146 - <command role="hg-cmd">hg config hooks</command> command. If 28.147 - you are working in one repository, but talking to another that 28.148 - you do not own (e.g. using <command role="hg-cmd">hg 28.149 - pull</command> or <command role="hg-cmd">hg 28.150 - incoming</command>), remember that it is the other 28.151 - repository's hooks you should be checking, not your own. 28.152 - </para> 28.153 - 28.154 - </sect2> 28.155 - <sect2> 28.156 - <title>Hooks do not propagate</title> 28.157 - 28.158 - <para>In Mercurial, hooks are not revision controlled, and do 28.159 - not propagate when you clone, or pull from, a repository. The 28.160 - reason for this is simple: a hook is a completely arbitrary 28.161 - piece of executable code. It runs under your user identity, 28.162 - with your privilege level, on your machine. 28.163 - </para> 28.164 - 28.165 - <para>It would be extremely reckless for any distributed 28.166 - revision control system to implement revision-controlled 28.167 - hooks, as this would offer an easily exploitable way to 28.168 - subvert the accounts of users of the revision control system. 28.169 - </para> 28.170 - 28.171 - <para>Since Mercurial does not propagate hooks, if you are 28.172 - collaborating with other people on a common project, you 28.173 - should not assume that they are using the same Mercurial hooks 28.174 - as you are, or that theirs are correctly configured. You 28.175 - should document the hooks you expect people to use. 28.176 - </para> 28.177 - 28.178 - <para>In a corporate intranet, this is somewhat easier to 28.179 - control, as you can for example provide a 28.180 - <quote>standard</quote> installation of Mercurial on an NFS 28.181 - filesystem, and use a site-wide <filename role="special">~/.hgrc</filename> file to define hooks that all users will 28.182 - see. However, this too has its limits; see below. 28.183 - </para> 28.184 - 28.185 - </sect2> 28.186 - <sect2> 28.187 - <title>Hooks can be overridden</title> 28.188 - 28.189 - <para>Mercurial allows you to override a hook definition by 28.190 - redefining the hook. You can disable it by setting its value 28.191 - to the empty string, or change its behaviour as you wish. 28.192 - </para> 28.193 - 28.194 - <para>If you deploy a system- or site-wide <filename 28.195 - role="special">~/.hgrc</filename> file that defines some 28.196 - hooks, you should thus understand that your users can disable 28.197 - or override those hooks. 28.198 - </para> 28.199 - 28.200 - </sect2> 28.201 - <sect2> 28.202 - <title>Ensuring that critical hooks are run</title> 28.203 - 28.204 - <para>Sometimes you may want to enforce a policy that you do not 28.205 - want others to be able to work around. For example, you may 28.206 - have a requirement that every changeset must pass a rigorous 28.207 - set of tests. Defining this requirement via a hook in a 28.208 - site-wide <filename role="special">~/.hgrc</filename> won't 28.209 - work for remote users on laptops, and of course local users 28.210 - can subvert it at will by overriding the hook. 28.211 - </para> 28.212 - 28.213 - <para>Instead, you can set up your policies for use of Mercurial 28.214 - so that people are expected to propagate changes through a 28.215 - well-known <quote>canonical</quote> server that you have 28.216 - locked down and configured appropriately. 28.217 - </para> 28.218 - 28.219 - <para>One way to do this is via a combination of social 28.220 - engineering and technology. Set up a restricted-access 28.221 - account; users can push changes over the network to 28.222 - repositories managed by this account, but they cannot log into 28.223 - the account and run normal shell commands. In this scenario, 28.224 - a user can commit a changeset that contains any old garbage 28.225 - they want. 28.226 - </para> 28.227 - 28.228 - <para>When someone pushes a changeset to the server that 28.229 - everyone pulls from, the server will test the changeset before 28.230 - it accepts it as permanent, and reject it if it fails to pass 28.231 - the test suite. If people only pull changes from this 28.232 - filtering server, it will serve to ensure that all changes 28.233 - that people pull have been automatically vetted. 28.234 - </para> 28.235 - 28.236 - </sect2> 28.237 - </sect1> 28.238 - <sect1> 28.239 - <title>Care with <literal>pretxn</literal> hooks in a 28.240 - shared-access repository</title> 28.241 - 28.242 - <para>If you want to use hooks to do some automated work in a 28.243 - repository that a number of people have shared access to, you 28.244 - need to be careful in how you do this. 28.245 - </para> 28.246 - 28.247 - <para>Mercurial only locks a repository when it is writing to the 28.248 - repository, and only the parts of Mercurial that write to the 28.249 - repository pay attention to locks. Write locks are necessary to 28.250 - prevent multiple simultaneous writers from scribbling on each 28.251 - other's work, corrupting the repository. 28.252 - </para> 28.253 - 28.254 - <para>Because Mercurial is careful with the order in which it 28.255 - reads and writes data, it does not need to acquire a lock when 28.256 - it wants to read data from the repository. The parts of 28.257 - Mercurial that read from the repository never pay attention to 28.258 - locks. This lockless reading scheme greatly increases 28.259 - performance and concurrency. 28.260 - </para> 28.261 - 28.262 - <para>With great performance comes a trade-off, though, one which 28.263 - has the potential to cause you trouble unless you're aware of 28.264 - it. To describe this requires a little detail about how 28.265 - Mercurial adds changesets to a repository and reads those 28.266 - changes. 28.267 - </para> 28.268 - 28.269 - <para>When Mercurial <emphasis>writes</emphasis> metadata, it 28.270 - writes it straight into the destination file. It writes file 28.271 - data first, then manifest data (which contains pointers to the 28.272 - new file data), then changelog data (which contains pointers to 28.273 - the new manifest data). Before the first write to each file, it 28.274 - stores a record of where the end of the file was in its 28.275 - transaction log. If the transaction must be rolled back, 28.276 - Mercurial simply truncates each file back to the size it was 28.277 - before the transaction began. 28.278 - </para> 28.279 - 28.280 - <para>When Mercurial <emphasis>reads</emphasis> metadata, it reads 28.281 - the changelog first, then everything else. Since a reader will 28.282 - only access parts of the manifest or file metadata that it can 28.283 - see in the changelog, it can never see partially written data. 28.284 - </para> 28.285 - 28.286 - <para>Some controlling hooks (<literal 28.287 - role="hook">pretxncommit</literal> and <literal 28.288 - role="hook">pretxnchangegroup</literal>) run when a 28.289 - transaction is almost complete. All of the metadata has been 28.290 - written, but Mercurial can still roll the transaction back and 28.291 - cause the newly-written data to disappear. 28.292 - </para> 28.293 - 28.294 - <para>If one of these hooks runs for long, it opens a window of 28.295 - time during which a reader can see the metadata for changesets 28.296 - that are not yet permanent, and should not be thought of as 28.297 - <quote>really there</quote>. The longer the hook runs, the 28.298 - longer that window is open. 28.299 - </para> 28.300 - 28.301 - <sect2> 28.302 - <title>The problem illustrated</title> 28.303 - 28.304 - <para>In principle, a good use for the <literal 28.305 - role="hook">pretxnchangegroup</literal> hook would be to 28.306 - automatically build and test incoming changes before they are 28.307 - accepted into a central repository. This could let you 28.308 - guarantee that nobody can push changes to this repository that 28.309 - <quote>break the build</quote>. But if a client can pull 28.310 - changes while they're being tested, the usefulness of the test 28.311 - is zero; an unsuspecting someone can pull untested changes, 28.312 - potentially breaking their build. 28.313 - </para> 28.314 - 28.315 - <para>The safest technological answer to this challenge is to 28.316 - set up such a <quote>gatekeeper</quote> repository as 28.317 - <emphasis>unidirectional</emphasis>. Let it take changes 28.318 - pushed in from the outside, but do not allow anyone to pull 28.319 - changes from it (use the <literal 28.320 - role="hook">preoutgoing</literal> hook to lock it down). 28.321 - Configure a <literal role="hook">changegroup</literal> hook so 28.322 - that if a build or test succeeds, the hook will push the new 28.323 - changes out to another repository that people 28.324 - <emphasis>can</emphasis> pull from. 28.325 - </para> 28.326 - 28.327 - <para>In practice, putting a centralised bottleneck like this in 28.328 - place is not often a good idea, and transaction visibility has 28.329 - nothing to do with the problem. As the size of a 28.330 - project&emdash;and the time it takes to build and 28.331 - test&emdash;grows, you rapidly run into a wall with this 28.332 - <quote>try before you buy</quote> approach, where you have 28.333 - more changesets to test than time in which to deal with them. 28.334 - The inevitable result is frustration on the part of all 28.335 - involved. 28.336 - </para> 28.337 - 28.338 - <para>An approach that scales better is to get people to build 28.339 - and test before they push, then run automated builds and tests 28.340 - centrally <emphasis>after</emphasis> a push, to be sure all is 28.341 - well. The advantage of this approach is that it does not 28.342 - impose a limit on the rate at which the repository can accept 28.343 - changes. 28.344 - </para> 28.345 - 28.346 - </sect2> 28.347 - </sect1> 28.348 - <sect1 id="sec.hook.simple"> 28.349 - <title>A short tutorial on using hooks</title> 28.350 - 28.351 - <para>It is easy to write a Mercurial hook. Let's start with a 28.352 - hook that runs when you finish a <command role="hg-cmd">hg 28.353 - commit</command>, and simply prints the hash of the changeset 28.354 - you just created. The hook is called <literal 28.355 - role="hook">commit</literal>. 28.356 - </para> 28.357 - 28.358 - <para>All hooks follow the pattern in this example.</para> 28.359 - 28.360 -&interaction.hook.simple.init; 28.361 - 28.362 - <para>You add an entry to the <literal 28.363 - role="rc-hooks">hooks</literal> section of your <filename 28.364 - role="special">~/.hgrc</filename>. On the left is the name of 28.365 - the event to trigger on; on the right is the action to take. As 28.366 - you can see, you can run an arbitrary shell command in a hook. 28.367 - Mercurial passes extra information to the hook using environment 28.368 - variables (look for <envar>HG_NODE</envar> in the example). 28.369 - </para> 28.370 - 28.371 - <sect2> 28.372 - <title>Performing multiple actions per event</title> 28.373 - 28.374 - <para>Quite often, you will want to define more than one hook 28.375 - for a particular kind of event, as shown below.</para> 28.376 - 28.377 -&interaction.hook.simple.ext; 28.378 - 28.379 - <para>Mercurial lets you do this by adding an 28.380 - <emphasis>extension</emphasis> to the end of a hook's name. 28.381 - You extend a hook's name by giving the name of the hook, 28.382 - followed by a full stop (the 28.383 - <quote><literal>.</literal></quote> character), followed by 28.384 - some more text of your choosing. For example, Mercurial will 28.385 - run both <literal>commit.foo</literal> and 28.386 - <literal>commit.bar</literal> when the 28.387 - <literal>commit</literal> event occurs. 28.388 - </para> 28.389 - 28.390 - <para>To give a well-defined order of execution when there are 28.391 - multiple hooks defined for an event, Mercurial sorts hooks by 28.392 - extension, and executes the hook commands in this sorted 28.393 - order. In the above example, it will execute 28.394 - <literal>commit.bar</literal> before 28.395 - <literal>commit.foo</literal>, and <literal>commit</literal> 28.396 - before both. 28.397 - </para> 28.398 - 28.399 - <para>It is a good idea to use a somewhat descriptive extension 28.400 - when you define a new hook. This will help you to remember 28.401 - what the hook was for. If the hook fails, you'll get an error 28.402 - message that contains the hook name and extension, so using a 28.403 - descriptive extension could give you an immediate hint as to 28.404 - why the hook failed (see section <xref 28.405 - linkend="sec.hook.perm"/> for an example). 28.406 - </para> 28.407 - 28.408 - </sect2> 28.409 - <sect2 id="sec.hook.perm"> 28.410 - <title>Controlling whether an activity can proceed</title> 28.411 - 28.412 - <para>In our earlier examples, we used the <literal 28.413 - role="hook">commit</literal> hook, which is run after a 28.414 - commit has completed. This is one of several Mercurial hooks 28.415 - that run after an activity finishes. Such hooks have no way 28.416 - of influencing the activity itself. 28.417 - </para> 28.418 - 28.419 - <para>Mercurial defines a number of events that occur before an 28.420 - activity starts; or after it starts, but before it finishes. 28.421 - Hooks that trigger on these events have the added ability to 28.422 - choose whether the activity can continue, or will abort. 28.423 - </para> 28.424 - 28.425 - <para>The <literal role="hook">pretxncommit</literal> hook runs 28.426 - after a commit has all but completed. In other words, the 28.427 - metadata representing the changeset has been written out to 28.428 - disk, but the transaction has not yet been allowed to 28.429 - complete. The <literal role="hook">pretxncommit</literal> 28.430 - hook has the ability to decide whether the transaction can 28.431 - complete, or must be rolled back. 28.432 - </para> 28.433 - 28.434 - <para>If the <literal role="hook">pretxncommit</literal> hook 28.435 - exits with a status code of zero, the transaction is allowed 28.436 - to complete; the commit finishes; and the <literal 28.437 - role="hook">commit</literal> hook is run. If the <literal 28.438 - role="hook">pretxncommit</literal> hook exits with a 28.439 - non-zero status code, the transaction is rolled back; the 28.440 - metadata representing the changeset is erased; and the 28.441 - <literal role="hook">commit</literal> hook is not run. 28.442 - </para> 28.443 - 28.444 -&interaction.hook.simple.pretxncommit; 28.445 - 28.446 - <para>The hook in the example above checks that a commit comment 28.447 - contains a bug ID. If it does, the commit can complete. If 28.448 - not, the commit is rolled back. 28.449 - </para> 28.450 - 28.451 - </sect2> 28.452 - </sect1> 28.453 - <sect1> 28.454 - <title>Writing your own hooks</title> 28.455 - 28.456 - <para>When you are writing a hook, you might find it useful to run 28.457 - Mercurial either with the <option 28.458 - role="hg-opt-global">-v</option> option, or the <envar 28.459 - role="rc-item-ui">verbose</envar> config item set to 28.460 - <quote>true</quote>. When you do so, Mercurial will print a 28.461 - message before it calls each hook. 28.462 - </para> 28.463 - 28.464 - <sect2 id="sec.hook.lang"> 28.465 - <title>Choosing how your hook should run</title> 28.466 - 28.467 - <para>You can write a hook either as a normal 28.468 - program&emdash;typically a shell script&emdash;or as a Python 28.469 - function that is executed within the Mercurial process. 28.470 - </para> 28.471 - 28.472 - <para>Writing a hook as an external program has the advantage 28.473 - that it requires no knowledge of Mercurial's internals. You 28.474 - can call normal Mercurial commands to get any added 28.475 - information you need. The trade-off is that external hooks 28.476 - are slower than in-process hooks. 28.477 - </para> 28.478 - 28.479 - <para>An in-process Python hook has complete access to the 28.480 - Mercurial API, and does not <quote>shell out</quote> to 28.481 - another process, so it is inherently faster than an external 28.482 - hook. It is also easier to obtain much of the information 28.483 - that a hook requires by using the Mercurial API than by 28.484 - running Mercurial commands. 28.485 - </para> 28.486 - 28.487 - <para>If you are comfortable with Python, or require high 28.488 - performance, writing your hooks in Python may be a good 28.489 - choice. However, when you have a straightforward hook to 28.490 - write and you don't need to care about performance (probably 28.491 - the majority of hooks), a shell script is perfectly fine. 28.492 - </para> 28.493 - 28.494 - </sect2> 28.495 - <sect2 id="sec.hook.param"> 28.496 - <title>Hook parameters</title> 28.497 - 28.498 - <para>Mercurial calls each hook with a set of well-defined 28.499 - parameters. In Python, a parameter is passed as a keyword 28.500 - argument to your hook function. For an external program, a 28.501 - parameter is passed as an environment variable. 28.502 - </para> 28.503 - 28.504 - <para>Whether your hook is written in Python or as a shell 28.505 - script, the hook-specific parameter names and values will be 28.506 - the same. A boolean parameter will be represented as a 28.507 - boolean value in Python, but as the number 1 (for 28.508 - <quote>true</quote>) or 0 (for <quote>false</quote>) as an 28.509 - environment variable for an external hook. If a hook 28.510 - parameter is named <literal>foo</literal>, the keyword 28.511 - argument for a Python hook will also be named 28.512 - <literal>foo</literal>, while the environment variable for an 28.513 - external hook will be named <literal>HG_FOO</literal>. 28.514 - </para> 28.515 - 28.516 - </sect2> 28.517 - <sect2> 28.518 - <title>Hook return values and activity control</title> 28.519 - 28.520 - <para>A hook that executes successfully must exit with a status 28.521 - of zero if external, or return boolean <quote>false</quote> if 28.522 - in-process. Failure is indicated with a non-zero exit status 28.523 - from an external hook, or an in-process hook returning boolean 28.524 - <quote>true</quote>. If an in-process hook raises an 28.525 - exception, the hook is considered to have failed. 28.526 - </para> 28.527 - 28.528 - <para>For a hook that controls whether an activity can proceed, 28.529 - zero/false means <quote>allow</quote>, while 28.530 - non-zero/true/exception means <quote>deny</quote>. 28.531 - </para> 28.532 - 28.533 - </sect2> 28.534 - <sect2> 28.535 - <title>Writing an external hook</title> 28.536 - 28.537 - <para>When you define an external hook in your <filename 28.538 - role="special">~/.hgrc</filename> and the hook is run, its 28.539 - value is passed to your shell, which interprets it. This 28.540 - means that you can use normal shell constructs in the body of 28.541 - the hook. 28.542 - </para> 28.543 - 28.544 - <para>An executable hook is always run with its current 28.545 - directory set to a repository's root directory. 28.546 - </para> 28.547 - 28.548 - <para>Each hook parameter is passed in as an environment 28.549 - variable; the name is upper-cased, and prefixed with the 28.550 - string <quote><literal>HG_</literal></quote>. 28.551 - </para> 28.552 - 28.553 - <para>With the exception of hook parameters, Mercurial does not 28.554 - set or modify any environment variables when running a hook. 28.555 - This is useful to remember if you are writing a site-wide hook 28.556 - that may be run by a number of different users with differing 28.557 - environment variables set. In multi-user situations, you 28.558 - should not rely on environment variables being set to the 28.559 - values you have in your environment when testing the hook. 28.560 - </para> 28.561 - 28.562 - </sect2> 28.563 - <sect2> 28.564 - <title>Telling Mercurial to use an in-process hook</title> 28.565 - 28.566 - <para>The <filename role="special">~/.hgrc</filename> syntax 28.567 - for defining an in-process hook is slightly different than for 28.568 - an executable hook. The value of the hook must start with the 28.569 - text <quote><literal>python:</literal></quote>, and continue 28.570 - with the fully-qualified name of a callable object to use as 28.571 - the hook's value. 28.572 - </para> 28.573 - 28.574 - <para>The module in which a hook lives is automatically imported 28.575 - when a hook is run. So long as you have the module name and 28.576 - <envar>PYTHONPATH</envar> right, it should <quote>just 28.577 - work</quote>. 28.578 - </para> 28.579 - 28.580 - <para>The following <filename role="special">~/.hgrc</filename> 28.581 - example snippet illustrates the syntax and meaning of the 28.582 - notions we just described. 28.583 - </para> 28.584 - <programlisting>[hooks] 28.585 -commit.example = python:mymodule.submodule.myhook</programlisting> 28.586 - <para>When Mercurial runs the <literal>commit.example</literal> 28.587 - hook, it imports <literal>mymodule.submodule</literal>, looks 28.588 - for the callable object named <literal>myhook</literal>, and 28.589 - calls it. 28.590 - </para> 28.591 - 28.592 - </sect2> 28.593 - <sect2> 28.594 - <title>Writing an in-process hook</title> 28.595 - 28.596 - <para>The simplest in-process hook does nothing, but illustrates 28.597 - the basic shape of the hook API: 28.598 - </para> 28.599 - <programlisting>def myhook(ui, repo, **kwargs): 28.600 - pass</programlisting> 28.601 - <para>The first argument to a Python hook is always a <literal 28.602 - role="py-mod-mercurial.ui">ui</literal> object. The second 28.603 - is a repository object; at the moment, it is always an 28.604 - instance of <literal 28.605 - role="py-mod-mercurial.localrepo">localrepository</literal>. 28.606 - Following these two arguments are other keyword arguments. 28.607 - Which ones are passed in depends on the hook being called, but 28.608 - a hook can ignore arguments it doesn't care about by dropping 28.609 - them into a keyword argument dict, as with 28.610 - <literal>**kwargs</literal> above. 28.611 - </para> 28.612 - 28.613 - </sect2> 28.614 - </sect1> 28.615 - <sect1> 28.616 - <title>Some hook examples</title> 28.617 - 28.618 - <sect2> 28.619 - <title>Writing meaningful commit messages</title> 28.620 - 28.621 - <para>It's hard to imagine a useful commit message being very 28.622 - short. The simple <literal role="hook">pretxncommit</literal> 28.623 - hook of the example below will prevent you from committing a 28.624 - changeset with a message that is less than ten bytes long. 28.625 - </para> 28.626 - 28.627 -&interaction.hook.msglen.go; 28.628 - 28.629 - </sect2> 28.630 - <sect2> 28.631 - <title>Checking for trailing whitespace</title> 28.632 - 28.633 - <para>An interesting use of a commit-related hook is to help you 28.634 - to write cleaner code. A simple example of <quote>cleaner 28.635 - code</quote> is the dictum that a change should not add any 28.636 - new lines of text that contain <quote>trailing 28.637 - whitespace</quote>. Trailing whitespace is a series of 28.638 - space and tab characters at the end of a line of text. In 28.639 - most cases, trailing whitespace is unnecessary, invisible 28.640 - noise, but it is occasionally problematic, and people often 28.641 - prefer to get rid of it. 28.642 - </para> 28.643 - 28.644 - <para>You can use either the <literal 28.645 - role="hook">precommit</literal> or <literal 28.646 - role="hook">pretxncommit</literal> hook to tell whether you 28.647 - have a trailing whitespace problem. If you use the <literal 28.648 - role="hook">precommit</literal> hook, the hook will not know 28.649 - which files you are committing, so it will have to check every 28.650 - modified file in the repository for trailing white space. If 28.651 - you want to commit a change to just the file 28.652 - <filename>foo</filename>, but the file 28.653 - <filename>bar</filename> contains trailing whitespace, doing a 28.654 - check in the <literal role="hook">precommit</literal> hook 28.655 - will prevent you from committing <filename>foo</filename> due 28.656 - to the problem with <filename>bar</filename>. This doesn't 28.657 - seem right. 28.658 - </para> 28.659 - 28.660 - <para>Should you choose the <literal 28.661 - role="hook">pretxncommit</literal> hook, the check won't 28.662 - occur until just before the transaction for the commit 28.663 - completes. This will allow you to check for problems only the 28.664 - exact files that are being committed. However, if you entered 28.665 - the commit message interactively and the hook fails, the 28.666 - transaction will roll back; you'll have to re-enter the commit 28.667 - message after you fix the trailing whitespace and run <command 28.668 - role="hg-cmd">hg commit</command> again. 28.669 - </para> 28.670 - 28.671 -&interaction.hook.ws.simple; 28.672 - 28.673 - <para>In this example, we introduce a simple <literal 28.674 - role="hook">pretxncommit</literal> hook that checks for 28.675 - trailing whitespace. This hook is short, but not very 28.676 - helpful. It exits with an error status if a change adds a 28.677 - line with trailing whitespace to any file, but does not print 28.678 - any information that might help us to identify the offending 28.679 - file or line. It also has the nice property of not paying 28.680 - attention to unmodified lines; only lines that introduce new 28.681 - trailing whitespace cause problems. 28.682 - </para> 28.683 - 28.684 - <para>The above version is much more complex, but also more 28.685 - useful. It parses a unified diff to see if any lines add 28.686 - trailing whitespace, and prints the name of the file and the 28.687 - line number of each such occurrence. Even better, if the 28.688 - change adds trailing whitespace, this hook saves the commit 28.689 - comment and prints the name of the save file before exiting 28.690 - and telling Mercurial to roll the transaction back, so you can 28.691 - use the <option role="hg-opt-commit">-l filename</option> 28.692 - option to <command role="hg-cmd">hg commit</command> to reuse 28.693 - the saved commit message once you've corrected the problem. 28.694 - </para> 28.695 - 28.696 -&interaction.hook.ws.better; 28.697 - 28.698 - <para>As a final aside, note in the example above the use of 28.699 - <command>perl</command>'s in-place editing feature to get rid 28.700 - of trailing whitespace from a file. This is concise and 28.701 - useful enough that I will reproduce it here. 28.702 - </para> 28.703 - <programlisting>perl -pi -e 's,\s+$,,' filename</programlisting> 28.704 - 28.705 - </sect2> 28.706 - </sect1> 28.707 - <sect1> 28.708 - <title>Bundled hooks</title> 28.709 - 28.710 - <para>Mercurial ships with several bundled hooks. You can find 28.711 - them in the <filename class="directory">hgext</filename> 28.712 - directory of a Mercurial source tree. If you are using a 28.713 - Mercurial binary package, the hooks will be located in the 28.714 - <filename class="directory">hgext</filename> directory of 28.715 - wherever your package installer put Mercurial. 28.716 - </para> 28.717 - 28.718 - <sect2> 28.719 - <title><literal role="hg-ext">acl</literal>&emdash;access 28.720 - control for parts of a repository</title> 28.721 - 28.722 - <para>The <literal role="hg-ext">acl</literal> extension lets 28.723 - you control which remote users are allowed to push changesets 28.724 - to a networked server. You can protect any portion of a 28.725 - repository (including the entire repo), so that a specific 28.726 - remote user can push changes that do not affect the protected 28.727 - portion. 28.728 - </para> 28.729 - 28.730 - <para>This extension implements access control based on the 28.731 - identity of the user performing a push, 28.732 - <emphasis>not</emphasis> on who committed the changesets 28.733 - they're pushing. It makes sense to use this hook only if you 28.734 - have a locked-down server environment that authenticates 28.735 - remote users, and you want to be sure that only specific users 28.736 - are allowed to push changes to that server. 28.737 - </para> 28.738 - 28.739 - <sect3> 28.740 - <title>Configuring the <literal role="hook">acl</literal> 28.741 - hook</title> 28.742 - 28.743 - <para>In order to manage incoming changesets, the <literal 28.744 - role="hg-ext">acl</literal> hook must be used as a 28.745 - <literal role="hook">pretxnchangegroup</literal> hook. This 28.746 - lets it see which files are modified by each incoming 28.747 - changeset, and roll back a group of changesets if they 28.748 - modify <quote>forbidden</quote> files. Example: 28.749 - </para> 28.750 - <programlisting>[hooks] 28.751 -pretxnchangegroup.acl = python:hgext.acl.hook</programlisting> 28.752 - 28.753 - <para>The <literal role="hg-ext">acl</literal> extension is 28.754 - configured using three sections. 28.755 - </para> 28.756 - 28.757 - <para>The <literal role="rc-acl">acl</literal> section has 28.758 - only one entry, <envar role="rc-item-acl">sources</envar>, 28.759 - which lists the sources of incoming changesets that the hook 28.760 - should pay attention to. You don't normally need to 28.761 - configure this section. 28.762 - </para> 28.763 - <itemizedlist> 28.764 - <listitem><para><envar role="rc-item-acl">serve</envar>: 28.765 - Control incoming changesets that are arriving from a 28.766 - remote repository over http or ssh. This is the default 28.767 - value of <envar role="rc-item-acl">sources</envar>, and 28.768 - usually the only setting you'll need for this 28.769 - configuration item. 28.770 - </para> 28.771 - </listitem> 28.772 - <listitem><para><envar role="rc-item-acl">pull</envar>: 28.773 - Control incoming changesets that are arriving via a pull 28.774 - from a local repository. 28.775 - </para> 28.776 - </listitem> 28.777 - <listitem><para><envar role="rc-item-acl">push</envar>: 28.778 - Control incoming changesets that are arriving via a push 28.779 - from a local repository. 28.780 - </para> 28.781 - </listitem> 28.782 - <listitem><para><envar role="rc-item-acl">bundle</envar>: 28.783 - Control incoming changesets that are arriving from 28.784 - another repository via a bundle. 28.785 - </para> 28.786 - </listitem></itemizedlist> 28.787 - 28.788 - <para>The <literal role="rc-acl.allow">acl.allow</literal> 28.789 - section controls the users that are allowed to add 28.790 - changesets to the repository. If this section is not 28.791 - present, all users that are not explicitly denied are 28.792 - allowed. If this section is present, all users that are not 28.793 - explicitly allowed are denied (so an empty section means 28.794 - that all users are denied). 28.795 - </para> 28.796 - 28.797 - <para>The <literal role="rc-acl.deny">acl.deny</literal> 28.798 - section determines which users are denied from adding 28.799 - changesets to the repository. If this section is not 28.800 - present or is empty, no users are denied. 28.801 - </para> 28.802 - 28.803 - <para>The syntaxes for the <literal 28.804 - role="rc-acl.allow">acl.allow</literal> and <literal 28.805 - role="rc-acl.deny">acl.deny</literal> sections are 28.806 - identical. On the left of each entry is a glob pattern that 28.807 - matches files or directories, relative to the root of the 28.808 - repository; on the right, a user name. 28.809 - </para> 28.810 - 28.811 - <para>In the following example, the user 28.812 - <literal>docwriter</literal> can only push changes to the 28.813 - <filename class="directory">docs</filename> subtree of the 28.814 - repository, while <literal>intern</literal> can push changes 28.815 - to any file or directory except <filename 28.816 - class="directory">source/sensitive</filename>. 28.817 - </para> 28.818 - <programlisting>[acl.allow] 28.819 -docs/** = docwriter 28.820 -[acl.deny] 28.821 -source/sensitive/** = intern</programlisting> 28.822 - 28.823 - </sect3> 28.824 - <sect3> 28.825 - <title>Testing and troubleshooting</title> 28.826 - 28.827 - <para>If you want to test the <literal 28.828 - role="hg-ext">acl</literal> hook, run it with Mercurial's 28.829 - debugging output enabled. Since you'll probably be running 28.830 - it on a server where it's not convenient (or sometimes 28.831 - possible) to pass in the <option 28.832 - role="hg-opt-global">--debug</option> option, don't forget 28.833 - that you can enable debugging output in your <filename 28.834 - role="special">~/.hgrc</filename>: 28.835 - </para> 28.836 - <programlisting>[ui] 28.837 -debug = true</programlisting> 28.838 - <para>With this enabled, the <literal 28.839 - role="hg-ext">acl</literal> hook will print enough 28.840 - information to let you figure out why it is allowing or 28.841 - forbidding pushes from specific users. 28.842 - </para> 28.843 - 28.844 - </sect3> 28.845 - </sect2> 28.846 - <sect2> 28.847 - <title><literal 28.848 - role="hg-ext">bugzilla</literal>&emdash;integration with 28.849 - Bugzilla</title> 28.850 - 28.851 - <para>The <literal role="hg-ext">bugzilla</literal> extension 28.852 - adds a comment to a Bugzilla bug whenever it finds a reference 28.853 - to that bug ID in a commit comment. You can install this hook 28.854 - on a shared server, so that any time a remote user pushes 28.855 - changes to this server, the hook gets run. 28.856 - </para> 28.857 - 28.858 - <para>It adds a comment to the bug that looks like this (you can 28.859 - configure the contents of the comment&emdash;see below): 28.860 - </para> 28.861 - <programlisting>Changeset aad8b264143a, made by Joe User 28.862 - <joe.user@domain.com> in the frobnitz repository, refers 28.863 - to this bug. For complete details, see 28.864 - http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 28.865 - Changeset description: Fix bug 10483 by guarding against some 28.866 - NULL pointers</programlisting> 28.867 - <para>The value of this hook is that it automates the process of 28.868 - updating a bug any time a changeset refers to it. If you 28.869 - configure the hook properly, it makes it easy for people to 28.870 - browse straight from a Bugzilla bug to a changeset that refers 28.871 - to that bug. 28.872 - </para> 28.873 - 28.874 - <para>You can use the code in this hook as a starting point for 28.875 - some more exotic Bugzilla integration recipes. Here are a few 28.876 - possibilities: 28.877 - </para> 28.878 - <itemizedlist> 28.879 - <listitem><para>Require that every changeset pushed to the 28.880 - server have a valid bug ID in its commit comment. In this 28.881 - case, you'd want to configure the hook as a <literal 28.882 - role="hook">pretxncommit</literal> hook. This would 28.883 - allow the hook to reject changes that didn't contain bug 28.884 - IDs. 28.885 - </para> 28.886 - </listitem> 28.887 - <listitem><para>Allow incoming changesets to automatically 28.888 - modify the <emphasis>state</emphasis> of a bug, as well as 28.889 - simply adding a comment. For example, the hook could 28.890 - recognise the string <quote>fixed bug 31337</quote> as 28.891 - indicating that it should update the state of bug 31337 to 28.892 - <quote>requires testing</quote>. 28.893 - </para> 28.894 - </listitem></itemizedlist> 28.895 - 28.896 - <sect3 id="sec.hook.bugzilla.config"> 28.897 - <title>Configuring the <literal role="hook">bugzilla</literal> 28.898 - hook</title> 28.899 - 28.900 - <para>You should configure this hook in your server's 28.901 - <filename role="special">~/.hgrc</filename> as an <literal 28.902 - role="hook">incoming</literal> hook, for example as 28.903 - follows: 28.904 - </para> 28.905 - <programlisting>[hooks] 28.906 -incoming.bugzilla = python:hgext.bugzilla.hook</programlisting> 28.907 - 28.908 - <para>Because of the specialised nature of this hook, and 28.909 - because Bugzilla was not written with this kind of 28.910 - integration in mind, configuring this hook is a somewhat 28.911 - involved process. 28.912 - </para> 28.913 - 28.914 - <para>Before you begin, you must install the MySQL bindings 28.915 - for Python on the host(s) where you'll be running the hook. 28.916 - If this is not available as a binary package for your 28.917 - system, you can download it from 28.918 - <citation>web:mysql-python</citation>. 28.919 - </para> 28.920 - 28.921 - <para>Configuration information for this hook lives in the 28.922 - <literal role="rc-bugzilla">bugzilla</literal> section of 28.923 - your <filename role="special">~/.hgrc</filename>. 28.924 - </para> 28.925 - <itemizedlist> 28.926 - <listitem><para><envar 28.927 - role="rc-item-bugzilla">version</envar>: The version 28.928 - of Bugzilla installed on the server. The database 28.929 - schema that Bugzilla uses changes occasionally, so this 28.930 - hook has to know exactly which schema to use. At the 28.931 - moment, the only version supported is 28.932 - <literal>2.16</literal>. 28.933 - </para> 28.934 - </listitem> 28.935 - <listitem><para><envar role="rc-item-bugzilla">host</envar>: 28.936 - The hostname of the MySQL server that stores your 28.937 - Bugzilla data. The database must be configured to allow 28.938 - connections from whatever host you are running the 28.939 - <literal role="hook">bugzilla</literal> hook on. 28.940 - </para> 28.941 - </listitem> 28.942 - <listitem><para><envar role="rc-item-bugzilla">user</envar>: 28.943 - The username with which to connect to the MySQL server. 28.944 - The database must be configured to allow this user to 28.945 - connect from whatever host you are running the <literal 28.946 - role="hook">bugzilla</literal> hook on. This user 28.947 - must be able to access and modify Bugzilla tables. The 28.948 - default value of this item is <literal>bugs</literal>, 28.949 - which is the standard name of the Bugzilla user in a 28.950 - MySQL database. 28.951 - </para> 28.952 - </listitem> 28.953 - <listitem><para><envar 28.954 - role="rc-item-bugzilla">password</envar>: The MySQL 28.955 - password for the user you configured above. This is 28.956 - stored as plain text, so you should make sure that 28.957 - unauthorised users cannot read the <filename 28.958 - role="special">~/.hgrc</filename> file where you 28.959 - store this information. 28.960 - </para> 28.961 - </listitem> 28.962 - <listitem><para><envar role="rc-item-bugzilla">db</envar>: 28.963 - The name of the Bugzilla database on the MySQL server. 28.964 - The default value of this item is 28.965 - <literal>bugs</literal>, which is the standard name of 28.966 - the MySQL database where Bugzilla stores its data. 28.967 - </para> 28.968 - </listitem> 28.969 - <listitem><para><envar 28.970 - role="rc-item-bugzilla">notify</envar>: If you want 28.971 - Bugzilla to send out a notification email to subscribers 28.972 - after this hook has added a comment to a bug, you will 28.973 - need this hook to run a command whenever it updates the 28.974 - database. The command to run depends on where you have 28.975 - installed Bugzilla, but it will typically look something 28.976 - like this, if you have Bugzilla installed in <filename 28.977 - class="directory">/var/www/html/bugzilla</filename>: 28.978 - </para> 28.979 - <programlisting>cd /var/www/html/bugzilla && 28.980 - ./processmail %s nobody@nowhere.com</programlisting> 28.981 - </listitem> 28.982 - <listitem><para> The Bugzilla 28.983 - <literal>processmail</literal> program expects to be 28.984 - given a bug ID (the hook replaces 28.985 - <quote><literal>%s</literal></quote> with the bug ID) 28.986 - and an email address. It also expects to be able to 28.987 - write to some files in the directory that it runs in. 28.988 - If Bugzilla and this hook are not installed on the same 28.989 - machine, you will need to find a way to run 28.990 - <literal>processmail</literal> on the server where 28.991 - Bugzilla is installed. 28.992 - </para> 28.993 - </listitem></itemizedlist> 28.994 - 28.995 - </sect3> 28.996 - <sect3> 28.997 - <title>Mapping committer names to Bugzilla user names</title> 28.998 - 28.999 - <para>By default, the <literal 28.1000 - role="hg-ext">bugzilla</literal> hook tries to use the 28.1001 - email address of a changeset's committer as the Bugzilla 28.1002 - user name with which to update a bug. If this does not suit 28.1003 - your needs, you can map committer email addresses to 28.1004 - Bugzilla user names using a <literal 28.1005 - role="rc-usermap">usermap</literal> section. 28.1006 - </para> 28.1007 - 28.1008 - <para>Each item in the <literal 28.1009 - role="rc-usermap">usermap</literal> section contains an 28.1010 - email address on the left, and a Bugzilla user name on the 28.1011 - right. 28.1012 - </para> 28.1013 - <programlisting>[usermap] 28.1014 -jane.user@example.com = jane</programlisting> 28.1015 - <para>You can either keep the <literal 28.1016 - role="rc-usermap">usermap</literal> data in a normal 28.1017 - <filename role="special">~/.hgrc</filename>, or tell the 28.1018 - <literal role="hg-ext">bugzilla</literal> hook to read the 28.1019 - information from an external <filename>usermap</filename> 28.1020 - file. In the latter case, you can store 28.1021 - <filename>usermap</filename> data by itself in (for example) 28.1022 - a user-modifiable repository. This makes it possible to let 28.1023 - your users maintain their own <envar 28.1024 - role="rc-item-bugzilla">usermap</envar> entries. The main 28.1025 - <filename role="special">~/.hgrc</filename> file might look 28.1026 - like this: 28.1027 - </para> 28.1028 - <programlisting># regular hgrc file refers to external usermap file 28.1029 -[bugzilla] 28.1030 -usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting> 28.1031 - <para>While the <filename>usermap</filename> file that it 28.1032 - refers to might look like this: 28.1033 - </para> 28.1034 - <programlisting># bugzilla-usermap.conf - inside a hg repository 28.1035 -[usermap] stephanie@example.com = steph</programlisting> 28.1036 - 28.1037 - </sect3> 28.1038 - <sect3> 28.1039 - <title>Configuring the text that gets added to a bug</title> 28.1040 - 28.1041 - <para>You can configure the text that this hook adds as a 28.1042 - comment; you specify it in the form of a Mercurial template. 28.1043 - Several <filename role="special">~/.hgrc</filename> entries 28.1044 - (still in the <literal role="rc-bugzilla">bugzilla</literal> 28.1045 - section) control this behaviour. 28.1046 - </para> 28.1047 - <itemizedlist> 28.1048 - <listitem><para><literal>strip</literal>: The number of 28.1049 - leading path elements to strip from a repository's path 28.1050 - name to construct a partial path for a URL. For example, 28.1051 - if the repositories on your server live under <filename 28.1052 - class="directory">/home/hg/repos</filename>, and you 28.1053 - have a repository whose path is <filename 28.1054 - class="directory">/home/hg/repos/app/tests</filename>, 28.1055 - then setting <literal>strip</literal> to 28.1056 - <literal>4</literal> will give a partial path of 28.1057 - <filename class="directory">app/tests</filename>. The 28.1058 - hook will make this partial path available when 28.1059 - expanding a template, as <literal>webroot</literal>. 28.1060 - </para> 28.1061 - </listitem> 28.1062 - <listitem><para><literal>template</literal>: The text of the 28.1063 - template to use. In addition to the usual 28.1064 - changeset-related variables, this template can use 28.1065 - <literal>hgweb</literal> (the value of the 28.1066 - <literal>hgweb</literal> configuration item above) and 28.1067 - <literal>webroot</literal> (the path constructed using 28.1068 - <literal>strip</literal> above). 28.1069 - </para> 28.1070 - </listitem></itemizedlist> 28.1071 - 28.1072 - <para>In addition, you can add a <envar 28.1073 - role="rc-item-web">baseurl</envar> item to the <literal 28.1074 - role="rc-web">web</literal> section of your <filename 28.1075 - role="special">~/.hgrc</filename>. The <literal 28.1076 - role="hg-ext">bugzilla</literal> hook will make this 28.1077 - available when expanding a template, as the base string to 28.1078 - use when constructing a URL that will let users browse from 28.1079 - a Bugzilla comment to view a changeset. Example: 28.1080 - </para> 28.1081 - <programlisting>[web] 28.1082 -baseurl = http://hg.domain.com/</programlisting> 28.1083 - 28.1084 - <para>Here is an example set of <literal 28.1085 - role="hg-ext">bugzilla</literal> hook config information. 28.1086 - </para> 28.1087 - 28.1088 - <programlisting>&ch10-bugzilla-config.lst;</programlisting> 28.1089 - 28.1090 - </sect3> 28.1091 - <sect3> 28.1092 - <title>Testing and troubleshooting</title> 28.1093 - 28.1094 - <para>The most common problems with configuring the <literal 28.1095 - role="hg-ext">bugzilla</literal> hook relate to running 28.1096 - Bugzilla's <filename>processmail</filename> script and 28.1097 - mapping committer names to user names. 28.1098 - </para> 28.1099 - 28.1100 - <para>Recall from section <xref 28.1101 - linkend="sec.hook.bugzilla.config"/> above that the user 28.1102 - that runs the Mercurial process on the server is also the 28.1103 - one that will run the <filename>processmail</filename> 28.1104 - script. The <filename>processmail</filename> script 28.1105 - sometimes causes Bugzilla to write to files in its 28.1106 - configuration directory, and Bugzilla's configuration files 28.1107 - are usually owned by the user that your web server runs 28.1108 - under. 28.1109 - </para> 28.1110 - 28.1111 - <para>You can cause <filename>processmail</filename> to be run 28.1112 - with the suitable user's identity using the 28.1113 - <command>sudo</command> command. Here is an example entry 28.1114 - for a <filename>sudoers</filename> file. 28.1115 - </para> 28.1116 - <programlisting>hg_user = (httpd_user) 28.1117 -NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting> 28.1118 - <para>This allows the <literal>hg_user</literal> user to run a 28.1119 - <filename>processmail-wrapper</filename> program under the 28.1120 - identity of <literal>httpd_user</literal>. 28.1121 - </para> 28.1122 - 28.1123 - <para>This indirection through a wrapper script is necessary, 28.1124 - because <filename>processmail</filename> expects to be run 28.1125 - with its current directory set to wherever you installed 28.1126 - Bugzilla; you can't specify that kind of constraint in a 28.1127 - <filename>sudoers</filename> file. The contents of the 28.1128 - wrapper script are simple: 28.1129 - </para> 28.1130 - <programlisting>#!/bin/sh 28.1131 -cd `dirname $0` && ./processmail "$1" nobody@example.com</programlisting> 28.1132 - <para>It doesn't seem to matter what email address you pass to 28.1133 - <filename>processmail</filename>. 28.1134 - </para> 28.1135 - 28.1136 - <para>If your <literal role="rc-usermap">usermap</literal> is 28.1137 - not set up correctly, users will see an error message from 28.1138 - the <literal role="hg-ext">bugzilla</literal> hook when they 28.1139 - push changes to the server. The error message will look 28.1140 - like this: 28.1141 - </para> 28.1142 - <programlisting>cannot find bugzilla user id for john.q.public@example.com</programlisting> 28.1143 - <para>What this means is that the committer's address, 28.1144 - <literal>john.q.public@example.com</literal>, is not a valid 28.1145 - Bugzilla user name, nor does it have an entry in your 28.1146 - <literal role="rc-usermap">usermap</literal> that maps it to 28.1147 - a valid Bugzilla user name. 28.1148 - </para> 28.1149 - 28.1150 - </sect3> 28.1151 - </sect2> 28.1152 - <sect2> 28.1153 - <title><literal role="hg-ext">notify</literal>&emdash;send email 28.1154 - notifications</title> 28.1155 - 28.1156 - <para>Although Mercurial's built-in web server provides RSS 28.1157 - feeds of changes in every repository, many people prefer to 28.1158 - receive change notifications via email. The <literal 28.1159 - role="hg-ext">notify</literal> hook lets you send out 28.1160 - notifications to a set of email addresses whenever changesets 28.1161 - arrive that those subscribers are interested in. 28.1162 - </para> 28.1163 - 28.1164 - <para>As with the <literal role="hg-ext">bugzilla</literal> 28.1165 - hook, the <literal role="hg-ext">notify</literal> hook is 28.1166 - template-driven, so you can customise the contents of the 28.1167 - notification messages that it sends. 28.1168 - </para> 28.1169 - 28.1170 - <para>By default, the <literal role="hg-ext">notify</literal> 28.1171 - hook includes a diff of every changeset that it sends out; you 28.1172 - can limit the size of the diff, or turn this feature off 28.1173 - entirely. It is useful for letting subscribers review changes 28.1174 - immediately, rather than clicking to follow a URL. 28.1175 - </para> 28.1176 - 28.1177 - <sect3> 28.1178 - <title>Configuring the <literal role="hg-ext">notify</literal> 28.1179 - hook</title> 28.1180 - 28.1181 - <para>You can set up the <literal 28.1182 - role="hg-ext">notify</literal> hook to send one email 28.1183 - message per incoming changeset, or one per incoming group of 28.1184 - changesets (all those that arrived in a single pull or 28.1185 - push). 28.1186 - </para> 28.1187 - <programlisting>[hooks] 28.1188 -# send one email per group of changes 28.1189 -changegroup.notify = python:hgext.notify.hook 28.1190 -# send one email per change 28.1191 -incoming.notify = python:hgext.notify.hook</programlisting> 28.1192 - 28.1193 - <para>Configuration information for this hook lives in the 28.1194 - <literal role="rc-notify">notify</literal> section of a 28.1195 - <filename role="special">~/.hgrc</filename> file. 28.1196 - </para> 28.1197 - <itemizedlist> 28.1198 - <listitem><para><envar role="rc-item-notify">test</envar>: 28.1199 - By default, this hook does not send out email at all; 28.1200 - instead, it prints the message that it 28.1201 - <emphasis>would</emphasis> send. Set this item to 28.1202 - <literal>false</literal> to allow email to be sent. The 28.1203 - reason that sending of email is turned off by default is 28.1204 - that it takes several tries to configure this extension 28.1205 - exactly as you would like, and it would be bad form to 28.1206 - spam subscribers with a number of <quote>broken</quote> 28.1207 - notifications while you debug your configuration. 28.1208 - </para> 28.1209 - </listitem> 28.1210 - <listitem><para><envar role="rc-item-notify">config</envar>: 28.1211 - The path to a configuration file that contains 28.1212 - subscription information. This is kept separate from 28.1213 - the main <filename role="special">~/.hgrc</filename> so 28.1214 - that you can maintain it in a repository of its own. 28.1215 - People can then clone that repository, update their 28.1216 - subscriptions, and push the changes back to your server. 28.1217 - </para> 28.1218 - </listitem> 28.1219 - <listitem><para><envar role="rc-item-notify">strip</envar>: 28.1220 - The number of leading path separator characters to strip 28.1221 - from a repository's path, when deciding whether a 28.1222 - repository has subscribers. For example, if the 28.1223 - repositories on your server live in <filename 28.1224 - class="directory">/home/hg/repos</filename>, and 28.1225 - <literal role="hg-ext">notify</literal> is considering a 28.1226 - repository named <filename 28.1227 - class="directory">/home/hg/repos/shared/test</filename>, 28.1228 - setting <envar role="rc-item-notify">strip</envar> to 28.1229 - <literal>4</literal> will cause <literal 28.1230 - role="hg-ext">notify</literal> to trim the path it 28.1231 - considers down to <filename 28.1232 - class="directory">shared/test</filename>, and it will 28.1233 - match subscribers against that. 28.1234 - </para> 28.1235 - </listitem> 28.1236 - <listitem><para><envar 28.1237 - role="rc-item-notify">template</envar>: The template 28.1238 - text to use when sending messages. This specifies both 28.1239 - the contents of the message header and its body. 28.1240 - </para> 28.1241 - </listitem> 28.1242 - <listitem><para><envar 28.1243 - role="rc-item-notify">maxdiff</envar>: The maximum 28.1244 - number of lines of diff data to append to the end of a 28.1245 - message. If a diff is longer than this, it is 28.1246 - truncated. By default, this is set to 300. Set this to 28.1247 - <literal>0</literal> to omit diffs from notification 28.1248 - emails. 28.1249 - </para> 28.1250 - </listitem> 28.1251 - <listitem><para><envar 28.1252 - role="rc-item-notify">sources</envar>: A list of 28.1253 - sources of changesets to consider. This lets you limit 28.1254 - <literal role="hg-ext">notify</literal> to only sending 28.1255 - out email about changes that remote users pushed into 28.1256 - this repository via a server, for example. See section 28.1257 - <xref 28.1258 - linkend="sec.hook.sources"/> for the sources you can 28.1259 - specify here. 28.1260 - </para> 28.1261 - </listitem></itemizedlist> 28.1262 - 28.1263 - <para>If you set the <envar role="rc-item-web">baseurl</envar> 28.1264 - item in the <literal role="rc-web">web</literal> section, 28.1265 - you can use it in a template; it will be available as 28.1266 - <literal>webroot</literal>. 28.1267 - </para> 28.1268 - 28.1269 - <para>Here is an example set of <literal 28.1270 - role="hg-ext">notify</literal> configuration information. 28.1271 - </para> 28.1272 - 28.1273 - <programlisting>&ch10-notify-config.lst;</programlisting> 28.1274 - 28.1275 - <para>This will produce a message that looks like the 28.1276 - following: 28.1277 - </para> 28.1278 - 28.1279 - <programlisting>&ch10-notify-config-mail.lst;</programlisting> 28.1280 - 28.1281 - </sect3> 28.1282 - <sect3> 28.1283 - <title>Testing and troubleshooting</title> 28.1284 - 28.1285 - <para>Do not forget that by default, the <literal 28.1286 - role="hg-ext">notify</literal> extension <emphasis>will not 28.1287 - send any mail</emphasis> until you explicitly configure it to do so, 28.1288 - by setting <envar role="rc-item-notify">test</envar> to 28.1289 - <literal>false</literal>. Until you do that, it simply 28.1290 - prints the message it <emphasis>would</emphasis> send. 28.1291 - </para> 28.1292 - 28.1293 - </sect3> 28.1294 - </sect2> 28.1295 - </sect1> 28.1296 - <sect1 id="sec.hook.ref"> 28.1297 - <title>Information for writers of hooks</title> 28.1298 - 28.1299 - <sect2> 28.1300 - <title>In-process hook execution</title> 28.1301 - 28.1302 - <para>An in-process hook is called with arguments of the 28.1303 - following form: 28.1304 - </para> 28.1305 - <programlisting>def myhook(ui, repo, **kwargs): pass</programlisting> 28.1306 - <para>The <literal>ui</literal> parameter is a <literal 28.1307 - role="py-mod-mercurial.ui">ui</literal> object. The 28.1308 - <literal>repo</literal> parameter is a <literal 28.1309 - role="py-mod-mercurial.localrepo">localrepository</literal> 28.1310 - object. The names and values of the 28.1311 - <literal>**kwargs</literal> parameters depend on the hook 28.1312 - being invoked, with the following common features: 28.1313 - </para> 28.1314 - <itemizedlist> 28.1315 - <listitem><para>If a parameter is named 28.1316 - <literal>node</literal> or <literal>parentN</literal>, it 28.1317 - will contain a hexadecimal changeset ID. The empty string 28.1318 - is used to represent <quote>null changeset ID</quote> 28.1319 - instead of a string of zeroes. 28.1320 - </para> 28.1321 - </listitem> 28.1322 - <listitem><para>If a parameter is named 28.1323 - <literal>url</literal>, it will contain the URL of a 28.1324 - remote repository, if that can be determined. 28.1325 - </para> 28.1326 - </listitem> 28.1327 - <listitem><para>Boolean-valued parameters are represented as 28.1328 - Python <literal>bool</literal> objects. 28.1329 - </para> 28.1330 - </listitem></itemizedlist> 28.1331 - 28.1332 - <para>An in-process hook is called without a change to the 28.1333 - process's working directory (unlike external hooks, which are 28.1334 - run in the root of the repository). It must not change the 28.1335 - process's working directory, or it will cause any calls it 28.1336 - makes into the Mercurial API to fail. 28.1337 - </para> 28.1338 - 28.1339 - <para>If a hook returns a boolean <quote>false</quote> value, it 28.1340 - is considered to have succeeded. If it returns a boolean 28.1341 - <quote>true</quote> value or raises an exception, it is 28.1342 - considered to have failed. A useful way to think of the 28.1343 - calling convention is <quote>tell me if you fail</quote>. 28.1344 - </para> 28.1345 - 28.1346 - <para>Note that changeset IDs are passed into Python hooks as 28.1347 - hexadecimal strings, not the binary hashes that Mercurial's 28.1348 - APIs normally use. To convert a hash from hex to binary, use 28.1349 - the <literal>bin</literal> function. 28.1350 - </para> 28.1351 - 28.1352 - </sect2> 28.1353 - <sect2> 28.1354 - <title>External hook execution</title> 28.1355 - 28.1356 - <para>An external hook is passed to the shell of the user 28.1357 - running Mercurial. Features of that shell, such as variable 28.1358 - substitution and command redirection, are available. The hook 28.1359 - is run in the root directory of the repository (unlike 28.1360 - in-process hooks, which are run in the same directory that 28.1361 - Mercurial was run in). 28.1362 - </para> 28.1363 - 28.1364 - <para>Hook parameters are passed to the hook as environment 28.1365 - variables. Each environment variable's name is converted in 28.1366 - upper case and prefixed with the string 28.1367 - <quote><literal>HG_</literal></quote>. For example, if the 28.1368 - name of a parameter is <quote><literal>node</literal></quote>, 28.1369 - the name of the environment variable representing that 28.1370 - parameter will be <quote><literal>HG_NODE</literal></quote>. 28.1371 - </para> 28.1372 - 28.1373 - <para>A boolean parameter is represented as the string 28.1374 - <quote><literal>1</literal></quote> for <quote>true</quote>, 28.1375 - <quote><literal>0</literal></quote> for <quote>false</quote>. 28.1376 - If an environment variable is named <envar>HG_NODE</envar>, 28.1377 - <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it 28.1378 - contains a changeset ID represented as a hexadecimal string. 28.1379 - The empty string is used to represent <quote>null changeset 28.1380 - ID</quote> instead of a string of zeroes. If an environment 28.1381 - variable is named <envar>HG_URL</envar>, it will contain the 28.1382 - URL of a remote repository, if that can be determined. 28.1383 - </para> 28.1384 - 28.1385 - <para>If a hook exits with a status of zero, it is considered to 28.1386 - have succeeded. If it exits with a non-zero status, it is 28.1387 - considered to have failed. 28.1388 - </para> 28.1389 - 28.1390 - </sect2> 28.1391 - <sect2> 28.1392 - <title>Finding out where changesets come from</title> 28.1393 - 28.1394 - <para>A hook that involves the transfer of changesets between a 28.1395 - local repository and another may be able to find out 28.1396 - information about the <quote>far side</quote>. Mercurial 28.1397 - knows <emphasis>how</emphasis> changes are being transferred, 28.1398 - and in many cases <emphasis>where</emphasis> they are being 28.1399 - transferred to or from. 28.1400 - </para> 28.1401 - 28.1402 - <sect3 id="sec.hook.sources"> 28.1403 - <title>Sources of changesets</title> 28.1404 - 28.1405 - <para>Mercurial will tell a hook what means are, or were, used 28.1406 - to transfer changesets between repositories. This is 28.1407 - provided by Mercurial in a Python parameter named 28.1408 - <literal>source</literal>, or an environment variable named 28.1409 - <envar>HG_SOURCE</envar>. 28.1410 - </para> 28.1411 - 28.1412 - <itemizedlist> 28.1413 - <listitem><para><literal>serve</literal>: Changesets are 28.1414 - transferred to or from a remote repository over http or 28.1415 - ssh. 28.1416 - </para> 28.1417 - </listitem> 28.1418 - <listitem><para><literal>pull</literal>: Changesets are 28.1419 - being transferred via a pull from one repository into 28.1420 - another. 28.1421 - </para> 28.1422 - </listitem> 28.1423 - <listitem><para><literal>push</literal>: Changesets are 28.1424 - being transferred via a push from one repository into 28.1425 - another. 28.1426 - </para> 28.1427 - </listitem> 28.1428 - <listitem><para><literal>bundle</literal>: Changesets are 28.1429 - being transferred to or from a bundle. 28.1430 - </para> 28.1431 - </listitem></itemizedlist> 28.1432 - 28.1433 - </sect3> 28.1434 - <sect3 id="sec.hook.url"> 28.1435 - <title>Where changes are going&emdash;remote repository 28.1436 - URLs</title> 28.1437 - 28.1438 - <para>When possible, Mercurial will tell a hook the location 28.1439 - of the <quote>far side</quote> of an activity that transfers 28.1440 - changeset data between repositories. This is provided by 28.1441 - Mercurial in a Python parameter named 28.1442 - <literal>url</literal>, or an environment variable named 28.1443 - <envar>HG_URL</envar>. 28.1444 - </para> 28.1445 - 28.1446 - <para>This information is not always known. If a hook is 28.1447 - invoked in a repository that is being served via http or 28.1448 - ssh, Mercurial cannot tell where the remote repository is, 28.1449 - but it may know where the client is connecting from. In 28.1450 - such cases, the URL will take one of the following forms: 28.1451 - </para> 28.1452 - <itemizedlist> 28.1453 - <listitem><para><literal>remote:ssh:1.2.3.4</literal>&emdash;remote 28.1454 - ssh client, at the IP address 28.1455 - <literal>1.2.3.4</literal>. 28.1456 - </para> 28.1457 - </listitem> 28.1458 - <listitem><para><literal>remote:http:1.2.3.4</literal>&emdash;remote 28.1459 - http client, at the IP address 28.1460 - <literal>1.2.3.4</literal>. If the client is using SSL, 28.1461 - this will be of the form 28.1462 - <literal>remote:https:1.2.3.4</literal>. 28.1463 - </para> 28.1464 - </listitem> 28.1465 - <listitem><para>Empty&emdash;no information could be 28.1466 - discovered about the remote client. 28.1467 - </para> 28.1468 - </listitem></itemizedlist> 28.1469 - 28.1470 - </sect3> 28.1471 - </sect2> 28.1472 - </sect1> 28.1473 - <sect1> 28.1474 - <title>Hook reference</title> 28.1475 - 28.1476 - <sect2 id="sec.hook.changegroup"> 28.1477 - <title><literal role="hook">changegroup</literal>&emdash;after 28.1478 - remote changesets added</title> 28.1479 - 28.1480 - <para>This hook is run after a group of pre-existing changesets 28.1481 - has been added to the repository, for example via a <command 28.1482 - role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg 28.1483 - unbundle</command>. This hook is run once per operation 28.1484 - that added one or more changesets. This is in contrast to the 28.1485 - <literal role="hook">incoming</literal> hook, which is run 28.1486 - once per changeset, regardless of whether the changesets 28.1487 - arrive in a group. 28.1488 - </para> 28.1489 - 28.1490 - <para>Some possible uses for this hook include kicking off an 28.1491 - automated build or test of the added changesets, updating a 28.1492 - bug database, or notifying subscribers that a repository 28.1493 - contains new changes. 28.1494 - </para> 28.1495 - 28.1496 - <para>Parameters to this hook: 28.1497 - </para> 28.1498 - <itemizedlist> 28.1499 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1500 - changeset ID of the first changeset in the group that was 28.1501 - added. All changesets between this and 28.1502 - <literal role="tag">tip</literal>, inclusive, were added by a single 28.1503 - <command role="hg-cmd">hg pull</command>, <command 28.1504 - role="hg-cmd">hg push</command> or <command 28.1505 - role="hg-cmd">hg unbundle</command>. 28.1506 - </para> 28.1507 - </listitem> 28.1508 - <listitem><para><literal>source</literal>: A string. The 28.1509 - source of these changes. See section <xref 28.1510 - linkend="sec.hook.sources"/> for details. 28.1511 - </para> 28.1512 - </listitem> 28.1513 - <listitem><para><literal>url</literal>: A URL. The location 28.1514 - of the remote repository, if known. See section <xref 28.1515 - linkend="sec.hook.url"/> for more 28.1516 - information. 28.1517 - </para> 28.1518 - </listitem></itemizedlist> 28.1519 - 28.1520 - <para>See also: <literal role="hook">incoming</literal> (section 28.1521 - <xref linkend="sec.hook.incoming"/>), <literal 28.1522 - role="hook">prechangegroup</literal> (section <xref 28.1523 - linkend="sec.hook.prechangegroup"/>), <literal 28.1524 - role="hook">pretxnchangegroup</literal> (section <xref 28.1525 - linkend="sec.hook.pretxnchangegroup"/>) 28.1526 - </para> 28.1527 - 28.1528 - </sect2> 28.1529 - <sect2 id="sec.hook.commit"> 28.1530 - <title><literal role="hook">commit</literal>&emdash;after a new 28.1531 - changeset is created</title> 28.1532 - 28.1533 - <para>This hook is run after a new changeset has been created. 28.1534 - </para> 28.1535 - 28.1536 - <para>Parameters to this hook: 28.1537 - </para> 28.1538 - <itemizedlist> 28.1539 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1540 - changeset ID of the newly committed changeset. 28.1541 - </para> 28.1542 - </listitem> 28.1543 - <listitem><para><literal>parent1</literal>: A changeset ID. 28.1544 - The changeset ID of the first parent of the newly 28.1545 - committed changeset. 28.1546 - </para> 28.1547 - </listitem> 28.1548 - <listitem><para><literal>parent2</literal>: A changeset ID. 28.1549 - The changeset ID of the second parent of the newly 28.1550 - committed changeset. 28.1551 - </para> 28.1552 - </listitem></itemizedlist> 28.1553 - 28.1554 - <para>See also: <literal role="hook">precommit</literal> 28.1555 - (section <xref linkend="sec.hook.precommit"/>), <literal 28.1556 - role="hook">pretxncommit</literal> (section <xref 28.1557 - linkend="sec.hook.pretxncommit"/>) 28.1558 - </para> 28.1559 - 28.1560 - </sect2> 28.1561 - <sect2 id="sec.hook.incoming"> 28.1562 - <title><literal role="hook">incoming</literal>&emdash;after one 28.1563 - remote changeset is added</title> 28.1564 - 28.1565 - <para>This hook is run after a pre-existing changeset has been 28.1566 - added to the repository, for example via a <command 28.1567 - role="hg-cmd">hg push</command>. If a group of changesets 28.1568 - was added in a single operation, this hook is called once for 28.1569 - each added changeset. 28.1570 - </para> 28.1571 - 28.1572 - <para>You can use this hook for the same purposes as the 28.1573 - <literal role="hook">changegroup</literal> hook (section <xref 28.1574 - linkend="sec.hook.changegroup"/>); it's simply 28.1575 - more convenient sometimes to run a hook once per group of 28.1576 - changesets, while other times it's handier once per changeset. 28.1577 - </para> 28.1578 - 28.1579 - <para>Parameters to this hook: 28.1580 - </para> 28.1581 - <itemizedlist> 28.1582 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1583 - ID of the newly added changeset. 28.1584 - </para> 28.1585 - </listitem> 28.1586 - <listitem><para><literal>source</literal>: A string. The 28.1587 - source of these changes. See section <xref 28.1588 - linkend="sec.hook.sources"/> for details. 28.1589 - </para> 28.1590 - </listitem> 28.1591 - <listitem><para><literal>url</literal>: A URL. The location 28.1592 - of the remote repository, if known. See section <xref 28.1593 - linkend="sec.hook.url"/> for more 28.1594 - information. 28.1595 - </para> 28.1596 - </listitem></itemizedlist> 28.1597 - 28.1598 - <para>See also: <literal role="hook">changegroup</literal> 28.1599 - (section <xref linkend="sec.hook.changegroup"/>) <literal 28.1600 - role="hook">prechangegroup</literal> (section <xref 28.1601 - linkend="sec.hook.prechangegroup"/>), <literal 28.1602 - role="hook">pretxnchangegroup</literal> (section <xref 28.1603 - linkend="sec.hook.pretxnchangegroup"/>) 28.1604 - </para> 28.1605 - 28.1606 - </sect2> 28.1607 - <sect2 id="sec.hook.outgoing"> 28.1608 - <title><literal role="hook">outgoing</literal>&emdash;after 28.1609 - changesets are propagated</title> 28.1610 - 28.1611 - <para>This hook is run after a group of changesets has been 28.1612 - propagated out of this repository, for example by a <command 28.1613 - role="hg-cmd">hg push</command> or <command role="hg-cmd">hg 28.1614 - bundle</command> command. 28.1615 - </para> 28.1616 - 28.1617 - <para>One possible use for this hook is to notify administrators 28.1618 - that changes have been pulled. 28.1619 - </para> 28.1620 - 28.1621 - <para>Parameters to this hook: 28.1622 - </para> 28.1623 - <itemizedlist> 28.1624 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1625 - changeset ID of the first changeset of the group that was 28.1626 - sent. 28.1627 - </para> 28.1628 - </listitem> 28.1629 - <listitem><para><literal>source</literal>: A string. The 28.1630 - source of the of the operation (see section <xref 28.1631 - linkend="sec.hook.sources"/>). If a remote 28.1632 - client pulled changes from this repository, 28.1633 - <literal>source</literal> will be 28.1634 - <literal>serve</literal>. If the client that obtained 28.1635 - changes from this repository was local, 28.1636 - <literal>source</literal> will be 28.1637 - <literal>bundle</literal>, <literal>pull</literal>, or 28.1638 - <literal>push</literal>, depending on the operation the 28.1639 - client performed. 28.1640 - </para> 28.1641 - </listitem> 28.1642 - <listitem><para><literal>url</literal>: A URL. The location 28.1643 - of the remote repository, if known. See section <xref 28.1644 - linkend="sec.hook.url"/> for more 28.1645 - information. 28.1646 - </para> 28.1647 - </listitem></itemizedlist> 28.1648 - 28.1649 - <para>See also: <literal role="hook">preoutgoing</literal> 28.1650 - (section <xref linkend="sec.hook.preoutgoing"/>) 28.1651 - </para> 28.1652 - 28.1653 - </sect2> 28.1654 - <sect2 id="sec.hook.prechangegroup"> 28.1655 - <title><literal 28.1656 - role="hook">prechangegroup</literal>&emdash;before starting 28.1657 - to add remote changesets</title> 28.1658 - 28.1659 - <para>This controlling hook is run before Mercurial begins to 28.1660 - add a group of changesets from another repository. 28.1661 - </para> 28.1662 - 28.1663 - <para>This hook does not have any information about the 28.1664 - changesets to be added, because it is run before transmission 28.1665 - of those changesets is allowed to begin. If this hook fails, 28.1666 - the changesets will not be transmitted. 28.1667 - </para> 28.1668 - 28.1669 - <para>One use for this hook is to prevent external changes from 28.1670 - being added to a repository. For example, you could use this 28.1671 - to <quote>freeze</quote> a server-hosted branch temporarily or 28.1672 - permanently so that users cannot push to it, while still 28.1673 - allowing a local administrator to modify the repository. 28.1674 - </para> 28.1675 - 28.1676 - <para>Parameters to this hook: 28.1677 - </para> 28.1678 - <itemizedlist> 28.1679 - <listitem><para><literal>source</literal>: A string. The 28.1680 - source of these changes. See section <xref 28.1681 - linkend="sec.hook.sources"/> for details. 28.1682 - </para> 28.1683 - </listitem> 28.1684 - <listitem><para><literal>url</literal>: A URL. The location 28.1685 - of the remote repository, if known. See section <xref 28.1686 - linkend="sec.hook.url"/> for more 28.1687 - information. 28.1688 - </para> 28.1689 - </listitem></itemizedlist> 28.1690 - 28.1691 - <para>See also: <literal role="hook">changegroup</literal> 28.1692 - (section <xref linkend="sec.hook.changegroup"/>), <literal 28.1693 - role="hook">incoming</literal> (section <xref 28.1694 - linkend="sec.hook.incoming"/>), , <literal 28.1695 - role="hook">pretxnchangegroup</literal> (section <xref 28.1696 - linkend="sec.hook.pretxnchangegroup"/>) 28.1697 - </para> 28.1698 - 28.1699 - </sect2> 28.1700 - <sect2 id="sec.hook.precommit"> 28.1701 - <title><literal role="hook">precommit</literal>&emdash;before 28.1702 - starting to commit a changeset</title> 28.1703 - 28.1704 - <para>This hook is run before Mercurial begins to commit a new 28.1705 - changeset. It is run before Mercurial has any of the metadata 28.1706 - for the commit, such as the files to be committed, the commit 28.1707 - message, or the commit date. 28.1708 - </para> 28.1709 - 28.1710 - <para>One use for this hook is to disable the ability to commit 28.1711 - new changesets, while still allowing incoming changesets. 28.1712 - Another is to run a build or test, and only allow the commit 28.1713 - to begin if the build or test succeeds. 28.1714 - </para> 28.1715 - 28.1716 - <para>Parameters to this hook: 28.1717 - </para> 28.1718 - <itemizedlist> 28.1719 - <listitem><para><literal>parent1</literal>: A changeset ID. 28.1720 - The changeset ID of the first parent of the working 28.1721 - directory. 28.1722 - </para> 28.1723 - </listitem> 28.1724 - <listitem><para><literal>parent2</literal>: A changeset ID. 28.1725 - The changeset ID of the second parent of the working 28.1726 - directory. 28.1727 - </para> 28.1728 - </listitem></itemizedlist> 28.1729 - <para>If the commit proceeds, the parents of the working 28.1730 - directory will become the parents of the new changeset. 28.1731 - </para> 28.1732 - 28.1733 - <para>See also: <literal role="hook">commit</literal> (section 28.1734 - <xref linkend="sec.hook.commit"/>), <literal 28.1735 - role="hook">pretxncommit</literal> (section <xref 28.1736 - linkend="sec.hook.pretxncommit"/>) 28.1737 - </para> 28.1738 - 28.1739 - </sect2> 28.1740 - <sect2 id="sec.hook.preoutgoing"> 28.1741 - <title><literal role="hook">preoutgoing</literal>&emdash;before 28.1742 - starting to propagate changesets</title> 28.1743 - 28.1744 - <para>This hook is invoked before Mercurial knows the identities 28.1745 - of the changesets to be transmitted. 28.1746 - </para> 28.1747 - 28.1748 - <para>One use for this hook is to prevent changes from being 28.1749 - transmitted to another repository. 28.1750 - </para> 28.1751 - 28.1752 - <para>Parameters to this hook: 28.1753 - </para> 28.1754 - <itemizedlist> 28.1755 - <listitem><para><literal>source</literal>: A string. The 28.1756 - source of the operation that is attempting to obtain 28.1757 - changes from this repository (see section <xref 28.1758 - linkend="sec.hook.sources"/>). See the documentation 28.1759 - for the <literal>source</literal> parameter to the 28.1760 - <literal role="hook">outgoing</literal> hook, in section 28.1761 - <xref linkend="sec.hook.outgoing"/>, for possible values 28.1762 - of 28.1763 - this parameter. 28.1764 - </para> 28.1765 - </listitem> 28.1766 - <listitem><para><literal>url</literal>: A URL. The location 28.1767 - of the remote repository, if known. See section <xref 28.1768 - linkend="sec.hook.url"/> for more 28.1769 - information. 28.1770 - </para> 28.1771 - </listitem></itemizedlist> 28.1772 - 28.1773 - <para>See also: <literal role="hook">outgoing</literal> (section 28.1774 - <xref linkend="sec.hook.outgoing"/>) 28.1775 - </para> 28.1776 - 28.1777 - </sect2> 28.1778 - <sect2 id="sec.hook.pretag"> 28.1779 - <title><literal role="hook">pretag</literal>&emdash;before 28.1780 - tagging a changeset</title> 28.1781 - 28.1782 - <para>This controlling hook is run before a tag is created. If 28.1783 - the hook succeeds, creation of the tag proceeds. If the hook 28.1784 - fails, the tag is not created. 28.1785 - </para> 28.1786 - 28.1787 - <para>Parameters to this hook: 28.1788 - </para> 28.1789 - <itemizedlist> 28.1790 - <listitem><para><literal>local</literal>: A boolean. Whether 28.1791 - the tag is local to this repository instance (i.e. stored 28.1792 - in <filename role="special">.hg/localtags</filename>) or 28.1793 - managed by Mercurial (stored in <filename 28.1794 - role="special">.hgtags</filename>). 28.1795 - </para> 28.1796 - </listitem> 28.1797 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1798 - ID of the changeset to be tagged. 28.1799 - </para> 28.1800 - </listitem> 28.1801 - <listitem><para><literal>tag</literal>: A string. The name of 28.1802 - the tag to be created. 28.1803 - </para> 28.1804 - </listitem></itemizedlist> 28.1805 - 28.1806 - <para>If the tag to be created is revision-controlled, the 28.1807 - <literal role="hook">precommit</literal> and <literal 28.1808 - role="hook">pretxncommit</literal> hooks (sections <xref 28.1809 - linkend="sec.hook.commit"/> and <xref 28.1810 - linkend="sec.hook.pretxncommit"/>) will also be run. 28.1811 - </para> 28.1812 - 28.1813 - <para>See also: <literal role="hook">tag</literal> (section 28.1814 - <xref linkend="sec.hook.tag"/>) 28.1815 - </para> 28.1816 - </sect2> 28.1817 - <sect2 id="sec.hook.pretxnchangegroup"> 28.1818 - <title><literal 28.1819 - role="hook">pretxnchangegroup</literal>&emdash;before 28.1820 - completing addition of remote changesets</title> 28.1821 - 28.1822 - <para>This controlling hook is run before a 28.1823 - transaction&emdash;that manages the addition of a group of new 28.1824 - changesets from outside the repository&emdash;completes. If 28.1825 - the hook succeeds, the transaction completes, and all of the 28.1826 - changesets become permanent within this repository. If the 28.1827 - hook fails, the transaction is rolled back, and the data for 28.1828 - the changesets is erased. 28.1829 - </para> 28.1830 - 28.1831 - <para>This hook can access the metadata associated with the 28.1832 - almost-added changesets, but it should not do anything 28.1833 - permanent with this data. It must also not modify the working 28.1834 - directory. 28.1835 - </para> 28.1836 - 28.1837 - <para>While this hook is running, if other Mercurial processes 28.1838 - access this repository, they will be able to see the 28.1839 - almost-added changesets as if they are permanent. This may 28.1840 - lead to race conditions if you do not take steps to avoid 28.1841 - them. 28.1842 - </para> 28.1843 - 28.1844 - <para>This hook can be used to automatically vet a group of 28.1845 - changesets. If the hook fails, all of the changesets are 28.1846 - <quote>rejected</quote> when the transaction rolls back. 28.1847 - </para> 28.1848 - 28.1849 - <para>Parameters to this hook: 28.1850 - </para> 28.1851 - <itemizedlist> 28.1852 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1853 - changeset ID of the first changeset in the group that was 28.1854 - added. All changesets between this and 28.1855 - <literal role="tag">tip</literal>, 28.1856 - inclusive, were added by a single <command 28.1857 - role="hg-cmd">hg pull</command>, <command 28.1858 - role="hg-cmd">hg push</command> or <command 28.1859 - role="hg-cmd">hg unbundle</command>. 28.1860 - </para> 28.1861 - </listitem> 28.1862 - <listitem><para><literal>source</literal>: A string. The 28.1863 - source of these changes. See section <xref 28.1864 - linkend="sec.hook.sources"/> for details. 28.1865 - </para> 28.1866 - </listitem> 28.1867 - <listitem><para><literal>url</literal>: A URL. The location 28.1868 - of the remote repository, if known. See section <xref 28.1869 - linkend="sec.hook.url"/> for more 28.1870 - information. 28.1871 - </para> 28.1872 - </listitem></itemizedlist> 28.1873 - 28.1874 - <para>See also: <literal role="hook">changegroup</literal> 28.1875 - (section <xref linkend="sec.hook.changegroup"/>), <literal 28.1876 - role="hook">incoming</literal> (section <xref 28.1877 - linkend="sec.hook.incoming"/>), <literal 28.1878 - role="hook">prechangegroup</literal> (section <xref 28.1879 - linkend="sec.hook.prechangegroup"/>) 28.1880 - </para> 28.1881 - 28.1882 - </sect2> 28.1883 - <sect2 id="sec.hook.pretxncommit"> 28.1884 - <title><literal role="hook">pretxncommit</literal>&emdash;before 28.1885 - completing commit of new changeset</title> 28.1886 - 28.1887 - <para>This controlling hook is run before a 28.1888 - transaction&emdash;that manages a new commit&emdash;completes. 28.1889 - If the hook succeeds, the transaction completes and the 28.1890 - changeset becomes permanent within this repository. If the 28.1891 - hook fails, the transaction is rolled back, and the commit 28.1892 - data is erased. 28.1893 - </para> 28.1894 - 28.1895 - <para>This hook can access the metadata associated with the 28.1896 - almost-new changeset, but it should not do anything permanent 28.1897 - with this data. It must also not modify the working 28.1898 - directory. 28.1899 - </para> 28.1900 - 28.1901 - <para>While this hook is running, if other Mercurial processes 28.1902 - access this repository, they will be able to see the 28.1903 - almost-new changeset as if it is permanent. This may lead to 28.1904 - race conditions if you do not take steps to avoid them. 28.1905 - </para> 28.1906 - 28.1907 - <para>Parameters to this hook: 28.1908 - </para> 28.1909 - <itemizedlist> 28.1910 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1911 - changeset ID of the newly committed changeset. 28.1912 - </para> 28.1913 - </listitem> 28.1914 - <listitem><para><literal>parent1</literal>: A changeset ID. 28.1915 - The changeset ID of the first parent of the newly 28.1916 - committed changeset. 28.1917 - </para> 28.1918 - </listitem> 28.1919 - <listitem><para><literal>parent2</literal>: A changeset ID. 28.1920 - The changeset ID of the second parent of the newly 28.1921 - committed changeset. 28.1922 - </para> 28.1923 - </listitem></itemizedlist> 28.1924 - 28.1925 - <para>See also: <literal role="hook">precommit</literal> 28.1926 - (section <xref linkend="sec.hook.precommit"/>) 28.1927 - </para> 28.1928 - 28.1929 - </sect2> 28.1930 - <sect2 id="sec.hook.preupdate"> 28.1931 - <title><literal role="hook">preupdate</literal>&emdash;before 28.1932 - updating or merging working directory</title> 28.1933 - 28.1934 - <para>This controlling hook is run before an update or merge of 28.1935 - the working directory begins. It is run only if Mercurial's 28.1936 - normal pre-update checks determine that the update or merge 28.1937 - can proceed. If the hook succeeds, the update or merge may 28.1938 - proceed; if it fails, the update or merge does not start. 28.1939 - </para> 28.1940 - 28.1941 - <para>Parameters to this hook: 28.1942 - </para> 28.1943 - <itemizedlist> 28.1944 - <listitem><para><literal>parent1</literal>: A changeset ID. 28.1945 - The ID of the parent that the working directory is to be 28.1946 - updated to. If the working directory is being merged, it 28.1947 - will not change this parent. 28.1948 - </para> 28.1949 - </listitem> 28.1950 - <listitem><para><literal>parent2</literal>: A changeset ID. 28.1951 - Only set if the working directory is being merged. The ID 28.1952 - of the revision that the working directory is being merged 28.1953 - with. 28.1954 - </para> 28.1955 - </listitem></itemizedlist> 28.1956 - 28.1957 - <para>See also: <literal role="hook">update</literal> (section 28.1958 - <xref linkend="sec.hook.update"/>) 28.1959 - </para> 28.1960 - 28.1961 - </sect2> 28.1962 - <sect2 id="sec.hook.tag"> 28.1963 - <title><literal role="hook">tag</literal>&emdash;after tagging a 28.1964 - changeset</title> 28.1965 - 28.1966 - <para>This hook is run after a tag has been created. 28.1967 - </para> 28.1968 - 28.1969 - <para>Parameters to this hook: 28.1970 - </para> 28.1971 - <itemizedlist> 28.1972 - <listitem><para><literal>local</literal>: A boolean. Whether 28.1973 - the new tag is local to this repository instance (i.e. 28.1974 - stored in <filename 28.1975 - role="special">.hg/localtags</filename>) or managed by 28.1976 - Mercurial (stored in <filename 28.1977 - role="special">.hgtags</filename>). 28.1978 - </para> 28.1979 - </listitem> 28.1980 - <listitem><para><literal>node</literal>: A changeset ID. The 28.1981 - ID of the changeset that was tagged. 28.1982 - </para> 28.1983 - </listitem> 28.1984 - <listitem><para><literal>tag</literal>: A string. The name of 28.1985 - the tag that was created. 28.1986 - </para> 28.1987 - </listitem></itemizedlist> 28.1988 - 28.1989 - <para>If the created tag is revision-controlled, the <literal 28.1990 - role="hook">commit</literal> hook (section <xref 28.1991 - linkend="sec.hook.commit"/>) is run before this hook. 28.1992 - </para> 28.1993 - 28.1994 - <para>See also: <literal role="hook">pretag</literal> (section 28.1995 - <xref linkend="sec.hook.pretag"/>) 28.1996 - </para> 28.1997 - 28.1998 - </sect2> 28.1999 - <sect2 id="sec.hook.update"> 28.2000 - <title><literal role="hook">update</literal>&emdash;after 28.2001 - updating or merging working directory</title> 28.2002 - 28.2003 - <para>This hook is run after an update or merge of the working 28.2004 - directory completes. Since a merge can fail (if the external 28.2005 - <command>hgmerge</command> command fails to resolve conflicts 28.2006 - in a file), this hook communicates whether the update or merge 28.2007 - completed cleanly. 28.2008 - </para> 28.2009 - 28.2010 - <itemizedlist> 28.2011 - <listitem><para><literal>error</literal>: A boolean. 28.2012 - Indicates whether the update or merge completed 28.2013 - successfully. 28.2014 - </para> 28.2015 - </listitem> 28.2016 - <listitem><para><literal>parent1</literal>: A changeset ID. 28.2017 - The ID of the parent that the working directory was 28.2018 - updated to. If the working directory was merged, it will 28.2019 - not have changed this parent. 28.2020 - </para> 28.2021 - </listitem> 28.2022 - <listitem><para><literal>parent2</literal>: A changeset ID. 28.2023 - Only set if the working directory was merged. The ID of 28.2024 - the revision that the working directory was merged with. 28.2025 - </para> 28.2026 - </listitem></itemizedlist> 28.2027 - 28.2028 - <para>See also: <literal role="hook">preupdate</literal> 28.2029 - (section <xref linkend="sec.hook.preupdate"/>) 28.2030 - </para> 28.2031 - 28.2032 - </sect2> 28.2033 - </sect1> 28.2034 -</chapter> 28.2035 - 28.2036 -<!-- 28.2037 -local variables: 28.2038 -sgml-parent-document: ("00book.xml" "book" "chapter") 28.2039 -end: 28.2040 --->
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/en/ch10-template.xml Fri Mar 20 16:43:35 2009 +0800 29.3 @@ -0,0 +1,675 @@ 29.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 29.5 + 29.6 +<chapter id="chap.template"> 29.7 + <?dbhtml filename="customizing-the-output-of-mercurial.html"?> 29.8 + <title>Customising the output of Mercurial</title> 29.9 + 29.10 + <para id="x_578">Mercurial provides a powerful mechanism to let you control how 29.11 + it displays information. The mechanism is based on templates. 29.12 + You can use templates to generate specific output for a single 29.13 + command, or to customise the entire appearance of the built-in web 29.14 + interface.</para> 29.15 + 29.16 + <sect1 id="sec.style"> 29.17 + <title>Using precanned output styles</title> 29.18 + 29.19 + <para id="x_579">Packaged with Mercurial are some output styles that you can 29.20 + use immediately. A style is simply a precanned template that 29.21 + someone wrote and installed somewhere that Mercurial can 29.22 + find.</para> 29.23 + 29.24 + <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's 29.25 + review its normal output.</para> 29.26 + 29.27 + &interaction.template.simple.normal; 29.28 + 29.29 + <para id="x_57b">This is somewhat informative, but it takes up a lot of 29.30 + space&emdash;five lines of output per changeset. The 29.31 + <literal>compact</literal> style reduces this to three lines, 29.32 + presented in a sparse manner.</para> 29.33 + 29.34 + &interaction.template.simple.compact; 29.35 + 29.36 + <para id="x_57c">The <literal>changelog</literal> style hints at the 29.37 + expressive power of Mercurial's templating engine. This style 29.38 + attempts to follow the GNU Project's changelog 29.39 + guidelines<citation>web:changelog</citation>.</para> 29.40 + 29.41 + &interaction.template.simple.changelog; 29.42 + 29.43 + <para id="x_57d">You will not be shocked to learn that Mercurial's default 29.44 + output style is named <literal>default</literal>.</para> 29.45 + 29.46 + <sect2> 29.47 + <title>Setting a default style</title> 29.48 + 29.49 + <para id="x_57e">You can modify the output style that Mercurial will use 29.50 + for every command by editing your <filename 29.51 + role="special">~/.hgrc</filename> file, naming the style 29.52 + you would prefer to use.</para> 29.53 + 29.54 + <programlisting>[ui] 29.55 +style = compact</programlisting> 29.56 + 29.57 + <para id="x_57f">If you write a style of your own, you can use it by either 29.58 + providing the path to your style file, or copying your style 29.59 + file into a location where Mercurial can find it (typically 29.60 + the <literal>templates</literal> subdirectory of your 29.61 + Mercurial install directory).</para> 29.62 + 29.63 + </sect2> 29.64 + </sect1> 29.65 + <sect1> 29.66 + <title>Commands that support styles and templates</title> 29.67 + 29.68 + <para id="x_580">All of Mercurial's 29.69 + <quote><literal>log</literal>-like</quote> commands let you use 29.70 + styles and templates: <command role="hg-cmd">hg 29.71 + incoming</command>, <command role="hg-cmd">hg log</command>, 29.72 + <command role="hg-cmd">hg outgoing</command>, and <command 29.73 + role="hg-cmd">hg tip</command>.</para> 29.74 + 29.75 + <para id="x_581">As I write this manual, these are so far the only commands 29.76 + that support styles and templates. Since these are the most 29.77 + important commands that need customisable output, there has been 29.78 + little pressure from the Mercurial user community to add style 29.79 + and template support to other commands.</para> 29.80 + 29.81 + </sect1> 29.82 + <sect1> 29.83 + <title>The basics of templating</title> 29.84 + 29.85 + <para id="x_582">At its simplest, a Mercurial template is a piece of text. 29.86 + Some of the text never changes, while other parts are 29.87 + <emphasis>expanded</emphasis>, or replaced with new text, when 29.88 + necessary.</para> 29.89 + 29.90 + <para id="x_583">Before we continue, let's look again at a simple example of 29.91 + Mercurial's normal output.</para> 29.92 + 29.93 + &interaction.template.simple.normal; 29.94 + 29.95 + <para id="x_584">Now, let's run the same command, but using a template to 29.96 + change its output.</para> 29.97 + 29.98 + &interaction.template.simple.simplest; 29.99 + 29.100 + <para id="x_585">The example above illustrates the simplest possible 29.101 + template; it's just a piece of static text, printed once for 29.102 + each changeset. The <option 29.103 + role="hg-opt-log">--template</option> option to the <command 29.104 + role="hg-cmd">hg log</command> command tells Mercurial to use 29.105 + the given text as the template when printing each 29.106 + changeset.</para> 29.107 + 29.108 + <para id="x_586">Notice that the template string above ends with the text 29.109 + <quote><literal>\n</literal></quote>. This is an 29.110 + <emphasis>escape sequence</emphasis>, telling Mercurial to print 29.111 + a newline at the end of each template item. If you omit this 29.112 + newline, Mercurial will run each piece of output together. See 29.113 + section <xref linkend="sec.template.escape"/> for more details 29.114 + of escape sequences.</para> 29.115 + 29.116 + <para id="x_587">A template that prints a fixed string of text all the time 29.117 + isn't very useful; let's try something a bit more 29.118 + complex.</para> 29.119 + 29.120 + &interaction.template.simple.simplesub; 29.121 + 29.122 + <para id="x_588">As you can see, the string 29.123 + <quote><literal>{desc}</literal></quote> in the template has 29.124 + been replaced in the output with the description of each 29.125 + changeset. Every time Mercurial finds text enclosed in curly 29.126 + braces (<quote><literal>{</literal></quote> and 29.127 + <quote><literal>}</literal></quote>), it will try to replace the braces 29.128 + and text with the expansion of whatever is inside. To print a 29.129 + literal curly brace, you must escape it, as described in section 29.130 + <xref 29.131 + linkend="sec.template.escape"/>.</para> 29.132 + 29.133 + </sect1> 29.134 + <sect1 id="sec.template.keyword"> 29.135 + <title>Common template keywords</title> 29.136 + 29.137 + <para id="x_589">You can start writing simple templates immediately using the 29.138 + keywords below.</para> 29.139 + 29.140 + <itemizedlist> 29.141 + <listitem><para id="x_58a"><literal 29.142 + role="template-keyword">author</literal>: String. The 29.143 + unmodified author of the changeset.</para> 29.144 + </listitem> 29.145 + <listitem><para id="x_58b"><literal 29.146 + role="template-keyword">branches</literal>: String. The 29.147 + name of the branch on which the changeset was committed. 29.148 + Will be empty if the branch name was 29.149 + <literal>default</literal>.</para> 29.150 + </listitem> 29.151 + <listitem><para id="x_58c"><literal role="template-keyword">date</literal>: 29.152 + Date information. The date when the changeset was 29.153 + committed. This is <emphasis>not</emphasis> human-readable; 29.154 + you must pass it through a filter that will render it 29.155 + appropriately. See section <xref 29.156 + linkend="sec.template.filter"/> for more information 29.157 + on filters. The date is expressed as a pair of numbers. The 29.158 + first number is a Unix UTC timestamp (seconds since January 29.159 + 1, 1970); the second is the offset of the committer's 29.160 + timezone from UTC, in seconds.</para> 29.161 + </listitem> 29.162 + <listitem><para id="x_58d"><literal role="template-keyword">desc</literal>: 29.163 + String. The text of the changeset description.</para> 29.164 + </listitem> 29.165 + <listitem><para id="x_58e"><literal 29.166 + role="template-keyword">files</literal>: List of strings. 29.167 + All files modified, added, or removed by this 29.168 + changeset.</para> 29.169 + </listitem> 29.170 + <listitem><para id="x_58f"><literal 29.171 + role="template-keyword">file_adds</literal>: List of 29.172 + strings. Files added by this changeset.</para> 29.173 + </listitem> 29.174 + <listitem><para id="x_590"><literal 29.175 + role="template-keyword">file_dels</literal>: List of 29.176 + strings. Files removed by this changeset.</para> 29.177 + </listitem> 29.178 + <listitem><para id="x_591"><literal role="template-keyword">node</literal>: 29.179 + String. The changeset identification hash, as a 29.180 + 40-character hexadecimal string.</para> 29.181 + </listitem> 29.182 + <listitem><para id="x_592"><literal 29.183 + role="template-keyword">parents</literal>: List of 29.184 + strings. The parents of the changeset.</para> 29.185 + </listitem> 29.186 + <listitem><para id="x_593"><literal role="template-keyword">rev</literal>: 29.187 + Integer. The repository-local changeset revision 29.188 + number.</para> 29.189 + </listitem> 29.190 + <listitem><para id="x_594"><literal role="template-keyword">tags</literal>: 29.191 + List of strings. Any tags associated with the 29.192 + changeset.</para> 29.193 + </listitem></itemizedlist> 29.194 + 29.195 + <para id="x_595">A few simple experiments will show us what to expect when we 29.196 + use these keywords; you can see the results below.</para> 29.197 + 29.198 +&interaction.template.simple.keywords; 29.199 + 29.200 + <para id="x_596">As we noted above, the date keyword does not produce 29.201 + human-readable output, so we must treat it specially. This 29.202 + involves using a <emphasis>filter</emphasis>, about which more 29.203 + in section <xref 29.204 + linkend="sec.template.filter"/>.</para> 29.205 + 29.206 + &interaction.template.simple.datekeyword; 29.207 + 29.208 + </sect1> 29.209 + <sect1 id="sec.template.escape"> 29.210 + <title>Escape sequences</title> 29.211 + 29.212 + <para id="x_597">Mercurial's templating engine recognises the most commonly 29.213 + used escape sequences in strings. When it sees a backslash 29.214 + (<quote><literal>\</literal></quote>) character, it looks at the 29.215 + following character and substitutes the two characters with a 29.216 + single replacement, as described below.</para> 29.217 + 29.218 + <itemizedlist> 29.219 + <listitem><para id="x_598"><literal>\</literal>: 29.220 + Backslash, <quote><literal>\</literal></quote>, ASCII 29.221 + 134.</para> 29.222 + </listitem> 29.223 + <listitem><para id="x_599"><literal>\n</literal>: Newline, 29.224 + ASCII 12.</para> 29.225 + </listitem> 29.226 + <listitem><para id="x_59a"><literal>\r</literal>: Carriage 29.227 + return, ASCII 15.</para> 29.228 + </listitem> 29.229 + <listitem><para id="x_59b"><literal>\t</literal>: Tab, ASCII 29.230 + 11.</para> 29.231 + </listitem> 29.232 + <listitem><para id="x_59c"><literal>\v</literal>: Vertical 29.233 + tab, ASCII 13.</para> 29.234 + </listitem> 29.235 + <listitem><para id="x_59d"><literal>{</literal>: Open curly 29.236 + brace, <quote><literal>{</literal></quote>, ASCII 29.237 + 173.</para> 29.238 + </listitem> 29.239 + <listitem><para id="x_59e"><literal>}</literal>: Close curly 29.240 + brace, <quote><literal>}</literal></quote>, ASCII 29.241 + 175.</para> 29.242 + </listitem></itemizedlist> 29.243 + 29.244 + <para id="x_59f">As indicated above, if you want the expansion of a template 29.245 + to contain a literal <quote><literal>\</literal></quote>, 29.246 + <quote><literal>{</literal></quote>, or 29.247 + <quote><literal>{</literal></quote> character, you must escape 29.248 + it.</para> 29.249 + 29.250 + </sect1> 29.251 + <sect1 id="sec.template.filter"> 29.252 + <title>Filtering keywords to change their results</title> 29.253 + 29.254 + <para id="x_5a0">Some of the results of template expansion are not 29.255 + immediately easy to use. Mercurial lets you specify an optional 29.256 + chain of <emphasis>filters</emphasis> to modify the result of 29.257 + expanding a keyword. You have already seen a common filter, 29.258 + <literal role="template-kw-filt-date">isodate</literal>, in 29.259 + action above, to make a date readable.</para> 29.260 + 29.261 + <para id="x_5a1">Below is a list of the most commonly used filters that 29.262 + Mercurial supports. While some filters can be applied to any 29.263 + text, others can only be used in specific circumstances. The 29.264 + name of each filter is followed first by an indication of where 29.265 + it can be used, then a description of its effect.</para> 29.266 + 29.267 + <itemizedlist> 29.268 + <listitem><para id="x_5a2"><literal 29.269 + role="template-filter">addbreaks</literal>: Any text. Add 29.270 + an XHTML <quote><literal><br/></literal></quote> tag 29.271 + before the end of every line except the last. For example, 29.272 + <quote><literal>foo\nbar</literal></quote> becomes 29.273 + <quote><literal>foo<br/>\nbar</literal></quote>.</para> 29.274 + </listitem> 29.275 + <listitem><para id="x_5a3"><literal 29.276 + role="template-kw-filt-date">age</literal>: <literal 29.277 + role="template-keyword">date</literal> keyword. Render 29.278 + the age of the date, relative to the current time. Yields a 29.279 + string like <quote><literal>10 29.280 + minutes</literal></quote>.</para> 29.281 + </listitem> 29.282 + <listitem><para id="x_5a4"><literal 29.283 + role="template-filter">basename</literal>: Any text, but 29.284 + most useful for the <literal 29.285 + role="template-keyword">files</literal> keyword and its 29.286 + relatives. Treat the text as a path, and return the 29.287 + basename. For example, 29.288 + <quote><literal>foo/bar/baz</literal></quote> becomes 29.289 + <quote><literal>baz</literal></quote>.</para> 29.290 + </listitem> 29.291 + <listitem><para id="x_5a5"><literal 29.292 + role="template-kw-filt-date">date</literal>: <literal 29.293 + role="template-keyword">date</literal> keyword. Render a 29.294 + date in a similar format to the Unix <literal 29.295 + role="template-keyword">date</literal> command, but with 29.296 + timezone included. Yields a string like <quote><literal>Mon 29.297 + Sep 04 15:13:13 2006 -0700</literal></quote>.</para> 29.298 + </listitem> 29.299 + <listitem><para id="x_5a6"><literal 29.300 + role="template-kw-filt-author">domain</literal>: Any text, 29.301 + but most useful for the <literal 29.302 + role="template-keyword">author</literal> keyword. Finds 29.303 + the first string that looks like an email address, and 29.304 + extract just the domain component. For example, 29.305 + <quote><literal>Bryan O'Sullivan 29.306 + <bos@serpentine.com></literal></quote> becomes 29.307 + <quote><literal>serpentine.com</literal></quote>.</para> 29.308 + </listitem> 29.309 + <listitem><para id="x_5a7"><literal 29.310 + role="template-kw-filt-author">email</literal>: Any text, 29.311 + but most useful for the <literal 29.312 + role="template-keyword">author</literal> keyword. Extract 29.313 + the first string that looks like an email address. For 29.314 + example, <quote><literal>Bryan O'Sullivan 29.315 + <bos@serpentine.com></literal></quote> becomes 29.316 + <quote><literal>bos@serpentine.com</literal></quote>.</para> 29.317 + </listitem> 29.318 + <listitem><para id="x_5a8"><literal 29.319 + role="template-filter">escape</literal>: Any text. 29.320 + Replace the special XML/XHTML characters 29.321 + <quote><literal>&</literal></quote>, 29.322 + <quote><literal><</literal></quote> and 29.323 + <quote><literal>></literal></quote> with XML 29.324 + entities.</para> 29.325 + </listitem> 29.326 + <listitem><para id="x_5a9"><literal 29.327 + role="template-filter">fill68</literal>: Any text. Wrap 29.328 + the text to fit in 68 columns. This is useful before you 29.329 + pass text through the <literal 29.330 + role="template-filter">tabindent</literal> filter, and 29.331 + still want it to fit in an 80-column fixed-font 29.332 + window.</para> 29.333 + </listitem> 29.334 + <listitem><para id="x_5aa"><literal 29.335 + role="template-filter">fill76</literal>: Any text. Wrap 29.336 + the text to fit in 76 columns.</para> 29.337 + </listitem> 29.338 + <listitem><para id="x_5ab"><literal 29.339 + role="template-filter">firstline</literal>: Any text. 29.340 + Yield the first line of text, without any trailing 29.341 + newlines.</para> 29.342 + </listitem> 29.343 + <listitem><para id="x_5ac"><literal 29.344 + role="template-kw-filt-date">hgdate</literal>: <literal 29.345 + role="template-keyword">date</literal> keyword. Render 29.346 + the date as a pair of readable numbers. Yields a string 29.347 + like <quote><literal>1157407993 29.348 + 25200</literal></quote>.</para> 29.349 + </listitem> 29.350 + <listitem><para id="x_5ad"><literal 29.351 + role="template-kw-filt-date">isodate</literal>: <literal 29.352 + role="template-keyword">date</literal> keyword. Render 29.353 + the date as a text string in ISO 8601 format. Yields a 29.354 + string like <quote><literal>2006-09-04 15:13:13 29.355 + -0700</literal></quote>.</para> 29.356 + </listitem> 29.357 + <listitem><para id="x_5ae"><literal 29.358 + role="template-filter">obfuscate</literal>: Any text, but 29.359 + most useful for the <literal 29.360 + role="template-keyword">author</literal> keyword. Yield 29.361 + the input text rendered as a sequence of XML entities. This 29.362 + helps to defeat some particularly stupid screen-scraping 29.363 + email harvesting spambots.</para> 29.364 + </listitem> 29.365 + <listitem><para id="x_5af"><literal 29.366 + role="template-kw-filt-author">person</literal>: Any text, 29.367 + but most useful for the <literal 29.368 + role="template-keyword">author</literal> keyword. Yield 29.369 + the text before an email address. For example, 29.370 + <quote><literal>Bryan O'Sullivan 29.371 + <bos@serpentine.com></literal></quote> becomes 29.372 + <quote><literal>Bryan O'Sullivan</literal></quote>.</para> 29.373 + </listitem> 29.374 + <listitem><para id="x_5b0"><literal 29.375 + role="template-kw-filt-date">rfc822date</literal>: 29.376 + <literal role="template-keyword">date</literal> keyword. 29.377 + Render a date using the same format used in email headers. 29.378 + Yields a string like <quote><literal>Mon, 04 Sep 2006 29.379 + 15:13:13 -0700</literal></quote>.</para> 29.380 + </listitem> 29.381 + <listitem><para id="x_5b1"><literal 29.382 + role="template-kw-filt-node">short</literal>: Changeset 29.383 + hash. Yield the short form of a changeset hash, i.e. a 29.384 + 12-character hexadecimal string.</para> 29.385 + </listitem> 29.386 + <listitem><para id="x_5b2"><literal 29.387 + role="template-kw-filt-date">shortdate</literal>: <literal 29.388 + role="template-keyword">date</literal> keyword. Render 29.389 + the year, month, and day of the date. Yields a string like 29.390 + <quote><literal>2006-09-04</literal></quote>.</para> 29.391 + </listitem> 29.392 + <listitem><para id="x_5b3"><literal role="template-filter">strip</literal>: 29.393 + Any text. Strip all leading and trailing whitespace from 29.394 + the string.</para> 29.395 + </listitem> 29.396 + <listitem><para id="x_5b4"><literal 29.397 + role="template-filter">tabindent</literal>: Any text. 29.398 + Yield the text, with every line except the first starting 29.399 + with a tab character.</para> 29.400 + </listitem> 29.401 + <listitem><para id="x_5b5"><literal 29.402 + role="template-filter">urlescape</literal>: Any text. 29.403 + Escape all characters that are considered 29.404 + <quote>special</quote> by URL parsers. For example, 29.405 + <literal>foo bar</literal> becomes 29.406 + <literal>foo%20bar</literal>.</para> 29.407 + </listitem> 29.408 + <listitem><para id="x_5b6"><literal 29.409 + role="template-kw-filt-author">user</literal>: Any text, 29.410 + but most useful for the <literal 29.411 + role="template-keyword">author</literal> keyword. Return 29.412 + the <quote>user</quote> portion of an email address. For 29.413 + example, <quote><literal>Bryan O'Sullivan 29.414 + <bos@serpentine.com></literal></quote> becomes 29.415 + <quote><literal>bos</literal></quote>.</para> 29.416 + </listitem></itemizedlist> 29.417 + 29.418 +&interaction.template.simple.manyfilters; 29.419 + 29.420 + <note> 29.421 + <para id="x_5b7"> If you try to apply a filter to a piece of data that it 29.422 + cannot process, Mercurial will fail and print a Python 29.423 + exception. For example, trying to run the output of the 29.424 + <literal role="template-keyword">desc</literal> keyword into 29.425 + the <literal role="template-kw-filt-date">isodate</literal> 29.426 + filter is not a good idea.</para> 29.427 + </note> 29.428 + 29.429 + <sect2> 29.430 + <title>Combining filters</title> 29.431 + 29.432 + <para id="x_5b8">It is easy to combine filters to yield output in the form 29.433 + you would like. The following chain of filters tidies up a 29.434 + description, then makes sure that it fits cleanly into 68 29.435 + columns, then indents it by a further 8 characters (at least 29.436 + on Unix-like systems, where a tab is conventionally 8 29.437 + characters wide).</para> 29.438 + 29.439 + &interaction.template.simple.combine; 29.440 + 29.441 + <para id="x_5b9">Note the use of <quote><literal>\t</literal></quote> (a 29.442 + tab character) in the template to force the first line to be 29.443 + indented; this is necessary since <literal 29.444 + role="template-keyword">tabindent</literal> indents all 29.445 + lines <emphasis>except</emphasis> the first.</para> 29.446 + 29.447 + <para id="x_5ba">Keep in mind that the order of filters in a chain is 29.448 + significant. The first filter is applied to the result of the 29.449 + keyword; the second to the result of the first filter; and so 29.450 + on. For example, using <literal>fill68|tabindent</literal> 29.451 + gives very different results from 29.452 + <literal>tabindent|fill68</literal>.</para> 29.453 + 29.454 + 29.455 + </sect2> 29.456 + </sect1> 29.457 + <sect1> 29.458 + <title>From templates to styles</title> 29.459 + 29.460 + <para id="x_5bb">A command line template provides a quick and simple way to 29.461 + format some output. Templates can become verbose, though, and 29.462 + it's useful to be able to give a template a name. A style file 29.463 + is a template with a name, stored in a file.</para> 29.464 + 29.465 + <para id="x_5bc">More than that, using a style file unlocks the power of 29.466 + Mercurial's templating engine in ways that are not possible 29.467 + using the command line <option 29.468 + role="hg-opt-log">--template</option> option.</para> 29.469 + 29.470 + <sect2> 29.471 + <title>The simplest of style files</title> 29.472 + 29.473 + <para id="x_5bd">Our simple style file contains just one line:</para> 29.474 + 29.475 + &interaction.template.simple.rev; 29.476 + 29.477 + <para id="x_5be">This tells Mercurial, <quote>if you're printing a 29.478 + changeset, use the text on the right as the 29.479 + template</quote>.</para> 29.480 + 29.481 + </sect2> 29.482 + <sect2> 29.483 + <title>Style file syntax</title> 29.484 + 29.485 + <para id="x_5bf">The syntax rules for a style file are simple.</para> 29.486 + 29.487 + <itemizedlist> 29.488 + <listitem><para id="x_5c0">The file is processed one line at a 29.489 + time.</para> 29.490 + </listitem> 29.491 + <listitem><para id="x_5c1">Leading and trailing white space are 29.492 + ignored.</para> 29.493 + </listitem> 29.494 + <listitem><para id="x_5c2">Empty lines are skipped.</para> 29.495 + </listitem> 29.496 + <listitem><para id="x_5c3">If a line starts with either of the characters 29.497 + <quote><literal>#</literal></quote> or 29.498 + <quote><literal>;</literal></quote>, the entire line is 29.499 + treated as a comment, and skipped as if empty.</para> 29.500 + </listitem> 29.501 + <listitem><para id="x_5c4">A line starts with a keyword. This must start 29.502 + with an alphabetic character or underscore, and can 29.503 + subsequently contain any alphanumeric character or 29.504 + underscore. (In regexp notation, a keyword must match 29.505 + <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> 29.506 + </listitem> 29.507 + <listitem><para id="x_5c5">The next element must be an 29.508 + <quote><literal>=</literal></quote> character, which can 29.509 + be preceded or followed by an arbitrary amount of white 29.510 + space.</para> 29.511 + </listitem> 29.512 + <listitem><para id="x_5c6">If the rest of the line starts and ends with 29.513 + matching quote characters (either single or double quote), 29.514 + it is treated as a template body.</para> 29.515 + </listitem> 29.516 + <listitem><para id="x_5c7">If the rest of the line <emphasis>does 29.517 + not</emphasis> start with a quote character, it is 29.518 + treated as the name of a file; the contents of this file 29.519 + will be read and used as a template body.</para> 29.520 + </listitem></itemizedlist> 29.521 + 29.522 + </sect2> 29.523 + </sect1> 29.524 + <sect1> 29.525 + <title>Style files by example</title> 29.526 + 29.527 + <para id="x_5c8">To illustrate how to write a style file, we will construct a 29.528 + few by example. Rather than provide a complete style file and 29.529 + walk through it, we'll mirror the usual process of developing a 29.530 + style file by starting with something very simple, and walking 29.531 + through a series of successively more complete examples.</para> 29.532 + 29.533 + <sect2> 29.534 + <title>Identifying mistakes in style files</title> 29.535 + 29.536 + <para id="x_5c9">If Mercurial encounters a problem in a style file you are 29.537 + working on, it prints a terse error message that, once you 29.538 + figure out what it means, is actually quite useful.</para> 29.539 + 29.540 +&interaction.template.svnstyle.syntax.input; 29.541 + 29.542 + <para id="x_5ca">Notice that <filename>broken.style</filename> attempts to 29.543 + define a <literal>changeset</literal> keyword, but forgets to 29.544 + give any content for it. When instructed to use this style 29.545 + file, Mercurial promptly complains.</para> 29.546 + 29.547 + &interaction.template.svnstyle.syntax.error; 29.548 + 29.549 + <para id="x_5cb">This error message looks intimidating, but it is not too 29.550 + hard to follow.</para> 29.551 + 29.552 + <itemizedlist> 29.553 + <listitem><para id="x_5cc">The first component is simply Mercurial's way 29.554 + of saying <quote>I am giving up</quote>.</para> 29.555 + <programlisting>___abort___: broken.style:1: parse error</programlisting> 29.556 + </listitem> 29.557 + <listitem><para id="x_5cd">Next comes the name of the style file that 29.558 + contains the error.</para> 29.559 + <programlisting>abort: ___broken.style___:1: parse error</programlisting> 29.560 + </listitem> 29.561 + <listitem><para id="x_5ce">Following the file name is the line number 29.562 + where the error was encountered.</para> 29.563 + <programlisting>abort: broken.style:___1___: parse error</programlisting> 29.564 + </listitem> 29.565 + <listitem><para id="x_5cf">Finally, a description of what went 29.566 + wrong.</para> 29.567 + <programlisting>abort: broken.style:1: ___parse error___</programlisting> 29.568 + </listitem> 29.569 + <listitem><para id="x_5d0">The description of the problem is not always 29.570 + clear (as in this case), but even when it is cryptic, it 29.571 + is almost always trivial to visually inspect the offending 29.572 + line in the style file and see what is wrong.</para> 29.573 + </listitem></itemizedlist> 29.574 + 29.575 + </sect2> 29.576 + <sect2> 29.577 + <title>Uniquely identifying a repository</title> 29.578 + 29.579 + <para id="x_5d1">If you would like to be able to identify a Mercurial 29.580 + repository <quote>fairly uniquely</quote> using a short string 29.581 + as an identifier, you can use the first revision in the 29.582 + repository.</para> 29.583 + 29.584 + &interaction.template.svnstyle.id; 29.585 + 29.586 + <para id="x_5d2">This is not guaranteed to be unique, but it is 29.587 + nevertheless useful in many cases.</para> 29.588 + <itemizedlist> 29.589 + <listitem><para id="x_5d3">It will not work in a completely empty 29.590 + repository, because such a repository does not have a 29.591 + revision zero.</para> 29.592 + </listitem> 29.593 + <listitem><para id="x_5d4">Neither will it work in the (extremely rare) 29.594 + case where a repository is a merge of two or more formerly 29.595 + independent repositories, and you still have those 29.596 + repositories around.</para> 29.597 + </listitem></itemizedlist> 29.598 + <para id="x_5d5">Here are some uses to which you could put this 29.599 + identifier:</para> 29.600 + <itemizedlist> 29.601 + <listitem><para id="x_5d6">As a key into a table for a database that 29.602 + manages repositories on a server.</para> 29.603 + </listitem> 29.604 + <listitem><para id="x_5d7">As half of a {<emphasis>repository 29.605 + ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 29.606 + Save this information away when you run an automated build 29.607 + or other activity, so that you can <quote>replay</quote> 29.608 + the build later if necessary.</para> 29.609 + </listitem></itemizedlist> 29.610 + 29.611 + </sect2> 29.612 + <sect2> 29.613 + <title>Mimicking Subversion's output</title> 29.614 + 29.615 + <para id="x_5d8">Let's try to emulate the default output format used by 29.616 + another revision control tool, Subversion.</para> 29.617 + 29.618 + &interaction.template.svnstyle.short; 29.619 + 29.620 + <para id="x_5d9">Since Subversion's output style is fairly simple, it is 29.621 + easy to copy-and-paste a hunk of its output into a file, and 29.622 + replace the text produced above by Subversion with the 29.623 + template values we'd like to see expanded.</para> 29.624 + 29.625 + &interaction.template.svnstyle.template; 29.626 + 29.627 + <para id="x_5da">There are a few small ways in which this template deviates 29.628 + from the output produced by Subversion.</para> 29.629 + <itemizedlist> 29.630 + <listitem><para id="x_5db">Subversion prints a <quote>readable</quote> 29.631 + date (the <quote><literal>Wed, 27 Sep 2006</literal></quote> in the 29.632 + example output above) in parentheses. Mercurial's 29.633 + templating engine does not provide a way to display a date 29.634 + in this format without also printing the time and time 29.635 + zone.</para> 29.636 + </listitem> 29.637 + <listitem><para id="x_5dc">We emulate Subversion's printing of 29.638 + <quote>separator</quote> lines full of 29.639 + <quote><literal>-</literal></quote> characters by ending 29.640 + the template with such a line. We use the templating 29.641 + engine's <literal role="template-keyword">header</literal> 29.642 + keyword to print a separator line as the first line of 29.643 + output (see below), thus achieving similar output to 29.644 + Subversion.</para> 29.645 + </listitem> 29.646 + <listitem><para id="x_5dd">Subversion's output includes a count in the 29.647 + header of the number of lines in the commit message. We 29.648 + cannot replicate this in Mercurial; the templating engine 29.649 + does not currently provide a filter that counts the number 29.650 + of lines the template generates.</para> 29.651 + </listitem></itemizedlist> 29.652 + <para id="x_5de">It took me no more than a minute or two of work to replace 29.653 + literal text from an example of Subversion's output with some 29.654 + keywords and filters to give the template above. The style 29.655 + file simply refers to the template.</para> 29.656 + 29.657 + &interaction.template.svnstyle.style; 29.658 + 29.659 + <para id="x_5df">We could have included the text of the template file 29.660 + directly in the style file by enclosing it in quotes and 29.661 + replacing the newlines with 29.662 + <quote><literal>\n</literal></quote> sequences, but it would 29.663 + have made the style file too difficult to read. Readability 29.664 + is a good guide when you're trying to decide whether some text 29.665 + belongs in a style file, or in a template file that the style 29.666 + file points to. If the style file will look too big or 29.667 + cluttered if you insert a literal piece of text, drop it into 29.668 + a template instead.</para> 29.669 + 29.670 + </sect2> 29.671 + </sect1> 29.672 +</chapter> 29.673 + 29.674 +<!-- 29.675 +local variables: 29.676 +sgml-parent-document: ("00book.xml" "book" "chapter") 29.677 +end: 29.678 +-->
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/en/ch11-mq.xml Fri Mar 20 16:43:35 2009 +0800 30.3 @@ -0,0 +1,1323 @@ 30.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 30.5 + 30.6 +<chapter id="chap.mq"> 30.7 + <?dbhtml filename="managing-change-with-mercurial-queues.html"?> 30.8 + <title>Managing change with Mercurial Queues</title> 30.9 + 30.10 + <sect1 id="sec.mq.patch-mgmt"> 30.11 + <title>The patch management problem</title> 30.12 + 30.13 + <para>Here is a common scenario: you need to install a software 30.14 + package from source, but you find a bug that you must fix in the 30.15 + source before you can start using the package. You make your 30.16 + changes, forget about the package for a while, and a few months 30.17 + later you need to upgrade to a newer version of the package. If 30.18 + the newer version of the package still has the bug, you must 30.19 + extract your fix from the older source tree and apply it against 30.20 + the newer version. This is a tedious task, and it's easy to 30.21 + make mistakes.</para> 30.22 + 30.23 + <para>This is a simple case of the <quote>patch management</quote> 30.24 + problem. You have an <quote>upstream</quote> source tree that 30.25 + you can't change; you need to make some local changes on top of 30.26 + the upstream tree; and you'd like to be able to keep those 30.27 + changes separate, so that you can apply them to newer versions 30.28 + of the upstream source.</para> 30.29 + 30.30 + <para>The patch management problem arises in many situations. 30.31 + Probably the most visible is that a user of an open source 30.32 + software project will contribute a bug fix or new feature to the 30.33 + project's maintainers in the form of a patch.</para> 30.34 + 30.35 + <para>Distributors of operating systems that include open source 30.36 + software often need to make changes to the packages they 30.37 + distribute so that they will build properly in their 30.38 + environments.</para> 30.39 + 30.40 + <para>When you have few changes to maintain, it is easy to manage 30.41 + a single patch using the standard <command>diff</command> and 30.42 + <command>patch</command> programs (see section <xref 30.43 + linkend="sec.mq.patch"/> for a discussion of these 30.44 + tools). Once the number of changes grows, it starts to make 30.45 + sense to maintain patches as discrete <quote>chunks of 30.46 + work,</quote> so that for example a single patch will contain 30.47 + only one bug fix (the patch might modify several files, but it's 30.48 + doing <quote>only one thing</quote>), and you may have a number 30.49 + of such patches for different bugs you need fixed and local 30.50 + changes you require. In this situation, if you submit a bug fix 30.51 + patch to the upstream maintainers of a package and they include 30.52 + your fix in a subsequent release, you can simply drop that 30.53 + single patch when you're updating to the newer release.</para> 30.54 + 30.55 + <para>Maintaining a single patch against an upstream tree is a 30.56 + little tedious and error-prone, but not difficult. However, the 30.57 + complexity of the problem grows rapidly as the number of patches 30.58 + you have to maintain increases. With more than a tiny number of 30.59 + patches in hand, understanding which ones you have applied and 30.60 + maintaining them moves from messy to overwhelming.</para> 30.61 + 30.62 + <para>Fortunately, Mercurial includes a powerful extension, 30.63 + Mercurial Queues (or simply <quote>MQ</quote>), that massively 30.64 + simplifies the patch management problem.</para> 30.65 + 30.66 + </sect1> 30.67 + <sect1 id="sec.mq.history"> 30.68 + <title>The prehistory of Mercurial Queues</title> 30.69 + 30.70 + <para>During the late 1990s, several Linux kernel developers 30.71 + started to maintain <quote>patch series</quote> that modified 30.72 + the behaviour of the Linux kernel. Some of these series were 30.73 + focused on stability, some on feature coverage, and others were 30.74 + more speculative.</para> 30.75 + 30.76 + <para>The sizes of these patch series grew rapidly. In 2002, 30.77 + Andrew Morton published some shell scripts he had been using to 30.78 + automate the task of managing his patch queues. Andrew was 30.79 + successfully using these scripts to manage hundreds (sometimes 30.80 + thousands) of patches on top of the Linux kernel.</para> 30.81 + 30.82 + <sect2 id="sec.mq.quilt"> 30.83 + <title>A patchwork quilt</title> 30.84 + 30.85 + <para>In early 2003, Andreas Gruenbacher and Martin Quinson 30.86 + borrowed the approach of Andrew's scripts and published a tool 30.87 + called <quote>patchwork quilt</quote> 30.88 + <citation>web:quilt</citation>, or simply <quote>quilt</quote> 30.89 + (see <citation>gruenbacher:2005</citation> for a paper 30.90 + describing it). Because quilt substantially automated patch 30.91 + management, it rapidly gained a large following among open 30.92 + source software developers.</para> 30.93 + 30.94 + <para>Quilt manages a <emphasis>stack of patches</emphasis> on 30.95 + top of a directory tree. To begin, you tell quilt to manage a 30.96 + directory tree, and tell it which files you want to manage; it 30.97 + stores away the names and contents of those files. To fix a 30.98 + bug, you create a new patch (using a single command), edit the 30.99 + files you need to fix, then <quote>refresh</quote> the 30.100 + patch.</para> 30.101 + 30.102 + <para>The refresh step causes quilt to scan the directory tree; 30.103 + it updates the patch with all of the changes you have made. 30.104 + You can create another patch on top of the first, which will 30.105 + track the changes required to modify the tree from <quote>tree 30.106 + with one patch applied</quote> to <quote>tree with two 30.107 + patches applied</quote>.</para> 30.108 + 30.109 + <para>You can <emphasis>change</emphasis> which patches are 30.110 + applied to the tree. If you <quote>pop</quote> a patch, the 30.111 + changes made by that patch will vanish from the directory 30.112 + tree. Quilt remembers which patches you have popped, though, 30.113 + so you can <quote>push</quote> a popped patch again, and the 30.114 + directory tree will be restored to contain the modifications 30.115 + in the patch. Most importantly, you can run the 30.116 + <quote>refresh</quote> command at any time, and the topmost 30.117 + applied patch will be updated. This means that you can, at 30.118 + any time, change both which patches are applied and what 30.119 + modifications those patches make.</para> 30.120 + 30.121 + <para>Quilt knows nothing about revision control tools, so it 30.122 + works equally well on top of an unpacked tarball or a 30.123 + Subversion working copy.</para> 30.124 + 30.125 + </sect2> 30.126 + <sect2 id="sec.mq.quilt-mq"> 30.127 + <title>From patchwork quilt to Mercurial Queues</title> 30.128 + 30.129 + <para>In mid-2005, Chris Mason took the features of quilt and 30.130 + wrote an extension that he called Mercurial Queues, which 30.131 + added quilt-like behaviour to Mercurial.</para> 30.132 + 30.133 + <para>The key difference between quilt and MQ is that quilt 30.134 + knows nothing about revision control systems, while MQ is 30.135 + <emphasis>integrated</emphasis> into Mercurial. Each patch 30.136 + that you push is represented as a Mercurial changeset. Pop a 30.137 + patch, and the changeset goes away.</para> 30.138 + 30.139 + <para>Because quilt does not care about revision control tools, 30.140 + it is still a tremendously useful piece of software to know 30.141 + about for situations where you cannot use Mercurial and 30.142 + MQ.</para> 30.143 + 30.144 + </sect2> 30.145 + </sect1> 30.146 + <sect1> 30.147 + <title>The huge advantage of MQ</title> 30.148 + 30.149 + <para>I cannot overstate the value that MQ offers through the 30.150 + unification of patches and revision control.</para> 30.151 + 30.152 + <para>A major reason that patches have persisted in the free 30.153 + software and open source world&emdash;in spite of the 30.154 + availability of increasingly capable revision control tools over 30.155 + the years&emdash;is the <emphasis>agility</emphasis> they 30.156 + offer.</para> 30.157 + 30.158 + <para>Traditional revision control tools make a permanent, 30.159 + irreversible record of everything that you do. While this has 30.160 + great value, it's also somewhat stifling. If you want to 30.161 + perform a wild-eyed experiment, you have to be careful in how 30.162 + you go about it, or you risk leaving unneeded&emdash;or worse, 30.163 + misleading or destabilising&emdash;traces of your missteps and 30.164 + errors in the permanent revision record.</para> 30.165 + 30.166 + <para>By contrast, MQ's marriage of distributed revision control 30.167 + with patches makes it much easier to isolate your work. Your 30.168 + patches live on top of normal revision history, and you can make 30.169 + them disappear or reappear at will. If you don't like a patch, 30.170 + you can drop it. If a patch isn't quite as you want it to be, 30.171 + simply fix it&emdash;as many times as you need to, until you 30.172 + have refined it into the form you desire.</para> 30.173 + 30.174 + <para>As an example, the integration of patches with revision 30.175 + control makes understanding patches and debugging their 30.176 + effects&emdash;and their interplay with the code they're based 30.177 + on&emdash;<emphasis>enormously</emphasis> easier. Since every 30.178 + applied patch has an associated changeset, you can give <command 30.179 + role="hg-cmd">hg log</command> a file name to see which 30.180 + changesets and patches affected the file. You can use the 30.181 + <command role="hg-cmd">hg bisect</command> command to 30.182 + binary-search through all changesets and applied patches to see 30.183 + where a bug got introduced or fixed. You can use the <command 30.184 + role="hg-cmd">hg annotate</command> command to see which 30.185 + changeset or patch modified a particular line of a source file. 30.186 + And so on.</para> 30.187 + 30.188 + </sect1> 30.189 + <sect1 id="sec.mq.patch"> 30.190 + <title>Understanding patches</title> 30.191 + 30.192 + <para>Because MQ doesn't hide its patch-oriented nature, it is 30.193 + helpful to understand what patches are, and a little about the 30.194 + tools that work with them.</para> 30.195 + 30.196 + <para>The traditional Unix <command>diff</command> command 30.197 + compares two files, and prints a list of differences between 30.198 + them. The <command>patch</command> command understands these 30.199 + differences as <emphasis>modifications</emphasis> to make to a 30.200 + file. Take a look below for a simple example of these commands 30.201 + in action.</para> 30.202 + 30.203 +&interaction.mq.dodiff.diff; 30.204 + 30.205 + <para>The type of file that <command>diff</command> generates (and 30.206 + <command>patch</command> takes as input) is called a 30.207 + <quote>patch</quote> or a <quote>diff</quote>; there is no 30.208 + difference between a patch and a diff. (We'll use the term 30.209 + <quote>patch</quote>, since it's more commonly used.)</para> 30.210 + 30.211 + <para>A patch file can start with arbitrary text; the 30.212 + <command>patch</command> command ignores this text, but MQ uses 30.213 + it as the commit message when creating changesets. To find the 30.214 + beginning of the patch content, <command>patch</command> 30.215 + searches for the first line that starts with the string 30.216 + <quote><literal>diff -</literal></quote>.</para> 30.217 + 30.218 + <para>MQ works with <emphasis>unified</emphasis> diffs 30.219 + (<command>patch</command> can accept several other diff formats, 30.220 + but MQ doesn't). A unified diff contains two kinds of header. 30.221 + The <emphasis>file header</emphasis> describes the file being 30.222 + modified; it contains the name of the file to modify. When 30.223 + <command>patch</command> sees a new file header, it looks for a 30.224 + file with that name to start modifying.</para> 30.225 + 30.226 + <para>After the file header comes a series of 30.227 + <emphasis>hunks</emphasis>. Each hunk starts with a header; 30.228 + this identifies the range of line numbers within the file that 30.229 + the hunk should modify. Following the header, a hunk starts and 30.230 + ends with a few (usually three) lines of text from the 30.231 + unmodified file; these are called the 30.232 + <emphasis>context</emphasis> for the hunk. If there's only a 30.233 + small amount of context between successive hunks, 30.234 + <command>diff</command> doesn't print a new hunk header; it just 30.235 + runs the hunks together, with a few lines of context between 30.236 + modifications.</para> 30.237 + 30.238 + <para>Each line of context begins with a space character. Within 30.239 + the hunk, a line that begins with 30.240 + <quote><literal>-</literal></quote> means <quote>remove this 30.241 + line,</quote> while a line that begins with 30.242 + <quote><literal>+</literal></quote> means <quote>insert this 30.243 + line.</quote> For example, a line that is modified is 30.244 + represented by one deletion and one insertion.</para> 30.245 + 30.246 + <para>We will return to some of the more subtle aspects of patches 30.247 + later (in section <xref linkend="sec.mq.adv-patch"/>), but you 30.248 + should have 30.249 + enough information now to use MQ.</para> 30.250 + 30.251 + </sect1> 30.252 + <sect1 id="sec.mq.start"> 30.253 + <title>Getting started with Mercurial Queues</title> 30.254 + 30.255 + <para>Because MQ is implemented as an extension, you must 30.256 + explicitly enable before you can use it. (You don't need to 30.257 + download anything; MQ ships with the standard Mercurial 30.258 + distribution.) To enable MQ, edit your <filename 30.259 + role="home">~/.hgrc</filename> file, and add the lines 30.260 + below.</para> 30.261 + 30.262 + <programlisting>[extensions] 30.263 +hgext.mq =</programlisting> 30.264 + 30.265 + <para>Once the extension is enabled, it will make a number of new 30.266 + commands available. To verify that the extension is working, 30.267 + you can use <command role="hg-cmd">hg help</command> to see if 30.268 + the <command role="hg-ext-mq">qinit</command> command is now 30.269 + available.</para> 30.270 + 30.271 +&interaction.mq.qinit-help.help; 30.272 + 30.273 + <para>You can use MQ with <emphasis>any</emphasis> Mercurial 30.274 + repository, and its commands only operate within that 30.275 + repository. To get started, simply prepare the repository using 30.276 + the <command role="hg-ext-mq">qinit</command> command.</para> 30.277 + 30.278 +&interaction.mq.tutorial.qinit; 30.279 + 30.280 + <para>This command creates an empty directory called <filename 30.281 + role="special" class="directory">.hg/patches</filename>, where 30.282 + MQ will keep its metadata. As with many Mercurial commands, the 30.283 + <command role="hg-ext-mq">qinit</command> command prints nothing 30.284 + if it succeeds.</para> 30.285 + 30.286 + <sect2> 30.287 + <title>Creating a new patch</title> 30.288 + 30.289 + <para>To begin work on a new patch, use the <command 30.290 + role="hg-ext-mq">qnew</command> command. This command takes 30.291 + one argument, the name of the patch to create.</para> 30.292 + 30.293 + <para>MQ will use this as the name of an actual file in the 30.294 + <filename role="special" 30.295 + class="directory">.hg/patches</filename> directory, as you 30.296 + can see below.</para> 30.297 + 30.298 +&interaction.mq.tutorial.qnew; 30.299 + 30.300 + <para>Also newly present in the <filename role="special" 30.301 + class="directory">.hg/patches</filename> directory are two 30.302 + other files, <filename role="special">series</filename> and 30.303 + <filename role="special">status</filename>. The <filename 30.304 + role="special">series</filename> file lists all of the 30.305 + patches that MQ knows about for this repository, with one 30.306 + patch per line. Mercurial uses the <filename 30.307 + role="special">status</filename> file for internal 30.308 + book-keeping; it tracks all of the patches that MQ has 30.309 + <emphasis>applied</emphasis> in this repository.</para> 30.310 + 30.311 + <note> 30.312 + <para> You may sometimes want to edit the <filename 30.313 + role="special">series</filename> file by hand; for 30.314 + example, to change the sequence in which some patches are 30.315 + applied. However, manually editing the <filename 30.316 + role="special">status</filename> file is almost always a 30.317 + bad idea, as it's easy to corrupt MQ's idea of what is 30.318 + happening.</para> 30.319 + </note> 30.320 + 30.321 + <para>Once you have created your new patch, you can edit files 30.322 + in the working directory as you usually would. All of the 30.323 + normal Mercurial commands, such as <command role="hg-cmd">hg 30.324 + diff</command> and <command role="hg-cmd">hg 30.325 + annotate</command>, work exactly as they did before.</para> 30.326 + 30.327 + </sect2> 30.328 + <sect2> 30.329 + <title>Refreshing a patch</title> 30.330 + 30.331 + <para>When you reach a point where you want to save your work, 30.332 + use the <command role="hg-ext-mq">qrefresh</command> command 30.333 + to update the patch you are working on.</para> 30.334 + 30.335 +&interaction.mq.tutorial.qrefresh; 30.336 + 30.337 + <para>This command folds the changes you have made in the 30.338 + working directory into your patch, and updates its 30.339 + corresponding changeset to contain those changes.</para> 30.340 + 30.341 + <para>You can run <command role="hg-ext-mq">qrefresh</command> 30.342 + as often as you like, so it's a good way to 30.343 + <quote>checkpoint</quote> your work. Refresh your patch at an 30.344 + opportune time; try an experiment; and if the experiment 30.345 + doesn't work out, <command role="hg-cmd">hg revert</command> 30.346 + your modifications back to the last time you refreshed.</para> 30.347 + 30.348 +&interaction.mq.tutorial.qrefresh2; 30.349 + 30.350 + </sect2> 30.351 + <sect2> 30.352 + <title>Stacking and tracking patches</title> 30.353 + 30.354 + <para>Once you have finished working on a patch, or need to work 30.355 + on another, you can use the <command 30.356 + role="hg-ext-mq">qnew</command> command again to create a 30.357 + new patch. Mercurial will apply this patch on top of your 30.358 + existing patch.</para> 30.359 + 30.360 +&interaction.mq.tutorial.qnew2; 30.361 + <para>Notice that the patch contains the changes in our prior 30.362 + patch as part of its context (you can see this more clearly in 30.363 + the output of <command role="hg-cmd">hg 30.364 + annotate</command>).</para> 30.365 + 30.366 + <para>So far, with the exception of <command 30.367 + role="hg-ext-mq">qnew</command> and <command 30.368 + role="hg-ext-mq">qrefresh</command>, we've been careful to 30.369 + only use regular Mercurial commands. However, MQ provides 30.370 + many commands that are easier to use when you are thinking 30.371 + about patches, as illustrated below.</para> 30.372 + 30.373 +&interaction.mq.tutorial.qseries; 30.374 + 30.375 + <itemizedlist> 30.376 + <listitem><para>The <command 30.377 + role="hg-ext-mq">qseries</command> command lists every 30.378 + patch that MQ knows about in this repository, from oldest 30.379 + to newest (most recently 30.380 + <emphasis>created</emphasis>).</para> 30.381 + </listitem> 30.382 + <listitem><para>The <command 30.383 + role="hg-ext-mq">qapplied</command> command lists every 30.384 + patch that MQ has <emphasis>applied</emphasis> in this 30.385 + repository, again from oldest to newest (most recently 30.386 + applied).</para> 30.387 + </listitem></itemizedlist> 30.388 + 30.389 + </sect2> 30.390 + <sect2> 30.391 + <title>Manipulating the patch stack</title> 30.392 + 30.393 + <para>The previous discussion implied that there must be a 30.394 + difference between <quote>known</quote> and 30.395 + <quote>applied</quote> patches, and there is. MQ can manage a 30.396 + patch without it being applied in the repository.</para> 30.397 + 30.398 + <para>An <emphasis>applied</emphasis> patch has a corresponding 30.399 + changeset in the repository, and the effects of the patch and 30.400 + changeset are visible in the working directory. You can undo 30.401 + the application of a patch using the <command 30.402 + role="hg-ext-mq">qpop</command> command. MQ still 30.403 + <emphasis>knows about</emphasis>, or manages, a popped patch, 30.404 + but the patch no longer has a corresponding changeset in the 30.405 + repository, and the working directory does not contain the 30.406 + changes made by the patch. Figure <xref 30.407 + endterm="fig.mq.stack.caption" linkend="fig.mq.stack"/> illustrates 30.408 + the difference between applied and tracked patches.</para> 30.409 + 30.410 + <informalfigure id="fig.mq.stack"> 30.411 + <mediaobject> 30.412 + <imageobject><imagedata fileref="images/mq-stack.png"/></imageobject> 30.413 + <textobject><phrase>XXX add text</phrase></textobject> 30.414 + <caption><para id="fig.mq.stack.caption">Applied and unapplied patches 30.415 + in the MQ patch stack</para></caption> 30.416 + </mediaobject> 30.417 + </informalfigure> 30.418 + 30.419 + <para>You can reapply an unapplied, or popped, patch using the 30.420 + <command role="hg-ext-mq">qpush</command> command. This 30.421 + creates a new changeset to correspond to the patch, and the 30.422 + patch's changes once again become present in the working 30.423 + directory. See below for examples of <command 30.424 + role="hg-ext-mq">qpop</command> and <command 30.425 + role="hg-ext-mq">qpush</command> in action.</para> 30.426 +&interaction.mq.tutorial.qpop; 30.427 + 30.428 + <para>Notice that once we have popped a patch or two patches, 30.429 + the output of <command role="hg-ext-mq">qseries</command> 30.430 + remains the same, while that of <command 30.431 + role="hg-ext-mq">qapplied</command> has changed.</para> 30.432 + 30.433 + 30.434 + </sect2> 30.435 + <sect2> 30.436 + <title>Pushing and popping many patches</title> 30.437 + 30.438 + <para>While <command role="hg-ext-mq">qpush</command> and 30.439 + <command role="hg-ext-mq">qpop</command> each operate on a 30.440 + single patch at a time by default, you can push and pop many 30.441 + patches in one go. The <option 30.442 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to 30.443 + <command role="hg-ext-mq">qpush</command> causes it to push 30.444 + all unapplied patches, while the <option 30.445 + role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command 30.446 + role="hg-ext-mq">qpop</command> causes it to pop all applied 30.447 + patches. (For some more ways to push and pop many patches, 30.448 + see section <xref linkend="sec.mq.perf"/> 30.449 + below.)</para> 30.450 + 30.451 +&interaction.mq.tutorial.qpush-a; 30.452 + 30.453 + </sect2> 30.454 + <sect2> 30.455 + <title>Safety checks, and overriding them</title> 30.456 + 30.457 + <para>Several MQ commands check the working directory before 30.458 + they do anything, and fail if they find any modifications. 30.459 + They do this to ensure that you won't lose any changes that 30.460 + you have made, but not yet incorporated into a patch. The 30.461 + example below illustrates this; the <command 30.462 + role="hg-ext-mq">qnew</command> command will not create a 30.463 + new patch if there are outstanding changes, caused in this 30.464 + case by the <command role="hg-cmd">hg add</command> of 30.465 + <filename>file3</filename>.</para> 30.466 + 30.467 +&interaction.mq.tutorial.add; 30.468 + 30.469 + <para>Commands that check the working directory all take an 30.470 + <quote>I know what I'm doing</quote> option, which is always 30.471 + named <option>-f</option>. The exact meaning of 30.472 + <option>-f</option> depends on the command. For example, 30.473 + <command role="hg-cmd">hg qnew <option 30.474 + role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command> 30.475 + will incorporate any outstanding changes into the new patch it 30.476 + creates, but <command role="hg-cmd">hg qpop <option 30.477 + role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command> 30.478 + will revert modifications to any files affected by the patch 30.479 + that it is popping. Be sure to read the documentation for a 30.480 + command's <option>-f</option> option before you use it!</para> 30.481 + 30.482 + </sect2> 30.483 + <sect2> 30.484 + <title>Working on several patches at once</title> 30.485 + 30.486 + <para>The <command role="hg-ext-mq">qrefresh</command> command 30.487 + always refreshes the <emphasis>topmost</emphasis> applied 30.488 + patch. This means that you can suspend work on one patch (by 30.489 + refreshing it), pop or push to make a different patch the top, 30.490 + and work on <emphasis>that</emphasis> patch for a 30.491 + while.</para> 30.492 + 30.493 + <para>Here's an example that illustrates how you can use this 30.494 + ability. Let's say you're developing a new feature as two 30.495 + patches. The first is a change to the core of your software, 30.496 + and the second&emdash;layered on top of the 30.497 + first&emdash;changes the user interface to use the code you 30.498 + just added to the core. If you notice a bug in the core while 30.499 + you're working on the UI patch, it's easy to fix the core. 30.500 + Simply <command role="hg-ext-mq">qrefresh</command> the UI 30.501 + patch to save your in-progress changes, and <command 30.502 + role="hg-ext-mq">qpop</command> down to the core patch. Fix 30.503 + the core bug, <command role="hg-ext-mq">qrefresh</command> the 30.504 + core patch, and <command role="hg-ext-mq">qpush</command> back 30.505 + to the UI patch to continue where you left off.</para> 30.506 + 30.507 + </sect2> 30.508 + </sect1> 30.509 + <sect1 id="sec.mq.adv-patch"> 30.510 + <title>More about patches</title> 30.511 + 30.512 + <para>MQ uses the GNU <command>patch</command> command to apply 30.513 + patches, so it's helpful to know a few more detailed aspects of 30.514 + how <command>patch</command> works, and about patches 30.515 + themselves.</para> 30.516 + 30.517 + <sect2> 30.518 + <title>The strip count</title> 30.519 + 30.520 + <para>If you look at the file headers in a patch, you will 30.521 + notice that the pathnames usually have an extra component on 30.522 + the front that isn't present in the actual path name. This is 30.523 + a holdover from the way that people used to generate patches 30.524 + (people still do this, but it's somewhat rare with modern 30.525 + revision control tools).</para> 30.526 + 30.527 + <para>Alice would unpack a tarball, edit her files, then decide 30.528 + that she wanted to create a patch. So she'd rename her 30.529 + working directory, unpack the tarball again (hence the need 30.530 + for the rename), and use the <option 30.531 + role="cmd-opt-diff">-r</option> and <option 30.532 + role="cmd-opt-diff">-N</option> options to 30.533 + <command>diff</command> to recursively generate a patch 30.534 + between the unmodified directory and the modified one. The 30.535 + result would be that the name of the unmodified directory 30.536 + would be at the front of the left-hand path in every file 30.537 + header, and the name of the modified directory would be at the 30.538 + front of the right-hand path.</para> 30.539 + 30.540 + <para>Since someone receiving a patch from the Alices of the net 30.541 + would be unlikely to have unmodified and modified directories 30.542 + with exactly the same names, the <command>patch</command> 30.543 + command has a <option role="cmd-opt-patch">-p</option> option 30.544 + that indicates the number of leading path name components to 30.545 + strip when trying to apply a patch. This number is called the 30.546 + <emphasis>strip count</emphasis>.</para> 30.547 + 30.548 + <para>An option of <quote><literal>-p1</literal></quote> means 30.549 + <quote>use a strip count of one</quote>. If 30.550 + <command>patch</command> sees a file name 30.551 + <filename>foo/bar/baz</filename> in a file header, it will 30.552 + strip <filename>foo</filename> and try to patch a file named 30.553 + <filename>bar/baz</filename>. (Strictly speaking, the strip 30.554 + count refers to the number of <emphasis>path 30.555 + separators</emphasis> (and the components that go with them 30.556 + ) to strip. A strip count of one will turn 30.557 + <filename>foo/bar</filename> into <filename>bar</filename>, 30.558 + but <filename>/foo/bar</filename> (notice the extra leading 30.559 + slash) into <filename>foo/bar</filename>.)</para> 30.560 + 30.561 + <para>The <quote>standard</quote> strip count for patches is 30.562 + one; almost all patches contain one leading path name 30.563 + component that needs to be stripped. Mercurial's <command 30.564 + role="hg-cmd">hg diff</command> command generates path names 30.565 + in this form, and the <command role="hg-cmd">hg 30.566 + import</command> command and MQ expect patches to have a 30.567 + strip count of one.</para> 30.568 + 30.569 + <para>If you receive a patch from someone that you want to add 30.570 + to your patch queue, and the patch needs a strip count other 30.571 + than one, you cannot just <command 30.572 + role="hg-ext-mq">qimport</command> the patch, because 30.573 + <command role="hg-ext-mq">qimport</command> does not yet have 30.574 + a <literal>-p</literal> option (see <ulink role="hg-bug" 30.575 + url="http://www.selenic.com/mercurial/bts/issue311">issue 30.576 + 311</ulink>). Your best bet is to <command 30.577 + role="hg-ext-mq">qnew</command> a patch of your own, then 30.578 + use <command>patch -pN</command> to apply their patch, 30.579 + followed by <command role="hg-cmd">hg addremove</command> to 30.580 + pick up any files added or removed by the patch, followed by 30.581 + <command role="hg-ext-mq">hg qrefresh</command>. This 30.582 + complexity may become unnecessary; see <ulink role="hg-bug" 30.583 + url="http://www.selenic.com/mercurial/bts/issue311">issue 30.584 + 311</ulink> for details. 30.585 + </para> 30.586 + </sect2> 30.587 + <sect2> 30.588 + <title>Strategies for applying a patch</title> 30.589 + 30.590 + <para>When <command>patch</command> applies a hunk, it tries a 30.591 + handful of successively less accurate strategies to try to 30.592 + make the hunk apply. This falling-back technique often makes 30.593 + it possible to take a patch that was generated against an old 30.594 + version of a file, and apply it against a newer version of 30.595 + that file.</para> 30.596 + 30.597 + <para>First, <command>patch</command> tries an exact match, 30.598 + where the line numbers, the context, and the text to be 30.599 + modified must apply exactly. If it cannot make an exact 30.600 + match, it tries to find an exact match for the context, 30.601 + without honouring the line numbering information. If this 30.602 + succeeds, it prints a line of output saying that the hunk was 30.603 + applied, but at some <emphasis>offset</emphasis> from the 30.604 + original line number.</para> 30.605 + 30.606 + <para>If a context-only match fails, <command>patch</command> 30.607 + removes the first and last lines of the context, and tries a 30.608 + <emphasis>reduced</emphasis> context-only match. If the hunk 30.609 + with reduced context succeeds, it prints a message saying that 30.610 + it applied the hunk with a <emphasis>fuzz factor</emphasis> 30.611 + (the number after the fuzz factor indicates how many lines of 30.612 + context <command>patch</command> had to trim before the patch 30.613 + applied).</para> 30.614 + 30.615 + <para>When neither of these techniques works, 30.616 + <command>patch</command> prints a message saying that the hunk 30.617 + in question was rejected. It saves rejected hunks (also 30.618 + simply called <quote>rejects</quote>) to a file with the same 30.619 + name, and an added <filename role="special">.rej</filename> 30.620 + extension. It also saves an unmodified copy of the file with 30.621 + a <filename role="special">.orig</filename> extension; the 30.622 + copy of the file without any extensions will contain any 30.623 + changes made by hunks that <emphasis>did</emphasis> apply 30.624 + cleanly. If you have a patch that modifies 30.625 + <filename>foo</filename> with six hunks, and one of them fails 30.626 + to apply, you will have: an unmodified 30.627 + <filename>foo.orig</filename>, a <filename>foo.rej</filename> 30.628 + containing one hunk, and <filename>foo</filename>, containing 30.629 + the changes made by the five successful hunks.</para> 30.630 + 30.631 + </sect2> 30.632 + <sect2> 30.633 + <title>Some quirks of patch representation</title> 30.634 + 30.635 + <para>There are a few useful things to know about how 30.636 + <command>patch</command> works with files.</para> 30.637 + <itemizedlist> 30.638 + <listitem><para>This should already be obvious, but 30.639 + <command>patch</command> cannot handle binary 30.640 + files.</para> 30.641 + </listitem> 30.642 + <listitem><para>Neither does it care about the executable bit; 30.643 + it creates new files as readable, but not 30.644 + executable.</para> 30.645 + </listitem> 30.646 + <listitem><para><command>patch</command> treats the removal of 30.647 + a file as a diff between the file to be removed and the 30.648 + empty file. So your idea of <quote>I deleted this 30.649 + file</quote> looks like <quote>every line of this file 30.650 + was deleted</quote> in a patch.</para> 30.651 + </listitem> 30.652 + <listitem><para>It treats the addition of a file as a diff 30.653 + between the empty file and the file to be added. So in a 30.654 + patch, your idea of <quote>I added this file</quote> looks 30.655 + like <quote>every line of this file was 30.656 + added</quote>.</para> 30.657 + </listitem> 30.658 + <listitem><para>It treats a renamed file as the removal of the 30.659 + old name, and the addition of the new name. This means 30.660 + that renamed files have a big footprint in patches. (Note 30.661 + also that Mercurial does not currently try to infer when 30.662 + files have been renamed or copied in a patch.)</para> 30.663 + </listitem> 30.664 + <listitem><para><command>patch</command> cannot represent 30.665 + empty files, so you cannot use a patch to represent the 30.666 + notion <quote>I added this empty file to the 30.667 + tree</quote>.</para> 30.668 + </listitem></itemizedlist> 30.669 + </sect2> 30.670 + <sect2> 30.671 + <title>Beware the fuzz</title> 30.672 + 30.673 + <para>While applying a hunk at an offset, or with a fuzz factor, 30.674 + will often be completely successful, these inexact techniques 30.675 + naturally leave open the possibility of corrupting the patched 30.676 + file. The most common cases typically involve applying a 30.677 + patch twice, or at an incorrect location in the file. If 30.678 + <command>patch</command> or <command 30.679 + role="hg-ext-mq">qpush</command> ever mentions an offset or 30.680 + fuzz factor, you should make sure that the modified files are 30.681 + correct afterwards.</para> 30.682 + 30.683 + <para>It's often a good idea to refresh a patch that has applied 30.684 + with an offset or fuzz factor; refreshing the patch generates 30.685 + new context information that will make it apply cleanly. I 30.686 + say <quote>often,</quote> not <quote>always,</quote> because 30.687 + sometimes refreshing a patch will make it fail to apply 30.688 + against a different revision of the underlying files. In some 30.689 + cases, such as when you're maintaining a patch that must sit 30.690 + on top of multiple versions of a source tree, it's acceptable 30.691 + to have a patch apply with some fuzz, provided you've verified 30.692 + the results of the patching process in such cases.</para> 30.693 + 30.694 + </sect2> 30.695 + <sect2> 30.696 + <title>Handling rejection</title> 30.697 + 30.698 + <para>If <command role="hg-ext-mq">qpush</command> fails to 30.699 + apply a patch, it will print an error message and exit. If it 30.700 + has left <filename role="special">.rej</filename> files 30.701 + behind, it is usually best to fix up the rejected hunks before 30.702 + you push more patches or do any further work.</para> 30.703 + 30.704 + <para>If your patch <emphasis>used to</emphasis> apply cleanly, 30.705 + and no longer does because you've changed the underlying code 30.706 + that your patches are based on, Mercurial Queues can help; see 30.707 + section <xref 30.708 + linkend="sec.mq.merge"/> for details.</para> 30.709 + 30.710 + <para>Unfortunately, there aren't any great techniques for 30.711 + dealing with rejected hunks. Most often, you'll need to view 30.712 + the <filename role="special">.rej</filename> file and edit the 30.713 + target file, applying the rejected hunks by hand.</para> 30.714 + 30.715 + <para>If you're feeling adventurous, Neil Brown, a Linux kernel 30.716 + hacker, wrote a tool called <command>wiggle</command> 30.717 + <citation>web:wiggle</citation>, which is more vigorous than 30.718 + <command>patch</command> in its attempts to make a patch 30.719 + apply.</para> 30.720 + 30.721 + <para>Another Linux kernel hacker, Chris Mason (the author of 30.722 + Mercurial Queues), wrote a similar tool called 30.723 + <command>mpatch</command> <citation>web:mpatch</citation>, 30.724 + which takes a simple approach to automating the application of 30.725 + hunks rejected by <command>patch</command>. The 30.726 + <command>mpatch</command> command can help with four common 30.727 + reasons that a hunk may be rejected:</para> 30.728 + 30.729 + <itemizedlist> 30.730 + <listitem><para>The context in the middle of a hunk has 30.731 + changed.</para> 30.732 + </listitem> 30.733 + <listitem><para>A hunk is missing some context at the 30.734 + beginning or end.</para> 30.735 + </listitem> 30.736 + <listitem><para>A large hunk might apply better&emdash;either 30.737 + entirely or in part&emdash;if it was broken up into 30.738 + smaller hunks.</para> 30.739 + </listitem> 30.740 + <listitem><para>A hunk removes lines with slightly different 30.741 + content than those currently present in the file.</para> 30.742 + </listitem></itemizedlist> 30.743 + 30.744 + <para>If you use <command>wiggle</command> or 30.745 + <command>mpatch</command>, you should be doubly careful to 30.746 + check your results when you're done. In fact, 30.747 + <command>mpatch</command> enforces this method of 30.748 + double-checking the tool's output, by automatically dropping 30.749 + you into a merge program when it has done its job, so that you 30.750 + can verify its work and finish off any remaining 30.751 + merges.</para> 30.752 + 30.753 + </sect2> 30.754 + </sect1> 30.755 + <sect1 id="sec.mq.perf"> 30.756 + <title>Getting the best performance out of MQ</title> 30.757 + 30.758 + <para>MQ is very efficient at handling a large number of patches. 30.759 + I ran some performance experiments in mid-2006 for a talk that I 30.760 + gave at the 2006 EuroPython conference 30.761 + <citation>web:europython</citation>. I used as my data set the 30.762 + Linux 2.6.17-mm1 patch series, which consists of 1,738 patches. 30.763 + I applied these on top of a Linux kernel repository containing 30.764 + all 27,472 revisions between Linux 2.6.12-rc2 and Linux 30.765 + 2.6.17.</para> 30.766 + 30.767 + <para>On my old, slow laptop, I was able to <command 30.768 + role="hg-cmd">hg qpush <option 30.769 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all 30.770 + 1,738 patches in 3.5 minutes, and <command role="hg-cmd">hg qpop 30.771 + <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> 30.772 + them all in 30 seconds. (On a newer laptop, the time to push 30.773 + all patches dropped to two minutes.) I could <command 30.774 + role="hg-ext-mq">qrefresh</command> one of the biggest patches 30.775 + (which made 22,779 lines of changes to 287 files) in 6.6 30.776 + seconds.</para> 30.777 + 30.778 + <para>Clearly, MQ is well suited to working in large trees, but 30.779 + there are a few tricks you can use to get the best performance 30.780 + of it.</para> 30.781 + 30.782 + <para>First of all, try to <quote>batch</quote> operations 30.783 + together. Every time you run <command 30.784 + role="hg-ext-mq">qpush</command> or <command 30.785 + role="hg-ext-mq">qpop</command>, these commands scan the 30.786 + working directory once to make sure you haven't made some 30.787 + changes and then forgotten to run <command 30.788 + role="hg-ext-mq">qrefresh</command>. On a small tree, the 30.789 + time that this scan takes is unnoticeable. However, on a 30.790 + medium-sized tree (containing tens of thousands of files), it 30.791 + can take a second or more.</para> 30.792 + 30.793 + <para>The <command role="hg-ext-mq">qpush</command> and <command 30.794 + role="hg-ext-mq">qpop</command> commands allow you to push and 30.795 + pop multiple patches at a time. You can identify the 30.796 + <quote>destination patch</quote> that you want to end up at. 30.797 + When you <command role="hg-ext-mq">qpush</command> with a 30.798 + destination specified, it will push patches until that patch is 30.799 + at the top of the applied stack. When you <command 30.800 + role="hg-ext-mq">qpop</command> to a destination, MQ will pop 30.801 + patches until the destination patch is at the top.</para> 30.802 + 30.803 + <para>You can identify a destination patch using either the name 30.804 + of the patch, or by number. If you use numeric addressing, 30.805 + patches are counted from zero; this means that the first patch 30.806 + is zero, the second is one, and so on.</para> 30.807 + 30.808 + </sect1> 30.809 + <sect1 id="sec.mq.merge"> 30.810 + <title>Updating your patches when the underlying code 30.811 + changes</title> 30.812 + 30.813 + <para>It's common to have a stack of patches on top of an 30.814 + underlying repository that you don't modify directly. If you're 30.815 + working on changes to third-party code, or on a feature that is 30.816 + taking longer to develop than the rate of change of the code 30.817 + beneath, you will often need to sync up with the underlying 30.818 + code, and fix up any hunks in your patches that no longer apply. 30.819 + This is called <emphasis>rebasing</emphasis> your patch 30.820 + series.</para> 30.821 + 30.822 + <para>The simplest way to do this is to <command role="hg-cmd">hg 30.823 + qpop <option role="hg-ext-mq-cmd-qpop-opt">hg 30.824 + -a</option></command> your patches, then <command 30.825 + role="hg-cmd">hg pull</command> changes into the underlying 30.826 + repository, and finally <command role="hg-cmd">hg qpush <option 30.827 + role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your 30.828 + patches again. MQ will stop pushing any time it runs across a 30.829 + patch that fails to apply during conflicts, allowing you to fix 30.830 + your conflicts, <command role="hg-ext-mq">qrefresh</command> the 30.831 + affected patch, and continue pushing until you have fixed your 30.832 + entire stack.</para> 30.833 + 30.834 + <para>This approach is easy to use and works well if you don't 30.835 + expect changes to the underlying code to affect how well your 30.836 + patches apply. If your patch stack touches code that is modified 30.837 + frequently or invasively in the underlying repository, however, 30.838 + fixing up rejected hunks by hand quickly becomes 30.839 + tiresome.</para> 30.840 + 30.841 + <para>It's possible to partially automate the rebasing process. 30.842 + If your patches apply cleanly against some revision of the 30.843 + underlying repo, MQ can use this information to help you to 30.844 + resolve conflicts between your patches and a different 30.845 + revision.</para> 30.846 + 30.847 + <para>The process is a little involved.</para> 30.848 + <orderedlist> 30.849 + <listitem><para>To begin, <command role="hg-cmd">hg qpush 30.850 + -a</command> all of your patches on top of the revision 30.851 + where you know that they apply cleanly.</para> 30.852 + </listitem> 30.853 + <listitem><para>Save a backup copy of your patch directory using 30.854 + <command role="hg-cmd">hg qsave <option 30.855 + role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option 30.856 + role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>. 30.857 + This prints the name of the directory that it has saved the 30.858 + patches in. It will save the patches to a directory called 30.859 + <filename role="special" 30.860 + class="directory">.hg/patches.N</filename>, where 30.861 + <literal>N</literal> is a small integer. It also commits a 30.862 + <quote>save changeset</quote> on top of your applied 30.863 + patches; this is for internal book-keeping, and records the 30.864 + states of the <filename role="special">series</filename> and 30.865 + <filename role="special">status</filename> files.</para> 30.866 + </listitem> 30.867 + <listitem><para>Use <command role="hg-cmd">hg pull</command> to 30.868 + bring new changes into the underlying repository. (Don't 30.869 + run <command role="hg-cmd">hg pull -u</command>; see below 30.870 + for why.)</para> 30.871 + </listitem> 30.872 + <listitem><para>Update to the new tip revision, using <command 30.873 + role="hg-cmd">hg update <option 30.874 + role="hg-opt-update">-C</option></command> to override 30.875 + the patches you have pushed.</para> 30.876 + </listitem> 30.877 + <listitem><para>Merge all patches using <command>hg qpush -m 30.878 + -a</command>. The <option 30.879 + role="hg-ext-mq-cmd-qpush-opt">-m</option> option to 30.880 + <command role="hg-ext-mq">qpush</command> tells MQ to 30.881 + perform a three-way merge if the patch fails to 30.882 + apply.</para> 30.883 + </listitem></orderedlist> 30.884 + 30.885 + <para>During the <command role="hg-cmd">hg qpush <option 30.886 + role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>, 30.887 + each patch in the <filename role="special">series</filename> 30.888 + file is applied normally. If a patch applies with fuzz or 30.889 + rejects, MQ looks at the queue you <command 30.890 + role="hg-ext-mq">qsave</command>d, and performs a three-way 30.891 + merge with the corresponding changeset. This merge uses 30.892 + Mercurial's normal merge machinery, so it may pop up a GUI merge 30.893 + tool to help you to resolve problems.</para> 30.894 + 30.895 + <para>When you finish resolving the effects of a patch, MQ 30.896 + refreshes your patch based on the result of the merge.</para> 30.897 + 30.898 + <para>At the end of this process, your repository will have one 30.899 + extra head from the old patch queue, and a copy of the old patch 30.900 + queue will be in <filename role="special" 30.901 + class="directory">.hg/patches.N</filename>. You can remove the 30.902 + extra head using <command role="hg-cmd">hg qpop -a -n 30.903 + patches.N</command> or <command role="hg-cmd">hg 30.904 + strip</command>. You can delete <filename role="special" 30.905 + class="directory">.hg/patches.N</filename> once you are sure 30.906 + that you no longer need it as a backup.</para> 30.907 + 30.908 + </sect1> 30.909 + <sect1> 30.910 + <title>Identifying patches</title> 30.911 + 30.912 + <para>MQ commands that work with patches let you refer to a patch 30.913 + either by using its name or by a number. By name is obvious 30.914 + enough; pass the name <filename>foo.patch</filename> to <command 30.915 + role="hg-ext-mq">qpush</command>, for example, and it will 30.916 + push patches until <filename>foo.patch</filename> is 30.917 + applied.</para> 30.918 + 30.919 + <para>As a shortcut, you can refer to a patch using both a name 30.920 + and a numeric offset; <literal>foo.patch-2</literal> means 30.921 + <quote>two patches before <literal>foo.patch</literal></quote>, 30.922 + while <literal>bar.patch+4</literal> means <quote>four patches 30.923 + after <literal>bar.patch</literal></quote>.</para> 30.924 + 30.925 + <para>Referring to a patch by index isn't much different. The 30.926 + first patch printed in the output of <command 30.927 + role="hg-ext-mq">qseries</command> is patch zero (yes, it's 30.928 + one of those start-at-zero counting systems); the second is 30.929 + patch one; and so on.</para> 30.930 + 30.931 + <para>MQ also makes it easy to work with patches when you are 30.932 + using normal Mercurial commands. Every command that accepts a 30.933 + changeset ID will also accept the name of an applied patch. MQ 30.934 + augments the tags normally in the repository with an eponymous 30.935 + one for each applied patch. In addition, the special tags 30.936 + <literal role="tag">qbase</literal> and 30.937 + <literal role="tag">qtip</literal> identify 30.938 + the <quote>bottom-most</quote> and topmost applied patches, 30.939 + respectively.</para> 30.940 + 30.941 + <para>These additions to Mercurial's normal tagging capabilities 30.942 + make dealing with patches even more of a breeze.</para> 30.943 + <itemizedlist> 30.944 + <listitem><para>Want to patchbomb a mailing list with your 30.945 + latest series of changes?</para> 30.946 + <programlisting>hg email qbase:qtip</programlisting> 30.947 + <para> (Don't know what <quote>patchbombing</quote> is? See 30.948 + section <xref linkend="sec.hgext.patchbomb"/>.)</para> 30.949 + </listitem> 30.950 + <listitem><para>Need to see all of the patches since 30.951 + <literal>foo.patch</literal> that have touched files in a 30.952 + subdirectory of your tree?</para> 30.953 + <programlisting>hg log -r foo.patch:qtip subdir</programlisting> 30.954 + </listitem> 30.955 + </itemizedlist> 30.956 + 30.957 + <para>Because MQ makes the names of patches available to the rest 30.958 + of Mercurial through its normal internal tag machinery, you 30.959 + don't need to type in the entire name of a patch when you want 30.960 + to identify it by name.</para> 30.961 + 30.962 + <para>Another nice consequence of representing patch names as tags 30.963 + is that when you run the <command role="hg-cmd">hg log</command> 30.964 + command, it will display a patch's name as a tag, simply as part 30.965 + of its normal output. This makes it easy to visually 30.966 + distinguish applied patches from underlying 30.967 + <quote>normal</quote> revisions. The following example shows a 30.968 + few normal Mercurial commands in use with applied 30.969 + patches.</para> 30.970 + 30.971 +&interaction.mq.id.output; 30.972 + 30.973 + </sect1> 30.974 + <sect1> 30.975 + <title>Useful things to know about</title> 30.976 + 30.977 + <para>There are a number of aspects of MQ usage that don't fit 30.978 + tidily into sections of their own, but that are good to know. 30.979 + Here they are, in one place.</para> 30.980 + 30.981 + <itemizedlist> 30.982 + <listitem><para>Normally, when you <command 30.983 + role="hg-ext-mq">qpop</command> a patch and <command 30.984 + role="hg-ext-mq">qpush</command> it again, the changeset 30.985 + that represents the patch after the pop/push will have a 30.986 + <emphasis>different identity</emphasis> than the changeset 30.987 + that represented the hash beforehand. See section <xref 30.988 + linkend="sec.mqref.cmd.qpush"/> for 30.989 + information as to why this is.</para> 30.990 + </listitem> 30.991 + <listitem><para>It's not a good idea to <command 30.992 + role="hg-cmd">hg merge</command> changes from another 30.993 + branch with a patch changeset, at least if you want to 30.994 + maintain the <quote>patchiness</quote> of that changeset and 30.995 + changesets below it on the patch stack. If you try to do 30.996 + this, it will appear to succeed, but MQ will become 30.997 + confused.</para> 30.998 + </listitem></itemizedlist> 30.999 + 30.1000 + </sect1> 30.1001 + <sect1 id="sec.mq.repo"> 30.1002 + <title>Managing patches in a repository</title> 30.1003 + 30.1004 + <para>Because MQ's <filename role="special" 30.1005 + class="directory">.hg/patches</filename> directory resides 30.1006 + outside a Mercurial repository's working directory, the 30.1007 + <quote>underlying</quote> Mercurial repository knows nothing 30.1008 + about the management or presence of patches.</para> 30.1009 + 30.1010 + <para>This presents the interesting possibility of managing the 30.1011 + contents of the patch directory as a Mercurial repository in its 30.1012 + own right. This can be a useful way to work. For example, you 30.1013 + can work on a patch for a while, <command 30.1014 + role="hg-ext-mq">qrefresh</command> it, then <command 30.1015 + role="hg-cmd">hg commit</command> the current state of the 30.1016 + patch. This lets you <quote>roll back</quote> to that version 30.1017 + of the patch later on.</para> 30.1018 + 30.1019 + <para>You can then share different versions of the same patch 30.1020 + stack among multiple underlying repositories. I use this when I 30.1021 + am developing a Linux kernel feature. I have a pristine copy of 30.1022 + my kernel sources for each of several CPU architectures, and a 30.1023 + cloned repository under each that contains the patches I am 30.1024 + working on. When I want to test a change on a different 30.1025 + architecture, I push my current patches to the patch repository 30.1026 + associated with that kernel tree, pop and push all of my 30.1027 + patches, and build and test that kernel.</para> 30.1028 + 30.1029 + <para>Managing patches in a repository makes it possible for 30.1030 + multiple developers to work on the same patch series without 30.1031 + colliding with each other, all on top of an underlying source 30.1032 + base that they may or may not control.</para> 30.1033 + 30.1034 + <sect2> 30.1035 + <title>MQ support for patch repositories</title> 30.1036 + 30.1037 + <para>MQ helps you to work with the <filename role="special" 30.1038 + class="directory">.hg/patches</filename> directory as a 30.1039 + repository; when you prepare a repository for working with 30.1040 + patches using <command role="hg-ext-mq">qinit</command>, you 30.1041 + can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg 30.1042 + -c</option> option to create the <filename role="special" 30.1043 + class="directory">.hg/patches</filename> directory as a 30.1044 + Mercurial repository.</para> 30.1045 + 30.1046 + <note> 30.1047 + <para> If you forget to use the <option 30.1048 + role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you 30.1049 + can simply go into the <filename role="special" 30.1050 + class="directory">.hg/patches</filename> directory at any 30.1051 + time and run <command role="hg-cmd">hg init</command>. 30.1052 + Don't forget to add an entry for the <filename 30.1053 + role="special">status</filename> file to the <filename 30.1054 + role="special">.hgignore</filename> file, though</para> 30.1055 + 30.1056 + <para> (<command role="hg-cmd">hg qinit <option 30.1057 + role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command> 30.1058 + does this for you automatically); you 30.1059 + <emphasis>really</emphasis> don't want to manage the 30.1060 + <filename role="special">status</filename> file.</para> 30.1061 + </note> 30.1062 + 30.1063 + <para>As a convenience, if MQ notices that the <filename 30.1064 + class="directory">.hg/patches</filename> directory is a 30.1065 + repository, it will automatically <command role="hg-cmd">hg 30.1066 + add</command> every patch that you create and import.</para> 30.1067 + 30.1068 + <para>MQ provides a shortcut command, <command 30.1069 + role="hg-ext-mq">qcommit</command>, that runs <command 30.1070 + role="hg-cmd">hg commit</command> in the <filename 30.1071 + role="special" class="directory">.hg/patches</filename> 30.1072 + directory. This saves some bothersome typing.</para> 30.1073 + 30.1074 + <para>Finally, as a convenience to manage the patch directory, 30.1075 + you can define the alias <command>mq</command> on Unix 30.1076 + systems. For example, on Linux systems using the 30.1077 + <command>bash</command> shell, you can include the following 30.1078 + snippet in your <filename 30.1079 + role="home">~/.bashrc</filename>.</para> 30.1080 + 30.1081 + <programlisting>alias mq=`hg -R $(hg root)/.hg/patches'</programlisting> 30.1082 + 30.1083 + <para>You can then issue commands of the form <command>mq 30.1084 + pull</command> from the main repository.</para> 30.1085 + 30.1086 + </sect2> 30.1087 + <sect2> 30.1088 + <title>A few things to watch out for</title> 30.1089 + 30.1090 + <para>MQ's support for working with a repository full of patches 30.1091 + is limited in a few small respects.</para> 30.1092 + 30.1093 + <para>MQ cannot automatically detect changes that you make to 30.1094 + the patch directory. If you <command role="hg-cmd">hg 30.1095 + pull</command>, manually edit, or <command role="hg-cmd">hg 30.1096 + update</command> changes to patches or the <filename 30.1097 + role="special">series</filename> file, you will have to 30.1098 + <command role="hg-cmd">hg qpop <option 30.1099 + role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and 30.1100 + then <command role="hg-cmd">hg qpush <option 30.1101 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in 30.1102 + the underlying repository to see those changes show up there. 30.1103 + If you forget to do this, you can confuse MQ's idea of which 30.1104 + patches are applied.</para> 30.1105 + 30.1106 + </sect2> 30.1107 + </sect1> 30.1108 + <sect1 id="sec.mq.tools"> 30.1109 + <title>Third party tools for working with patches</title> 30.1110 + 30.1111 + <para>Once you've been working with patches for a while, you'll 30.1112 + find yourself hungry for tools that will help you to understand 30.1113 + and manipulate the patches you're dealing with.</para> 30.1114 + 30.1115 + <para>The <command>diffstat</command> command 30.1116 + <citation>web:diffstat</citation> generates a histogram of the 30.1117 + modifications made to each file in a patch. It provides a good 30.1118 + way to <quote>get a sense of</quote> a patch&emdash;which files 30.1119 + it affects, and how much change it introduces to each file and 30.1120 + as a whole. (I find that it's a good idea to use 30.1121 + <command>diffstat</command>'s <option 30.1122 + role="cmd-opt-diffstat">-p</option> option as a matter of 30.1123 + course, as otherwise it will try to do clever things with 30.1124 + prefixes of file names that inevitably confuse at least 30.1125 + me.)</para> 30.1126 + 30.1127 +&interaction.mq.tools.tools; 30.1128 + 30.1129 + <para>The <literal role="package">patchutils</literal> package 30.1130 + <citation>web:patchutils</citation> is invaluable. It provides a 30.1131 + set of small utilities that follow the <quote>Unix 30.1132 + philosophy;</quote> each does one useful thing with a patch. 30.1133 + The <literal role="package">patchutils</literal> command I use 30.1134 + most is <command>filterdiff</command>, which extracts subsets 30.1135 + from a patch file. For example, given a patch that modifies 30.1136 + hundreds of files across dozens of directories, a single 30.1137 + invocation of <command>filterdiff</command> can generate a 30.1138 + smaller patch that only touches files whose names match a 30.1139 + particular glob pattern. See section <xref 30.1140 + linkend="mq-collab.tips.interdiff"/> for another 30.1141 + example.</para> 30.1142 + 30.1143 + </sect1> 30.1144 + <sect1> 30.1145 + <title>Good ways to work with patches</title> 30.1146 + 30.1147 + <para>Whether you are working on a patch series to submit to a 30.1148 + free software or open source project, or a series that you 30.1149 + intend to treat as a sequence of regular changesets when you're 30.1150 + done, you can use some simple techniques to keep your work well 30.1151 + organised.</para> 30.1152 + 30.1153 + <para>Give your patches descriptive names. A good name for a 30.1154 + patch might be <filename>rework-device-alloc.patch</filename>, 30.1155 + because it will immediately give you a hint what the purpose of 30.1156 + the patch is. Long names shouldn't be a problem; you won't be 30.1157 + typing the names often, but you <emphasis>will</emphasis> be 30.1158 + running commands like <command 30.1159 + role="hg-ext-mq">qapplied</command> and <command 30.1160 + role="hg-ext-mq">qtop</command> over and over. Good naming 30.1161 + becomes especially important when you have a number of patches 30.1162 + to work with, or if you are juggling a number of different tasks 30.1163 + and your patches only get a fraction of your attention.</para> 30.1164 + 30.1165 + <para>Be aware of what patch you're working on. Use the <command 30.1166 + role="hg-ext-mq">qtop</command> command and skim over the text 30.1167 + of your patches frequently&emdash;for example, using <command 30.1168 + role="hg-cmd">hg tip <option 30.1169 + role="hg-opt-tip">-p</option></command>)&emdash;to be sure 30.1170 + of where you stand. I have several times worked on and <command 30.1171 + role="hg-ext-mq">qrefresh</command>ed a patch other than the 30.1172 + one I intended, and it's often tricky to migrate changes into 30.1173 + the right patch after making them in the wrong one.</para> 30.1174 + 30.1175 + <para>For this reason, it is very much worth investing a little 30.1176 + time to learn how to use some of the third-party tools I 30.1177 + described in section <xref linkend="sec.mq.tools"/>, 30.1178 + particularly 30.1179 + <command>diffstat</command> and <command>filterdiff</command>. 30.1180 + The former will give you a quick idea of what changes your patch 30.1181 + is making, while the latter makes it easy to splice hunks 30.1182 + selectively out of one patch and into another.</para> 30.1183 + 30.1184 + </sect1> 30.1185 + <sect1> 30.1186 + <title>MQ cookbook</title> 30.1187 + 30.1188 + <sect2> 30.1189 + <title>Manage <quote>trivial</quote> patches</title> 30.1190 + 30.1191 + <para>Because the overhead of dropping files into a new 30.1192 + Mercurial repository is so low, it makes a lot of sense to 30.1193 + manage patches this way even if you simply want to make a few 30.1194 + changes to a source tarball that you downloaded.</para> 30.1195 + 30.1196 + <para>Begin by downloading and unpacking the source tarball, and 30.1197 + turning it into a Mercurial repository.</para> 30.1198 + 30.1199 + &interaction.mq.tarball.download; 30.1200 + 30.1201 + <para>Continue by creating a patch stack and making your 30.1202 + changes.</para> 30.1203 + 30.1204 + &interaction.mq.tarball.qinit; 30.1205 + 30.1206 + <para>Let's say a few weeks or months pass, and your package 30.1207 + author releases a new version. First, bring their changes 30.1208 + into the repository.</para> 30.1209 + 30.1210 + &interaction.mq.tarball.newsource; 30.1211 + 30.1212 + <para>The pipeline starting with <command role="hg-cmd">hg 30.1213 + locate</command> above deletes all files in the working 30.1214 + directory, so that <command role="hg-cmd">hg 30.1215 + commit</command>'s <option 30.1216 + role="hg-opt-commit">--addremove</option> option can 30.1217 + actually tell which files have really been removed in the 30.1218 + newer version of the source.</para> 30.1219 + 30.1220 + <para>Finally, you can apply your patches on top of the new 30.1221 + tree.</para> 30.1222 + 30.1223 + &interaction.mq.tarball.repush; 30.1224 + 30.1225 + </sect2> 30.1226 + <sect2 id="sec.mq.combine"> 30.1227 + <title>Combining entire patches</title> 30.1228 + 30.1229 + <para>MQ provides a command, <command 30.1230 + role="hg-ext-mq">qfold</command> that lets you combine 30.1231 + entire patches. This <quote>folds</quote> the patches you 30.1232 + name, in the order you name them, into the topmost applied 30.1233 + patch, and concatenates their descriptions onto the end of its 30.1234 + description. The patches that you fold must be unapplied 30.1235 + before you fold them.</para> 30.1236 + 30.1237 + <para>The order in which you fold patches matters. If your 30.1238 + topmost applied patch is <literal>foo</literal>, and you 30.1239 + <command role="hg-ext-mq">qfold</command> 30.1240 + <literal>bar</literal> and <literal>quux</literal> into it, 30.1241 + you will end up with a patch that has the same effect as if 30.1242 + you applied first <literal>foo</literal>, then 30.1243 + <literal>bar</literal>, followed by 30.1244 + <literal>quux</literal>.</para> 30.1245 + 30.1246 + </sect2> 30.1247 + <sect2> 30.1248 + <title>Merging part of one patch into another</title> 30.1249 + 30.1250 + <para>Merging <emphasis>part</emphasis> of one patch into 30.1251 + another is more difficult than combining entire 30.1252 + patches.</para> 30.1253 + 30.1254 + <para>If you want to move changes to entire files, you can use 30.1255 + <command>filterdiff</command>'s <option 30.1256 + role="cmd-opt-filterdiff">-i</option> and <option 30.1257 + role="cmd-opt-filterdiff">-x</option> options to choose the 30.1258 + modifications to snip out of one patch, concatenating its 30.1259 + output onto the end of the patch you want to merge into. You 30.1260 + usually won't need to modify the patch you've merged the 30.1261 + changes from. Instead, MQ will report some rejected hunks 30.1262 + when you <command role="hg-ext-mq">qpush</command> it (from 30.1263 + the hunks you moved into the other patch), and you can simply 30.1264 + <command role="hg-ext-mq">qrefresh</command> the patch to drop 30.1265 + the duplicate hunks.</para> 30.1266 + 30.1267 + <para>If you have a patch that has multiple hunks modifying a 30.1268 + file, and you only want to move a few of those hunks, the job 30.1269 + becomes more messy, but you can still partly automate it. Use 30.1270 + <command>lsdiff -nvv</command> to print some metadata about 30.1271 + the patch.</para> 30.1272 + 30.1273 + &interaction.mq.tools.lsdiff; 30.1274 + 30.1275 + <para>This command prints three different kinds of 30.1276 + number:</para> 30.1277 + <itemizedlist> 30.1278 + <listitem><para>(in the first column) a <emphasis>file 30.1279 + number</emphasis> to identify each file modified in the 30.1280 + patch;</para> 30.1281 + </listitem> 30.1282 + <listitem><para>(on the next line, indented) the line number 30.1283 + within a modified file where a hunk starts; and</para> 30.1284 + </listitem> 30.1285 + <listitem><para>(on the same line) a <emphasis>hunk 30.1286 + number</emphasis> to identify that hunk.</para> 30.1287 + </listitem></itemizedlist> 30.1288 + 30.1289 + <para>You'll have to use some visual inspection, and reading of 30.1290 + the patch, to identify the file and hunk numbers you'll want, 30.1291 + but you can then pass them to to 30.1292 + <command>filterdiff</command>'s <option 30.1293 + role="cmd-opt-filterdiff">--files</option> and <option 30.1294 + role="cmd-opt-filterdiff">--hunks</option> options, to 30.1295 + select exactly the file and hunk you want to extract.</para> 30.1296 + 30.1297 + <para>Once you have this hunk, you can concatenate it onto the 30.1298 + end of your destination patch and continue with the remainder 30.1299 + of section <xref linkend="sec.mq.combine"/>.</para> 30.1300 + 30.1301 + </sect2> 30.1302 + </sect1> 30.1303 + <sect1> 30.1304 + <title>Differences between quilt and MQ</title> 30.1305 + 30.1306 + <para>If you are already familiar with quilt, MQ provides a 30.1307 + similar command set. There are a few differences in the way 30.1308 + that it works.</para> 30.1309 + 30.1310 + <para>You will already have noticed that most quilt commands have 30.1311 + MQ counterparts that simply begin with a 30.1312 + <quote><literal>q</literal></quote>. The exceptions are quilt's 30.1313 + <literal>add</literal> and <literal>remove</literal> commands, 30.1314 + the counterparts for which are the normal Mercurial <command 30.1315 + role="hg-cmd">hg add</command> and <command role="hg-cmd">hg 30.1316 + remove</command> commands. There is no MQ equivalent of the 30.1317 + quilt <literal>edit</literal> command.</para> 30.1318 + 30.1319 + </sect1> 30.1320 +</chapter> 30.1321 + 30.1322 +<!-- 30.1323 +local variables: 30.1324 +sgml-parent-document: ("00book.xml" "book" "chapter") 30.1325 +end: 30.1326 +-->
31.1 --- a/en/ch11-template.xml Fri Mar 20 15:40:06 2009 +0800 31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 31.3 @@ -1,675 +0,0 @@ 31.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 31.5 - 31.6 -<chapter id="chap.template"> 31.7 - <?dbhtml filename="customizing-the-output-of-mercurial.html"?> 31.8 - <title>Customising the output of Mercurial</title> 31.9 - 31.10 - <para>Mercurial provides a powerful mechanism to let you control how 31.11 - it displays information. The mechanism is based on templates. 31.12 - You can use templates to generate specific output for a single 31.13 - command, or to customise the entire appearance of the built-in web 31.14 - interface.</para> 31.15 - 31.16 - <sect1 id="sec.style"> 31.17 - <title>Using precanned output styles</title> 31.18 - 31.19 - <para>Packaged with Mercurial are some output styles that you can 31.20 - use immediately. A style is simply a precanned template that 31.21 - someone wrote and installed somewhere that Mercurial can 31.22 - find.</para> 31.23 - 31.24 - <para>Before we take a look at Mercurial's bundled styles, let's 31.25 - review its normal output.</para> 31.26 - 31.27 - &interaction.template.simple.normal; 31.28 - 31.29 - <para>This is somewhat informative, but it takes up a lot of 31.30 - space&emdash;five lines of output per changeset. The 31.31 - <literal>compact</literal> style reduces this to three lines, 31.32 - presented in a sparse manner.</para> 31.33 - 31.34 - &interaction.template.simple.compact; 31.35 - 31.36 - <para>The <literal>changelog</literal> style hints at the 31.37 - expressive power of Mercurial's templating engine. This style 31.38 - attempts to follow the GNU Project's changelog 31.39 - guidelines<citation>web:changelog</citation>.</para> 31.40 - 31.41 - &interaction.template.simple.changelog; 31.42 - 31.43 - <para>You will not be shocked to learn that Mercurial's default 31.44 - output style is named <literal>default</literal>.</para> 31.45 - 31.46 - <sect2> 31.47 - <title>Setting a default style</title> 31.48 - 31.49 - <para>You can modify the output style that Mercurial will use 31.50 - for every command by editing your <filename 31.51 - role="special">~/.hgrc</filename> file, naming the style 31.52 - you would prefer to use.</para> 31.53 - 31.54 - <programlisting>[ui] 31.55 -style = compact</programlisting> 31.56 - 31.57 - <para>If you write a style of your own, you can use it by either 31.58 - providing the path to your style file, or copying your style 31.59 - file into a location where Mercurial can find it (typically 31.60 - the <literal>templates</literal> subdirectory of your 31.61 - Mercurial install directory).</para> 31.62 - 31.63 - </sect2> 31.64 - </sect1> 31.65 - <sect1> 31.66 - <title>Commands that support styles and templates</title> 31.67 - 31.68 - <para>All of Mercurial's 31.69 - <quote><literal>log</literal>-like</quote> commands let you use 31.70 - styles and templates: <command role="hg-cmd">hg 31.71 - incoming</command>, <command role="hg-cmd">hg log</command>, 31.72 - <command role="hg-cmd">hg outgoing</command>, and <command 31.73 - role="hg-cmd">hg tip</command>.</para> 31.74 - 31.75 - <para>As I write this manual, these are so far the only commands 31.76 - that support styles and templates. Since these are the most 31.77 - important commands that need customisable output, there has been 31.78 - little pressure from the Mercurial user community to add style 31.79 - and template support to other commands.</para> 31.80 - 31.81 - </sect1> 31.82 - <sect1> 31.83 - <title>The basics of templating</title> 31.84 - 31.85 - <para>At its simplest, a Mercurial template is a piece of text. 31.86 - Some of the text never changes, while other parts are 31.87 - <emphasis>expanded</emphasis>, or replaced with new text, when 31.88 - necessary.</para> 31.89 - 31.90 - <para>Before we continue, let's look again at a simple example of 31.91 - Mercurial's normal output.</para> 31.92 - 31.93 - &interaction.template.simple.normal; 31.94 - 31.95 - <para>Now, let's run the same command, but using a template to 31.96 - change its output.</para> 31.97 - 31.98 - &interaction.template.simple.simplest; 31.99 - 31.100 - <para>The example above illustrates the simplest possible 31.101 - template; it's just a piece of static text, printed once for 31.102 - each changeset. The <option 31.103 - role="hg-opt-log">--template</option> option to the <command 31.104 - role="hg-cmd">hg log</command> command tells Mercurial to use 31.105 - the given text as the template when printing each 31.106 - changeset.</para> 31.107 - 31.108 - <para>Notice that the template string above ends with the text 31.109 - <quote><literal>\n</literal></quote>. This is an 31.110 - <emphasis>escape sequence</emphasis>, telling Mercurial to print 31.111 - a newline at the end of each template item. If you omit this 31.112 - newline, Mercurial will run each piece of output together. See 31.113 - section <xref linkend="sec.template.escape"/> for more details 31.114 - of escape sequences.</para> 31.115 - 31.116 - <para>A template that prints a fixed string of text all the time 31.117 - isn't very useful; let's try something a bit more 31.118 - complex.</para> 31.119 - 31.120 - &interaction.template.simple.simplesub; 31.121 - 31.122 - <para>As you can see, the string 31.123 - <quote><literal>{desc}</literal></quote> in the template has 31.124 - been replaced in the output with the description of each 31.125 - changeset. Every time Mercurial finds text enclosed in curly 31.126 - braces (<quote><literal>{</literal></quote> and 31.127 - <quote><literal>}</literal></quote>), it will try to replace the braces 31.128 - and text with the expansion of whatever is inside. To print a 31.129 - literal curly brace, you must escape it, as described in section 31.130 - <xref 31.131 - linkend="sec.template.escape"/>.</para> 31.132 - 31.133 - </sect1> 31.134 - <sect1 id="sec.template.keyword"> 31.135 - <title>Common template keywords</title> 31.136 - 31.137 - <para>You can start writing simple templates immediately using the 31.138 - keywords below.</para> 31.139 - 31.140 - <itemizedlist> 31.141 - <listitem><para><literal 31.142 - role="template-keyword">author</literal>: String. The 31.143 - unmodified author of the changeset.</para> 31.144 - </listitem> 31.145 - <listitem><para><literal 31.146 - role="template-keyword">branches</literal>: String. The 31.147 - name of the branch on which the changeset was committed. 31.148 - Will be empty if the branch name was 31.149 - <literal>default</literal>.</para> 31.150 - </listitem> 31.151 - <listitem><para><literal role="template-keyword">date</literal>: 31.152 - Date information. The date when the changeset was 31.153 - committed. This is <emphasis>not</emphasis> human-readable; 31.154 - you must pass it through a filter that will render it 31.155 - appropriately. See section <xref 31.156 - linkend="sec.template.filter"/> for more information 31.157 - on filters. The date is expressed as a pair of numbers. The 31.158 - first number is a Unix UTC timestamp (seconds since January 31.159 - 1, 1970); the second is the offset of the committer's 31.160 - timezone from UTC, in seconds.</para> 31.161 - </listitem> 31.162 - <listitem><para><literal role="template-keyword">desc</literal>: 31.163 - String. The text of the changeset description.</para> 31.164 - </listitem> 31.165 - <listitem><para><literal 31.166 - role="template-keyword">files</literal>: List of strings. 31.167 - All files modified, added, or removed by this 31.168 - changeset.</para> 31.169 - </listitem> 31.170 - <listitem><para><literal 31.171 - role="template-keyword">file_adds</literal>: List of 31.172 - strings. Files added by this changeset.</para> 31.173 - </listitem> 31.174 - <listitem><para><literal 31.175 - role="template-keyword">file_dels</literal>: List of 31.176 - strings. Files removed by this changeset.</para> 31.177 - </listitem> 31.178 - <listitem><para><literal role="template-keyword">node</literal>: 31.179 - String. The changeset identification hash, as a 31.180 - 40-character hexadecimal string.</para> 31.181 - </listitem> 31.182 - <listitem><para><literal 31.183 - role="template-keyword">parents</literal>: List of 31.184 - strings. The parents of the changeset.</para> 31.185 - </listitem> 31.186 - <listitem><para><literal role="template-keyword">rev</literal>: 31.187 - Integer. The repository-local changeset revision 31.188 - number.</para> 31.189 - </listitem> 31.190 - <listitem><para><literal role="template-keyword">tags</literal>: 31.191 - List of strings. Any tags associated with the 31.192 - changeset.</para> 31.193 - </listitem></itemizedlist> 31.194 - 31.195 - <para>A few simple experiments will show us what to expect when we 31.196 - use these keywords; you can see the results below.</para> 31.197 - 31.198 -&interaction.template.simple.keywords; 31.199 - 31.200 - <para>As we noted above, the date keyword does not produce 31.201 - human-readable output, so we must treat it specially. This 31.202 - involves using a <emphasis>filter</emphasis>, about which more 31.203 - in section <xref 31.204 - linkend="sec.template.filter"/>.</para> 31.205 - 31.206 - &interaction.template.simple.datekeyword; 31.207 - 31.208 - </sect1> 31.209 - <sect1 id="sec.template.escape"> 31.210 - <title>Escape sequences</title> 31.211 - 31.212 - <para>Mercurial's templating engine recognises the most commonly 31.213 - used escape sequences in strings. When it sees a backslash 31.214 - (<quote><literal>\</literal></quote>) character, it looks at the 31.215 - following character and substitutes the two characters with a 31.216 - single replacement, as described below.</para> 31.217 - 31.218 - <itemizedlist> 31.219 - <listitem><para><literal>\</literal>: 31.220 - Backslash, <quote><literal>\</literal></quote>, ASCII 31.221 - 134.</para> 31.222 - </listitem> 31.223 - <listitem><para><literal>\n</literal>: Newline, 31.224 - ASCII 12.</para> 31.225 - </listitem> 31.226 - <listitem><para><literal>\r</literal>: Carriage 31.227 - return, ASCII 15.</para> 31.228 - </listitem> 31.229 - <listitem><para><literal>\t</literal>: Tab, ASCII 31.230 - 11.</para> 31.231 - </listitem> 31.232 - <listitem><para><literal>\v</literal>: Vertical 31.233 - tab, ASCII 13.</para> 31.234 - </listitem> 31.235 - <listitem><para><literal>{</literal>: Open curly 31.236 - brace, <quote><literal>{</literal></quote>, ASCII 31.237 - 173.</para> 31.238 - </listitem> 31.239 - <listitem><para><literal>}</literal>: Close curly 31.240 - brace, <quote><literal>}</literal></quote>, ASCII 31.241 - 175.</para> 31.242 - </listitem></itemizedlist> 31.243 - 31.244 - <para>As indicated above, if you want the expansion of a template 31.245 - to contain a literal <quote><literal>\</literal></quote>, 31.246 - <quote><literal>{</literal></quote>, or 31.247 - <quote><literal>{</literal></quote> character, you must escape 31.248 - it.</para> 31.249 - 31.250 - </sect1> 31.251 - <sect1 id="sec.template.filter"> 31.252 - <title>Filtering keywords to change their results</title> 31.253 - 31.254 - <para>Some of the results of template expansion are not 31.255 - immediately easy to use. Mercurial lets you specify an optional 31.256 - chain of <emphasis>filters</emphasis> to modify the result of 31.257 - expanding a keyword. You have already seen a common filter, 31.258 - <literal role="template-kw-filt-date">isodate</literal>, in 31.259 - action above, to make a date readable.</para> 31.260 - 31.261 - <para>Below is a list of the most commonly used filters that 31.262 - Mercurial supports. While some filters can be applied to any 31.263 - text, others can only be used in specific circumstances. The 31.264 - name of each filter is followed first by an indication of where 31.265 - it can be used, then a description of its effect.</para> 31.266 - 31.267 - <itemizedlist> 31.268 - <listitem><para><literal 31.269 - role="template-filter">addbreaks</literal>: Any text. Add 31.270 - an XHTML <quote><literal><br/></literal></quote> tag 31.271 - before the end of every line except the last. For example, 31.272 - <quote><literal>foo\nbar</literal></quote> becomes 31.273 - <quote><literal>foo<br/>\nbar</literal></quote>.</para> 31.274 - </listitem> 31.275 - <listitem><para><literal 31.276 - role="template-kw-filt-date">age</literal>: <literal 31.277 - role="template-keyword">date</literal> keyword. Render 31.278 - the age of the date, relative to the current time. Yields a 31.279 - string like <quote><literal>10 31.280 - minutes</literal></quote>.</para> 31.281 - </listitem> 31.282 - <listitem><para><literal 31.283 - role="template-filter">basename</literal>: Any text, but 31.284 - most useful for the <literal 31.285 - role="template-keyword">files</literal> keyword and its 31.286 - relatives. Treat the text as a path, and return the 31.287 - basename. For example, 31.288 - <quote><literal>foo/bar/baz</literal></quote> becomes 31.289 - <quote><literal>baz</literal></quote>.</para> 31.290 - </listitem> 31.291 - <listitem><para><literal 31.292 - role="template-kw-filt-date">date</literal>: <literal 31.293 - role="template-keyword">date</literal> keyword. Render a 31.294 - date in a similar format to the Unix <literal 31.295 - role="template-keyword">date</literal> command, but with 31.296 - timezone included. Yields a string like <quote><literal>Mon 31.297 - Sep 04 15:13:13 2006 -0700</literal></quote>.</para> 31.298 - </listitem> 31.299 - <listitem><para><literal 31.300 - role="template-kw-filt-author">domain</literal>: Any text, 31.301 - but most useful for the <literal 31.302 - role="template-keyword">author</literal> keyword. Finds 31.303 - the first string that looks like an email address, and 31.304 - extract just the domain component. For example, 31.305 - <quote><literal>Bryan O'Sullivan 31.306 - <bos@serpentine.com></literal></quote> becomes 31.307 - <quote><literal>serpentine.com</literal></quote>.</para> 31.308 - </listitem> 31.309 - <listitem><para><literal 31.310 - role="template-kw-filt-author">email</literal>: Any text, 31.311 - but most useful for the <literal 31.312 - role="template-keyword">author</literal> keyword. Extract 31.313 - the first string that looks like an email address. For 31.314 - example, <quote><literal>Bryan O'Sullivan 31.315 - <bos@serpentine.com></literal></quote> becomes 31.316 - <quote><literal>bos@serpentine.com</literal></quote>.</para> 31.317 - </listitem> 31.318 - <listitem><para><literal 31.319 - role="template-filter">escape</literal>: Any text. 31.320 - Replace the special XML/XHTML characters 31.321 - <quote><literal>&</literal></quote>, 31.322 - <quote><literal><</literal></quote> and 31.323 - <quote><literal>></literal></quote> with XML 31.324 - entities.</para> 31.325 - </listitem> 31.326 - <listitem><para><literal 31.327 - role="template-filter">fill68</literal>: Any text. Wrap 31.328 - the text to fit in 68 columns. This is useful before you 31.329 - pass text through the <literal 31.330 - role="template-filter">tabindent</literal> filter, and 31.331 - still want it to fit in an 80-column fixed-font 31.332 - window.</para> 31.333 - </listitem> 31.334 - <listitem><para><literal 31.335 - role="template-filter">fill76</literal>: Any text. Wrap 31.336 - the text to fit in 76 columns.</para> 31.337 - </listitem> 31.338 - <listitem><para><literal 31.339 - role="template-filter">firstline</literal>: Any text. 31.340 - Yield the first line of text, without any trailing 31.341 - newlines.</para> 31.342 - </listitem> 31.343 - <listitem><para><literal 31.344 - role="template-kw-filt-date">hgdate</literal>: <literal 31.345 - role="template-keyword">date</literal> keyword. Render 31.346 - the date as a pair of readable numbers. Yields a string 31.347 - like <quote><literal>1157407993 31.348 - 25200</literal></quote>.</para> 31.349 - </listitem> 31.350 - <listitem><para><literal 31.351 - role="template-kw-filt-date">isodate</literal>: <literal 31.352 - role="template-keyword">date</literal> keyword. Render 31.353 - the date as a text string in ISO 8601 format. Yields a 31.354 - string like <quote><literal>2006-09-04 15:13:13 31.355 - -0700</literal></quote>.</para> 31.356 - </listitem> 31.357 - <listitem><para><literal 31.358 - role="template-filter">obfuscate</literal>: Any text, but 31.359 - most useful for the <literal 31.360 - role="template-keyword">author</literal> keyword. Yield 31.361 - the input text rendered as a sequence of XML entities. This 31.362 - helps to defeat some particularly stupid screen-scraping 31.363 - email harvesting spambots.</para> 31.364 - </listitem> 31.365 - <listitem><para><literal 31.366 - role="template-kw-filt-author">person</literal>: Any text, 31.367 - but most useful for the <literal 31.368 - role="template-keyword">author</literal> keyword. Yield 31.369 - the text before an email address. For example, 31.370 - <quote><literal>Bryan O'Sullivan 31.371 - <bos@serpentine.com></literal></quote> becomes 31.372 - <quote><literal>Bryan O'Sullivan</literal></quote>.</para> 31.373 - </listitem> 31.374 - <listitem><para><literal 31.375 - role="template-kw-filt-date">rfc822date</literal>: 31.376 - <literal role="template-keyword">date</literal> keyword. 31.377 - Render a date using the same format used in email headers. 31.378 - Yields a string like <quote><literal>Mon, 04 Sep 2006 31.379 - 15:13:13 -0700</literal></quote>.</para> 31.380 - </listitem> 31.381 - <listitem><para><literal 31.382 - role="template-kw-filt-node">short</literal>: Changeset 31.383 - hash. Yield the short form of a changeset hash, i.e. a 31.384 - 12-character hexadecimal string.</para> 31.385 - </listitem> 31.386 - <listitem><para><literal 31.387 - role="template-kw-filt-date">shortdate</literal>: <literal 31.388 - role="template-keyword">date</literal> keyword. Render 31.389 - the year, month, and day of the date. Yields a string like 31.390 - <quote><literal>2006-09-04</literal></quote>.</para> 31.391 - </listitem> 31.392 - <listitem><para><literal role="template-filter">strip</literal>: 31.393 - Any text. Strip all leading and trailing whitespace from 31.394 - the string.</para> 31.395 - </listitem> 31.396 - <listitem><para><literal 31.397 - role="template-filter">tabindent</literal>: Any text. 31.398 - Yield the text, with every line except the first starting 31.399 - with a tab character.</para> 31.400 - </listitem> 31.401 - <listitem><para><literal 31.402 - role="template-filter">urlescape</literal>: Any text. 31.403 - Escape all characters that are considered 31.404 - <quote>special</quote> by URL parsers. For example, 31.405 - <literal>foo bar</literal> becomes 31.406 - <literal>foo%20bar</literal>.</para> 31.407 - </listitem> 31.408 - <listitem><para><literal 31.409 - role="template-kw-filt-author">user</literal>: Any text, 31.410 - but most useful for the <literal 31.411 - role="template-keyword">author</literal> keyword. Return 31.412 - the <quote>user</quote> portion of an email address. For 31.413 - example, <quote><literal>Bryan O'Sullivan 31.414 - <bos@serpentine.com></literal></quote> becomes 31.415 - <quote><literal>bos</literal></quote>.</para> 31.416 - </listitem></itemizedlist> 31.417 - 31.418 -&interaction.template.simple.manyfilters; 31.419 - 31.420 - <note> 31.421 - <para> If you try to apply a filter to a piece of data that it 31.422 - cannot process, Mercurial will fail and print a Python 31.423 - exception. For example, trying to run the output of the 31.424 - <literal role="template-keyword">desc</literal> keyword into 31.425 - the <literal role="template-kw-filt-date">isodate</literal> 31.426 - filter is not a good idea.</para> 31.427 - </note> 31.428 - 31.429 - <sect2> 31.430 - <title>Combining filters</title> 31.431 - 31.432 - <para>It is easy to combine filters to yield output in the form 31.433 - you would like. The following chain of filters tidies up a 31.434 - description, then makes sure that it fits cleanly into 68 31.435 - columns, then indents it by a further 8 characters (at least 31.436 - on Unix-like systems, where a tab is conventionally 8 31.437 - characters wide).</para> 31.438 - 31.439 - &interaction.template.simple.combine; 31.440 - 31.441 - <para>Note the use of <quote><literal>\t</literal></quote> (a 31.442 - tab character) in the template to force the first line to be 31.443 - indented; this is necessary since <literal 31.444 - role="template-keyword">tabindent</literal> indents all 31.445 - lines <emphasis>except</emphasis> the first.</para> 31.446 - 31.447 - <para>Keep in mind that the order of filters in a chain is 31.448 - significant. The first filter is applied to the result of the 31.449 - keyword; the second to the result of the first filter; and so 31.450 - on. For example, using <literal>fill68|tabindent</literal> 31.451 - gives very different results from 31.452 - <literal>tabindent|fill68</literal>.</para> 31.453 - 31.454 - 31.455 - </sect2> 31.456 - </sect1> 31.457 - <sect1> 31.458 - <title>From templates to styles</title> 31.459 - 31.460 - <para>A command line template provides a quick and simple way to 31.461 - format some output. Templates can become verbose, though, and 31.462 - it's useful to be able to give a template a name. A style file 31.463 - is a template with a name, stored in a file.</para> 31.464 - 31.465 - <para>More than that, using a style file unlocks the power of 31.466 - Mercurial's templating engine in ways that are not possible 31.467 - using the command line <option 31.468 - role="hg-opt-log">--template</option> option.</para> 31.469 - 31.470 - <sect2> 31.471 - <title>The simplest of style files</title> 31.472 - 31.473 - <para>Our simple style file contains just one line:</para> 31.474 - 31.475 - &interaction.template.simple.rev; 31.476 - 31.477 - <para>This tells Mercurial, <quote>if you're printing a 31.478 - changeset, use the text on the right as the 31.479 - template</quote>.</para> 31.480 - 31.481 - </sect2> 31.482 - <sect2> 31.483 - <title>Style file syntax</title> 31.484 - 31.485 - <para>The syntax rules for a style file are simple.</para> 31.486 - 31.487 - <itemizedlist> 31.488 - <listitem><para>The file is processed one line at a 31.489 - time.</para> 31.490 - </listitem> 31.491 - <listitem><para>Leading and trailing white space are 31.492 - ignored.</para> 31.493 - </listitem> 31.494 - <listitem><para>Empty lines are skipped.</para> 31.495 - </listitem> 31.496 - <listitem><para>If a line starts with either of the characters 31.497 - <quote><literal>#</literal></quote> or 31.498 - <quote><literal>;</literal></quote>, the entire line is 31.499 - treated as a comment, and skipped as if empty.</para> 31.500 - </listitem> 31.501 - <listitem><para>A line starts with a keyword. This must start 31.502 - with an alphabetic character or underscore, and can 31.503 - subsequently contain any alphanumeric character or 31.504 - underscore. (In regexp notation, a keyword must match 31.505 - <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> 31.506 - </listitem> 31.507 - <listitem><para>The next element must be an 31.508 - <quote><literal>=</literal></quote> character, which can 31.509 - be preceded or followed by an arbitrary amount of white 31.510 - space.</para> 31.511 - </listitem> 31.512 - <listitem><para>If the rest of the line starts and ends with 31.513 - matching quote characters (either single or double quote), 31.514 - it is treated as a template body.</para> 31.515 - </listitem> 31.516 - <listitem><para>If the rest of the line <emphasis>does 31.517 - not</emphasis> start with a quote character, it is 31.518 - treated as the name of a file; the contents of this file 31.519 - will be read and used as a template body.</para> 31.520 - </listitem></itemizedlist> 31.521 - 31.522 - </sect2> 31.523 - </sect1> 31.524 - <sect1> 31.525 - <title>Style files by example</title> 31.526 - 31.527 - <para>To illustrate how to write a style file, we will construct a 31.528 - few by example. Rather than provide a complete style file and 31.529 - walk through it, we'll mirror the usual process of developing a 31.530 - style file by starting with something very simple, and walking 31.531 - through a series of successively more complete examples.</para> 31.532 - 31.533 - <sect2> 31.534 - <title>Identifying mistakes in style files</title> 31.535 - 31.536 - <para>If Mercurial encounters a problem in a style file you are 31.537 - working on, it prints a terse error message that, once you 31.538 - figure out what it means, is actually quite useful.</para> 31.539 - 31.540 -&interaction.template.svnstyle.syntax.input; 31.541 - 31.542 - <para>Notice that <filename>broken.style</filename> attempts to 31.543 - define a <literal>changeset</literal> keyword, but forgets to 31.544 - give any content for it. When instructed to use this style 31.545 - file, Mercurial promptly complains.</para> 31.546 - 31.547 - &interaction.template.svnstyle.syntax.error; 31.548 - 31.549 - <para>This error message looks intimidating, but it is not too 31.550 - hard to follow.</para> 31.551 - 31.552 - <itemizedlist> 31.553 - <listitem><para>The first component is simply Mercurial's way 31.554 - of saying <quote>I am giving up</quote>.</para> 31.555 - <programlisting>___abort___: broken.style:1: parse error</programlisting> 31.556 - </listitem> 31.557 - <listitem><para>Next comes the name of the style file that 31.558 - contains the error.</para> 31.559 - <programlisting>abort: ___broken.style___:1: parse error</programlisting> 31.560 - </listitem> 31.561 - <listitem><para>Following the file name is the line number 31.562 - where the error was encountered.</para> 31.563 - <programlisting>abort: broken.style:___1___: parse error</programlisting> 31.564 - </listitem> 31.565 - <listitem><para>Finally, a description of what went 31.566 - wrong.</para> 31.567 - <programlisting>abort: broken.style:1: ___parse error___</programlisting> 31.568 - </listitem> 31.569 - <listitem><para>The description of the problem is not always 31.570 - clear (as in this case), but even when it is cryptic, it 31.571 - is almost always trivial to visually inspect the offending 31.572 - line in the style file and see what is wrong.</para> 31.573 - </listitem></itemizedlist> 31.574 - 31.575 - </sect2> 31.576 - <sect2> 31.577 - <title>Uniquely identifying a repository</title> 31.578 - 31.579 - <para>If you would like to be able to identify a Mercurial 31.580 - repository <quote>fairly uniquely</quote> using a short string 31.581 - as an identifier, you can use the first revision in the 31.582 - repository.</para> 31.583 - 31.584 - &interaction.template.svnstyle.id; 31.585 - 31.586 - <para>This is not guaranteed to be unique, but it is 31.587 - nevertheless useful in many cases.</para> 31.588 - <itemizedlist> 31.589 - <listitem><para>It will not work in a completely empty 31.590 - repository, because such a repository does not have a 31.591 - revision zero.</para> 31.592 - </listitem> 31.593 - <listitem><para>Neither will it work in the (extremely rare) 31.594 - case where a repository is a merge of two or more formerly 31.595 - independent repositories, and you still have those 31.596 - repositories around.</para> 31.597 - </listitem></itemizedlist> 31.598 - <para>Here are some uses to which you could put this 31.599 - identifier:</para> 31.600 - <itemizedlist> 31.601 - <listitem><para>As a key into a table for a database that 31.602 - manages repositories on a server.</para> 31.603 - </listitem> 31.604 - <listitem><para>As half of a {<emphasis>repository 31.605 - ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 31.606 - Save this information away when you run an automated build 31.607 - or other activity, so that you can <quote>replay</quote> 31.608 - the build later if necessary.</para> 31.609 - </listitem></itemizedlist> 31.610 - 31.611 - </sect2> 31.612 - <sect2> 31.613 - <title>Mimicking Subversion's output</title> 31.614 - 31.615 - <para>Let's try to emulate the default output format used by 31.616 - another revision control tool, Subversion.</para> 31.617 - 31.618 - &interaction.template.svnstyle.short; 31.619 - 31.620 - <para>Since Subversion's output style is fairly simple, it is 31.621 - easy to copy-and-paste a hunk of its output into a file, and 31.622 - replace the text produced above by Subversion with the 31.623 - template values we'd like to see expanded.</para> 31.624 - 31.625 - &interaction.template.svnstyle.template; 31.626 - 31.627 - <para>There are a few small ways in which this template deviates 31.628 - from the output produced by Subversion.</para> 31.629 - <itemizedlist> 31.630 - <listitem><para>Subversion prints a <quote>readable</quote> 31.631 - date (the <quote><literal>Wed, 27 Sep 2006</literal></quote> in the 31.632 - example output above) in parentheses. Mercurial's 31.633 - templating engine does not provide a way to display a date 31.634 - in this format without also printing the time and time 31.635 - zone.</para> 31.636 - </listitem> 31.637 - <listitem><para>We emulate Subversion's printing of 31.638 - <quote>separator</quote> lines full of 31.639 - <quote><literal>-</literal></quote> characters by ending 31.640 - the template with such a line. We use the templating 31.641 - engine's <literal role="template-keyword">header</literal> 31.642 - keyword to print a separator line as the first line of 31.643 - output (see below), thus achieving similar output to 31.644 - Subversion.</para> 31.645 - </listitem> 31.646 - <listitem><para>Subversion's output includes a count in the 31.647 - header of the number of lines in the commit message. We 31.648 - cannot replicate this in Mercurial; the templating engine 31.649 - does not currently provide a filter that counts the number 31.650 - of lines the template generates.</para> 31.651 - </listitem></itemizedlist> 31.652 - <para>It took me no more than a minute or two of work to replace 31.653 - literal text from an example of Subversion's output with some 31.654 - keywords and filters to give the template above. The style 31.655 - file simply refers to the template.</para> 31.656 - 31.657 - &interaction.template.svnstyle.style; 31.658 - 31.659 - <para>We could have included the text of the template file 31.660 - directly in the style file by enclosing it in quotes and 31.661 - replacing the newlines with 31.662 - <quote><literal>\n</literal></quote> sequences, but it would 31.663 - have made the style file too difficult to read. Readability 31.664 - is a good guide when you're trying to decide whether some text 31.665 - belongs in a style file, or in a template file that the style 31.666 - file points to. If the style file will look too big or 31.667 - cluttered if you insert a literal piece of text, drop it into 31.668 - a template instead.</para> 31.669 - 31.670 - </sect2> 31.671 - </sect1> 31.672 -</chapter> 31.673 - 31.674 -<!-- 31.675 -local variables: 31.676 -sgml-parent-document: ("00book.xml" "book" "chapter") 31.677 -end: 31.678 --->
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/en/ch12-mq-collab.xml Fri Mar 20 16:43:35 2009 +0800 32.3 @@ -0,0 +1,518 @@ 32.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 32.5 + 32.6 +<chapter id="chap.mq-collab"> 32.7 + <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?> 32.8 + <title>Advanced uses of Mercurial Queues</title> 32.9 + 32.10 + <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial 32.11 + Queues, use of a little discipline and some of MQ's less 32.12 + frequently used capabilities makes it possible to work in 32.13 + complicated development environments.</para> 32.14 + 32.15 + <para id="x_15e">In this chapter, I will use as an example a technique I have 32.16 + used to manage the development of an Infiniband device driver for 32.17 + the Linux kernel. The driver in question is large (at least as 32.18 + drivers go), with 25,000 lines of code spread across 35 source 32.19 + files. It is maintained by a small team of developers.</para> 32.20 + 32.21 + <para id="x_15f">While much of the material in this chapter is specific to 32.22 + Linux, the same principles apply to any code base for which you're 32.23 + not the primary owner, and upon which you need to do a lot of 32.24 + development.</para> 32.25 + 32.26 + <sect1> 32.27 + <title>The problem of many targets</title> 32.28 + 32.29 + <para id="x_160">The Linux kernel changes rapidly, and has never been 32.30 + internally stable; developers frequently make drastic changes 32.31 + between releases. This means that a version of the driver that 32.32 + works well with a particular released version of the kernel will 32.33 + not even <emphasis>compile</emphasis> correctly against, 32.34 + typically, any other version.</para> 32.35 + 32.36 + <para id="x_161">To maintain a driver, we have to keep a number of distinct 32.37 + versions of Linux in mind.</para> 32.38 + <itemizedlist> 32.39 + <listitem><para id="x_162">One target is the main Linux kernel development 32.40 + tree. Maintenance of the code is in this case partly shared 32.41 + by other developers in the kernel community, who make 32.42 + <quote>drive-by</quote> modifications to the driver as they 32.43 + develop and refine kernel subsystems.</para> 32.44 + </listitem> 32.45 + <listitem><para id="x_163">We also maintain a number of 32.46 + <quote>backports</quote> to older versions of the Linux 32.47 + kernel, to support the needs of customers who are running 32.48 + older Linux distributions that do not incorporate our 32.49 + drivers. (To <emphasis>backport</emphasis> a piece of code 32.50 + is to modify it to work in an older version of its target 32.51 + environment than the version it was developed for.)</para> 32.52 + </listitem> 32.53 + <listitem><para id="x_164">Finally, we make software releases on a schedule 32.54 + that is necessarily not aligned with those used by Linux 32.55 + distributors and kernel developers, so that we can deliver 32.56 + new features to customers without forcing them to upgrade 32.57 + their entire kernels or distributions.</para> 32.58 + </listitem></itemizedlist> 32.59 + 32.60 + <sect2> 32.61 + <title>Tempting approaches that don't work well</title> 32.62 + 32.63 + <para id="x_165">There are two <quote>standard</quote> ways to maintain a 32.64 + piece of software that has to target many different 32.65 + environments.</para> 32.66 + 32.67 + <para id="x_166">The first is to maintain a number of branches, each 32.68 + intended for a single target. The trouble with this approach 32.69 + is that you must maintain iron discipline in the flow of 32.70 + changes between repositories. A new feature or bug fix must 32.71 + start life in a <quote>pristine</quote> repository, then 32.72 + percolate out to every backport repository. Backport changes 32.73 + are more limited in the branches they should propagate to; a 32.74 + backport change that is applied to a branch where it doesn't 32.75 + belong will probably stop the driver from compiling.</para> 32.76 + 32.77 + <para id="x_167">The second is to maintain a single source tree filled with 32.78 + conditional statements that turn chunks of code on or off 32.79 + depending on the intended target. Because these 32.80 + <quote>ifdefs</quote> are not allowed in the Linux kernel 32.81 + tree, a manual or automatic process must be followed to strip 32.82 + them out and yield a clean tree. A code base maintained in 32.83 + this fashion rapidly becomes a rat's nest of conditional 32.84 + blocks that are difficult to understand and maintain.</para> 32.85 + 32.86 + <para id="x_168">Neither of these approaches is well suited to a situation 32.87 + where you don't <quote>own</quote> the canonical copy of a 32.88 + source tree. In the case of a Linux driver that is 32.89 + distributed with the standard kernel, Linus's tree contains 32.90 + the copy of the code that will be treated by the world as 32.91 + canonical. The upstream version of <quote>my</quote> driver 32.92 + can be modified by people I don't know, without me even 32.93 + finding out about it until after the changes show up in 32.94 + Linus's tree.</para> 32.95 + 32.96 + <para id="x_169">These approaches have the added weakness of making it 32.97 + difficult to generate well-formed patches to submit 32.98 + upstream.</para> 32.99 + 32.100 + <para id="x_16a">In principle, Mercurial Queues seems like a good candidate 32.101 + to manage a development scenario such as the above. While 32.102 + this is indeed the case, MQ contains a few added features that 32.103 + make the job more pleasant.</para> 32.104 + 32.105 + </sect2> 32.106 + </sect1> 32.107 + <sect1> 32.108 + <title>Conditionally applying patches with guards</title> 32.109 + 32.110 + <para id="x_16b">Perhaps the best way to maintain sanity with so many targets 32.111 + is to be able to choose specific patches to apply for a given 32.112 + situation. MQ provides a feature called <quote>guards</quote> 32.113 + (which originates with quilt's <literal>guards</literal> 32.114 + command) that does just this. To start off, let's create a 32.115 + simple repository for experimenting in.</para> 32.116 + 32.117 + &interaction.mq.guards.init; 32.118 + 32.119 + <para id="x_16c">This gives us a tiny repository that contains two patches 32.120 + that don't have any dependencies on each other, because they 32.121 + touch different files.</para> 32.122 + 32.123 + <para id="x_16d">The idea behind conditional application is that you can 32.124 + <quote>tag</quote> a patch with a <emphasis>guard</emphasis>, 32.125 + which is simply a text string of your choosing, then tell MQ to 32.126 + select specific guards to use when applying patches. MQ will 32.127 + then either apply, or skip over, a guarded patch, depending on 32.128 + the guards that you have selected.</para> 32.129 + 32.130 + <para id="x_16e">A patch can have an arbitrary number of guards; each one is 32.131 + <emphasis>positive</emphasis> (<quote>apply this patch if this 32.132 + guard is selected</quote>) or <emphasis>negative</emphasis> 32.133 + (<quote>skip this patch if this guard is selected</quote>). A 32.134 + patch with no guards is always applied.</para> 32.135 + 32.136 + </sect1> 32.137 + <sect1> 32.138 + <title>Controlling the guards on a patch</title> 32.139 + 32.140 + <para id="x_16f">The <command role="hg-ext-mq">qguard</command> command lets 32.141 + you determine which guards should apply to a patch, or display 32.142 + the guards that are already in effect. Without any arguments, it 32.143 + displays the guards on the current topmost patch.</para> 32.144 + 32.145 + &interaction.mq.guards.qguard; 32.146 + 32.147 + <para id="x_170">To set a positive guard on a patch, prefix the name of the 32.148 + guard with a <quote><literal>+</literal></quote>.</para> 32.149 + 32.150 + &interaction.mq.guards.qguard.pos; 32.151 + 32.152 + <para id="x_171">To set a negative guard 32.153 + on a patch, prefix the name of the guard with a 32.154 + <quote><literal>-</literal></quote>.</para> 32.155 + 32.156 + &interaction.mq.guards.qguard.neg; 32.157 + 32.158 + <note> 32.159 + <para id="x_172"> The <command role="hg-ext-mq">qguard</command> command 32.160 + <emphasis>sets</emphasis> the guards on a patch; it doesn't 32.161 + <emphasis>modify</emphasis> them. What this means is that if 32.162 + you run <command role="hg-cmd">hg qguard +a +b</command> on a 32.163 + patch, then <command role="hg-cmd">hg qguard +c</command> on 32.164 + the same patch, the <emphasis>only</emphasis> guard that will 32.165 + be set on it afterwards is <literal>+c</literal>.</para> 32.166 + </note> 32.167 + 32.168 + <para id="x_173">Mercurial stores guards in the <filename 32.169 + role="special">series</filename> file; the form in which they 32.170 + are stored is easy both to understand and to edit by hand. (In 32.171 + other words, you don't have to use the <command 32.172 + role="hg-ext-mq">qguard</command> command if you don't want 32.173 + to; it's okay to simply edit the <filename 32.174 + role="special">series</filename> file.)</para> 32.175 + 32.176 + &interaction.mq.guards.series; 32.177 + 32.178 + </sect1> 32.179 + <sect1> 32.180 + <title>Selecting the guards to use</title> 32.181 + 32.182 + <para id="x_174">The <command role="hg-ext-mq">qselect</command> command 32.183 + determines which guards are active at a given time. The effect 32.184 + of this is to determine which patches MQ will apply the next 32.185 + time you run <command role="hg-ext-mq">qpush</command>. It has 32.186 + no other effect; in particular, it doesn't do anything to 32.187 + patches that are already applied.</para> 32.188 + 32.189 + <para id="x_175">With no arguments, the <command 32.190 + role="hg-ext-mq">qselect</command> command lists the guards 32.191 + currently in effect, one per line of output. Each argument is 32.192 + treated as the name of a guard to apply.</para> 32.193 + 32.194 + &interaction.mq.guards.qselect.foo; 32.195 + 32.196 + <para id="x_176">In case you're interested, the currently selected guards are 32.197 + stored in the <filename role="special">guards</filename> file.</para> 32.198 + 32.199 + &interaction.mq.guards.qselect.cat; 32.200 + 32.201 + <para id="x_177">We can see the effect the selected guards have when we run 32.202 + <command role="hg-ext-mq">qpush</command>.</para> 32.203 + 32.204 + &interaction.mq.guards.qselect.qpush; 32.205 + 32.206 + <para id="x_178">A guard cannot start with a 32.207 + <quote><literal>+</literal></quote> or 32.208 + <quote><literal>-</literal></quote> character. The name of a 32.209 + guard must not contain white space, but most other characters 32.210 + are acceptable. If you try to use a guard with an invalid name, 32.211 + MQ will complain:</para> 32.212 + 32.213 + &interaction.mq.guards.qselect.error; 32.214 + 32.215 + <para id="x_179">Changing the selected guards changes the patches that are 32.216 + applied.</para> 32.217 + 32.218 + &interaction.mq.guards.qselect.quux; 32.219 + 32.220 + <para id="x_17a">You can see in the example below that negative guards take 32.221 + precedence over positive guards.</para> 32.222 + 32.223 + &interaction.mq.guards.qselect.foobar; 32.224 + 32.225 + </sect1> 32.226 + <sect1> 32.227 + <title>MQ's rules for applying patches</title> 32.228 + 32.229 + <para id="x_17b">The rules that MQ uses when deciding whether to apply a 32.230 + patch are as follows.</para> 32.231 + <itemizedlist> 32.232 + <listitem><para id="x_17c">A patch that has no guards is always 32.233 + applied.</para> 32.234 + </listitem> 32.235 + <listitem><para id="x_17d">If the patch has any negative guard that matches 32.236 + any currently selected guard, the patch is skipped.</para> 32.237 + </listitem> 32.238 + <listitem><para id="x_17e">If the patch has any positive guard that matches 32.239 + any currently selected guard, the patch is applied.</para> 32.240 + </listitem> 32.241 + <listitem><para id="x_17f">If the patch has positive or negative guards, 32.242 + but none matches any currently selected guard, the patch is 32.243 + skipped.</para> 32.244 + </listitem></itemizedlist> 32.245 + 32.246 + </sect1> 32.247 + <sect1> 32.248 + <title>Trimming the work environment</title> 32.249 + 32.250 + <para id="x_180">In working on the device driver I mentioned earlier, I don't 32.251 + apply the patches to a normal Linux kernel tree. Instead, I use 32.252 + a repository that contains only a snapshot of the source files 32.253 + and headers that are relevant to Infiniband development. This 32.254 + repository is 1% the size of a kernel repository, so it's easier 32.255 + to work with.</para> 32.256 + 32.257 + <para id="x_181">I then choose a <quote>base</quote> version on top of which 32.258 + the patches are applied. This is a snapshot of the Linux kernel 32.259 + tree as of a revision of my choosing. When I take the snapshot, 32.260 + I record the changeset ID from the kernel repository in the 32.261 + commit message. Since the snapshot preserves the 32.262 + <quote>shape</quote> and content of the relevant parts of the 32.263 + kernel tree, I can apply my patches on top of either my tiny 32.264 + repository or a normal kernel tree.</para> 32.265 + 32.266 + <para id="x_182">Normally, the base tree atop which the patches apply should 32.267 + be a snapshot of a very recent upstream tree. This best 32.268 + facilitates the development of patches that can easily be 32.269 + submitted upstream with few or no modifications.</para> 32.270 + 32.271 + </sect1> 32.272 + <sect1> 32.273 + <title>Dividing up the <filename role="special">series</filename> 32.274 + file</title> 32.275 + 32.276 + <para id="x_183">I categorise the patches in the <filename 32.277 + role="special">series</filename> file into a number of logical 32.278 + groups. Each section of like patches begins with a block of 32.279 + comments that describes the purpose of the patches that 32.280 + follow.</para> 32.281 + 32.282 + <para id="x_184">The sequence of patch groups that I maintain follows. The 32.283 + ordering of these groups is important; I'll describe why after I 32.284 + introduce the groups.</para> 32.285 + <itemizedlist> 32.286 + <listitem><para id="x_185">The <quote>accepted</quote> group. Patches that 32.287 + the development team has submitted to the maintainer of the 32.288 + Infiniband subsystem, and which he has accepted, but which 32.289 + are not present in the snapshot that the tiny repository is 32.290 + based on. These are <quote>read only</quote> patches, 32.291 + present only to transform the tree into a similar state as 32.292 + it is in the upstream maintainer's repository.</para> 32.293 + </listitem> 32.294 + <listitem><para id="x_186">The <quote>rework</quote> group. Patches that I 32.295 + have submitted, but that the upstream maintainer has 32.296 + requested modifications to before he will accept 32.297 + them.</para> 32.298 + </listitem> 32.299 + <listitem><para id="x_187">The <quote>pending</quote> group. Patches that 32.300 + I have not yet submitted to the upstream maintainer, but 32.301 + which we have finished working on. These will be <quote>read 32.302 + only</quote> for a while. If the upstream maintainer 32.303 + accepts them upon submission, I'll move them to the end of 32.304 + the <quote>accepted</quote> group. If he requests that I 32.305 + modify any, I'll move them to the beginning of the 32.306 + <quote>rework</quote> group.</para> 32.307 + </listitem> 32.308 + <listitem><para id="x_188">The <quote>in progress</quote> group. Patches 32.309 + that are actively being developed, and should not be 32.310 + submitted anywhere yet.</para> 32.311 + </listitem> 32.312 + <listitem><para id="x_189">The <quote>backport</quote> group. Patches that 32.313 + adapt the source tree to older versions of the kernel 32.314 + tree.</para> 32.315 + </listitem> 32.316 + <listitem><para id="x_18a">The <quote>do not ship</quote> group. Patches 32.317 + that for some reason should never be submitted upstream. 32.318 + For example, one such patch might change embedded driver 32.319 + identification strings to make it easier to distinguish, in 32.320 + the field, between an out-of-tree version of the driver and 32.321 + a version shipped by a distribution vendor.</para> 32.322 + </listitem></itemizedlist> 32.323 + 32.324 + <para id="x_18b">Now to return to the reasons for ordering groups of patches 32.325 + in this way. We would like the lowest patches in the stack to 32.326 + be as stable as possible, so that we will not need to rework 32.327 + higher patches due to changes in context. Putting patches that 32.328 + will never be changed first in the <filename 32.329 + role="special">series</filename> file serves this 32.330 + purpose.</para> 32.331 + 32.332 + <para id="x_18c">We would also like the patches that we know we'll need to 32.333 + modify to be applied on top of a source tree that resembles the 32.334 + upstream tree as closely as possible. This is why we keep 32.335 + accepted patches around for a while.</para> 32.336 + 32.337 + <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote> 32.338 + patches float at the end of the <filename 32.339 + role="special">series</filename> file. The backport patches 32.340 + must be applied on top of all other patches, and the <quote>do 32.341 + not ship</quote> patches might as well stay out of harm's 32.342 + way.</para> 32.343 + 32.344 + </sect1> 32.345 + <sect1> 32.346 + <title>Maintaining the patch series</title> 32.347 + 32.348 + <para id="x_18e">In my work, I use a number of guards to control which 32.349 + patches are to be applied.</para> 32.350 + 32.351 + <itemizedlist> 32.352 + <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with 32.353 + <literal>accepted</literal>. I enable this guard most of 32.354 + the time. When I'm applying the patches on top of a tree 32.355 + where the patches are already present, I can turn this patch 32.356 + off, and the patches that follow it will apply 32.357 + cleanly.</para> 32.358 + </listitem> 32.359 + <listitem><para id="x_190">Patches that are <quote>finished</quote>, but 32.360 + not yet submitted, have no guards. If I'm applying the 32.361 + patch stack to a copy of the upstream tree, I don't need to 32.362 + enable any guards in order to get a reasonably safe source 32.363 + tree.</para> 32.364 + </listitem> 32.365 + <listitem><para id="x_191">Those patches that need reworking before being 32.366 + resubmitted are guarded with 32.367 + <literal>rework</literal>.</para> 32.368 + </listitem> 32.369 + <listitem><para id="x_192">For those patches that are still under 32.370 + development, I use <literal>devel</literal>.</para> 32.371 + </listitem> 32.372 + <listitem><para id="x_193">A backport patch may have several guards, one 32.373 + for each version of the kernel to which it applies. For 32.374 + example, a patch that backports a piece of code to 2.6.9 32.375 + will have a <literal>2.6.9</literal> guard.</para> 32.376 + </listitem></itemizedlist> 32.377 + <para id="x_194">This variety of guards gives me considerable flexibility in 32.378 + determining what kind of source tree I want to end up with. For 32.379 + most situations, the selection of appropriate guards is 32.380 + automated during the build process, but I can manually tune the 32.381 + guards to use for less common circumstances.</para> 32.382 + 32.383 + <sect2> 32.384 + <title>The art of writing backport patches</title> 32.385 + 32.386 + <para id="x_195">Using MQ, writing a backport patch is a simple process. 32.387 + All such a patch has to do is modify a piece of code that uses 32.388 + a kernel feature not present in the older version of the 32.389 + kernel, so that the driver continues to work correctly under 32.390 + that older version.</para> 32.391 + 32.392 + <para id="x_196">A useful goal when writing a good backport patch is to 32.393 + make your code look as if it was written for the older version 32.394 + of the kernel you're targeting. The less obtrusive the patch, 32.395 + the easier it will be to understand and maintain. If you're 32.396 + writing a collection of backport patches to avoid the 32.397 + <quote>rat's nest</quote> effect of lots of 32.398 + <literal>#ifdef</literal>s (hunks of source code that are only 32.399 + used conditionally) in your code, don't introduce 32.400 + version-dependent <literal>#ifdef</literal>s into the patches. 32.401 + Instead, write several patches, each of which makes 32.402 + unconditional changes, and control their application using 32.403 + guards.</para> 32.404 + 32.405 + <para id="x_197">There are two reasons to divide backport patches into a 32.406 + distinct group, away from the <quote>regular</quote> patches 32.407 + whose effects they modify. The first is that intermingling the 32.408 + two makes it more difficult to use a tool like the <literal 32.409 + role="hg-ext">patchbomb</literal> extension to automate the 32.410 + process of submitting the patches to an upstream maintainer. 32.411 + The second is that a backport patch could perturb the context 32.412 + in which a subsequent regular patch is applied, making it 32.413 + impossible to apply the regular patch cleanly 32.414 + <emphasis>without</emphasis> the earlier backport patch 32.415 + already being applied.</para> 32.416 + 32.417 + </sect2> 32.418 + </sect1> 32.419 + <sect1> 32.420 + <title>Useful tips for developing with MQ</title> 32.421 + 32.422 + <sect2> 32.423 + <title>Organising patches in directories</title> 32.424 + 32.425 + <para id="x_198">If you're working on a substantial project with MQ, it's 32.426 + not difficult to accumulate a large number of patches. For 32.427 + example, I have one patch repository that contains over 250 32.428 + patches.</para> 32.429 + 32.430 + <para id="x_199">If you can group these patches into separate logical 32.431 + categories, you can if you like store them in different 32.432 + directories; MQ has no problems with patch names that contain 32.433 + path separators.</para> 32.434 + 32.435 + </sect2> 32.436 + <sect2 id="mq-collab.tips.interdiff"> 32.437 + <title>Viewing the history of a patch</title> 32.438 + 32.439 + <para id="x_19a">If you're developing a set of patches over a long time, 32.440 + it's a good idea to maintain them in a repository, as 32.441 + discussed in section <xref linkend="sec.mq.repo"/>. If you do 32.442 + so, you'll quickly 32.443 + discover that using the <command role="hg-cmd">hg 32.444 + diff</command> command to look at the history of changes to 32.445 + a patch is unworkable. This is in part because you're looking 32.446 + at the second derivative of the real code (a diff of a diff), 32.447 + but also because MQ adds noise to the process by modifying 32.448 + time stamps and directory names when it updates a 32.449 + patch.</para> 32.450 + 32.451 + <para id="x_19b">However, you can use the <literal 32.452 + role="hg-ext">extdiff</literal> extension, which is bundled 32.453 + with Mercurial, to turn a diff of two versions of a patch into 32.454 + something readable. To do this, you will need a third-party 32.455 + package called <literal role="package">patchutils</literal> 32.456 + <citation>web:patchutils</citation>. This provides a command 32.457 + named <command>interdiff</command>, which shows the 32.458 + differences between two diffs as a diff. Used on two versions 32.459 + of the same diff, it generates a diff that represents the diff 32.460 + from the first to the second version.</para> 32.461 + 32.462 + <para id="x_19c">You can enable the <literal 32.463 + role="hg-ext">extdiff</literal> extension in the usual way, 32.464 + by adding a line to the <literal 32.465 + role="rc-extensions">extensions</literal> section of your 32.466 + <filename role="special">~/.hgrc</filename>.</para> 32.467 + <programlisting>[extensions] 32.468 +extdiff =</programlisting> 32.469 + <para id="x_19d">The <command>interdiff</command> command expects to be 32.470 + passed the names of two files, but the <literal 32.471 + role="hg-ext">extdiff</literal> extension passes the program 32.472 + it runs a pair of directories, each of which can contain an 32.473 + arbitrary number of files. We thus need a small program that 32.474 + will run <command>interdiff</command> on each pair of files in 32.475 + these two directories. This program is available as <filename 32.476 + role="special">hg-interdiff</filename> in the <filename 32.477 + class="directory">examples</filename> directory of the 32.478 + source code repository that accompanies this book. <!-- 32.479 + &example.hg-interdiff; --></para> 32.480 + 32.481 + <para id="x_19e">With the <filename role="special">hg-interdiff</filename> 32.482 + program in your shell's search path, you can run it as 32.483 + follows, from inside an MQ patch directory:</para> 32.484 + <programlisting>hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting> 32.485 + <para id="x_19f">Since you'll probably want to use this long-winded command 32.486 + a lot, you can get <literal role="hg-ext">hgext</literal> to 32.487 + make it available as a normal Mercurial command, again by 32.488 + editing your <filename 32.489 + role="special">~/.hgrc</filename>.</para> 32.490 + <programlisting>[extdiff] 32.491 +cmd.interdiff = hg-interdiff</programlisting> 32.492 + <para id="x_1a0">This directs <literal role="hg-ext">hgext</literal> to 32.493 + make an <literal>interdiff</literal> command available, so you 32.494 + can now shorten the previous invocation of <command 32.495 + role="hg-ext-extdiff">extdiff</command> to something a 32.496 + little more wieldy.</para> 32.497 + <programlisting>hg interdiff -r A:B my-change.patch</programlisting> 32.498 + 32.499 + <note> 32.500 + <para id="x_1a1"> The <command>interdiff</command> command works well 32.501 + only if the underlying files against which versions of a 32.502 + patch are generated remain the same. If you create a patch, 32.503 + modify the underlying files, and then regenerate the patch, 32.504 + <command>interdiff</command> may not produce useful 32.505 + output.</para> 32.506 + </note> 32.507 + 32.508 + <para id="x_1a2">The <literal role="hg-ext">extdiff</literal> extension is 32.509 + useful for more than merely improving the presentation of MQ 32.510 + patches. To read more about it, go to section <xref 32.511 + linkend="sec.hgext.extdiff"/>.</para> 32.512 + 32.513 + </sect2> 32.514 + </sect1> 32.515 +</chapter> 32.516 + 32.517 +<!-- 32.518 +local variables: 32.519 +sgml-parent-document: ("00book.xml" "book" "chapter") 32.520 +end: 32.521 +-->
33.1 --- a/en/ch12-mq.xml Fri Mar 20 15:40:06 2009 +0800 33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 33.3 @@ -1,1323 +0,0 @@ 33.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 33.5 - 33.6 -<chapter id="chap.mq"> 33.7 - <?dbhtml filename="managing-change-with-mercurial-queues.html"?> 33.8 - <title>Managing change with Mercurial Queues</title> 33.9 - 33.10 - <sect1 id="sec.mq.patch-mgmt"> 33.11 - <title>The patch management problem</title> 33.12 - 33.13 - <para>Here is a common scenario: you need to install a software 33.14 - package from source, but you find a bug that you must fix in the 33.15 - source before you can start using the package. You make your 33.16 - changes, forget about the package for a while, and a few months 33.17 - later you need to upgrade to a newer version of the package. If 33.18 - the newer version of the package still has the bug, you must 33.19 - extract your fix from the older source tree and apply it against 33.20 - the newer version. This is a tedious task, and it's easy to 33.21 - make mistakes.</para> 33.22 - 33.23 - <para>This is a simple case of the <quote>patch management</quote> 33.24 - problem. You have an <quote>upstream</quote> source tree that 33.25 - you can't change; you need to make some local changes on top of 33.26 - the upstream tree; and you'd like to be able to keep those 33.27 - changes separate, so that you can apply them to newer versions 33.28 - of the upstream source.</para> 33.29 - 33.30 - <para>The patch management problem arises in many situations. 33.31 - Probably the most visible is that a user of an open source 33.32 - software project will contribute a bug fix or new feature to the 33.33 - project's maintainers in the form of a patch.</para> 33.34 - 33.35 - <para>Distributors of operating systems that include open source 33.36 - software often need to make changes to the packages they 33.37 - distribute so that they will build properly in their 33.38 - environments.</para> 33.39 - 33.40 - <para>When you have few changes to maintain, it is easy to manage 33.41 - a single patch using the standard <command>diff</command> and 33.42 - <command>patch</command> programs (see section <xref 33.43 - linkend="sec.mq.patch"/> for a discussion of these 33.44 - tools). Once the number of changes grows, it starts to make 33.45 - sense to maintain patches as discrete <quote>chunks of 33.46 - work,</quote> so that for example a single patch will contain 33.47 - only one bug fix (the patch might modify several files, but it's 33.48 - doing <quote>only one thing</quote>), and you may have a number 33.49 - of such patches for different bugs you need fixed and local 33.50 - changes you require. In this situation, if you submit a bug fix 33.51 - patch to the upstream maintainers of a package and they include 33.52 - your fix in a subsequent release, you can simply drop that 33.53 - single patch when you're updating to the newer release.</para> 33.54 - 33.55 - <para>Maintaining a single patch against an upstream tree is a 33.56 - little tedious and error-prone, but not difficult. However, the 33.57 - complexity of the problem grows rapidly as the number of patches 33.58 - you have to maintain increases. With more than a tiny number of 33.59 - patches in hand, understanding which ones you have applied and 33.60 - maintaining them moves from messy to overwhelming.</para> 33.61 - 33.62 - <para>Fortunately, Mercurial includes a powerful extension, 33.63 - Mercurial Queues (or simply <quote>MQ</quote>), that massively 33.64 - simplifies the patch management problem.</para> 33.65 - 33.66 - </sect1> 33.67 - <sect1 id="sec.mq.history"> 33.68 - <title>The prehistory of Mercurial Queues</title> 33.69 - 33.70 - <para>During the late 1990s, several Linux kernel developers 33.71 - started to maintain <quote>patch series</quote> that modified 33.72 - the behaviour of the Linux kernel. Some of these series were 33.73 - focused on stability, some on feature coverage, and others were 33.74 - more speculative.</para> 33.75 - 33.76 - <para>The sizes of these patch series grew rapidly. In 2002, 33.77 - Andrew Morton published some shell scripts he had been using to 33.78 - automate the task of managing his patch queues. Andrew was 33.79 - successfully using these scripts to manage hundreds (sometimes 33.80 - thousands) of patches on top of the Linux kernel.</para> 33.81 - 33.82 - <sect2 id="sec.mq.quilt"> 33.83 - <title>A patchwork quilt</title> 33.84 - 33.85 - <para>In early 2003, Andreas Gruenbacher and Martin Quinson 33.86 - borrowed the approach of Andrew's scripts and published a tool 33.87 - called <quote>patchwork quilt</quote> 33.88 - <citation>web:quilt</citation>, or simply <quote>quilt</quote> 33.89 - (see <citation>gruenbacher:2005</citation> for a paper 33.90 - describing it). Because quilt substantially automated patch 33.91 - management, it rapidly gained a large following among open 33.92 - source software developers.</para> 33.93 - 33.94 - <para>Quilt manages a <emphasis>stack of patches</emphasis> on 33.95 - top of a directory tree. To begin, you tell quilt to manage a 33.96 - directory tree, and tell it which files you want to manage; it 33.97 - stores away the names and contents of those files. To fix a 33.98 - bug, you create a new patch (using a single command), edit the 33.99 - files you need to fix, then <quote>refresh</quote> the 33.100 - patch.</para> 33.101 - 33.102 - <para>The refresh step causes quilt to scan the directory tree; 33.103 - it updates the patch with all of the changes you have made. 33.104 - You can create another patch on top of the first, which will 33.105 - track the changes required to modify the tree from <quote>tree 33.106 - with one patch applied</quote> to <quote>tree with two 33.107 - patches applied</quote>.</para> 33.108 - 33.109 - <para>You can <emphasis>change</emphasis> which patches are 33.110 - applied to the tree. If you <quote>pop</quote> a patch, the 33.111 - changes made by that patch will vanish from the directory 33.112 - tree. Quilt remembers which patches you have popped, though, 33.113 - so you can <quote>push</quote> a popped patch again, and the 33.114 - directory tree will be restored to contain the modifications 33.115 - in the patch. Most importantly, you can run the 33.116 - <quote>refresh</quote> command at any time, and the topmost 33.117 - applied patch will be updated. This means that you can, at 33.118 - any time, change both which patches are applied and what 33.119 - modifications those patches make.</para> 33.120 - 33.121 - <para>Quilt knows nothing about revision control tools, so it 33.122 - works equally well on top of an unpacked tarball or a 33.123 - Subversion working copy.</para> 33.124 - 33.125 - </sect2> 33.126 - <sect2 id="sec.mq.quilt-mq"> 33.127 - <title>From patchwork quilt to Mercurial Queues</title> 33.128 - 33.129 - <para>In mid-2005, Chris Mason took the features of quilt and 33.130 - wrote an extension that he called Mercurial Queues, which 33.131 - added quilt-like behaviour to Mercurial.</para> 33.132 - 33.133 - <para>The key difference between quilt and MQ is that quilt 33.134 - knows nothing about revision control systems, while MQ is 33.135 - <emphasis>integrated</emphasis> into Mercurial. Each patch 33.136 - that you push is represented as a Mercurial changeset. Pop a 33.137 - patch, and the changeset goes away.</para> 33.138 - 33.139 - <para>Because quilt does not care about revision control tools, 33.140 - it is still a tremendously useful piece of software to know 33.141 - about for situations where you cannot use Mercurial and 33.142 - MQ.</para> 33.143 - 33.144 - </sect2> 33.145 - </sect1> 33.146 - <sect1> 33.147 - <title>The huge advantage of MQ</title> 33.148 - 33.149 - <para>I cannot overstate the value that MQ offers through the 33.150 - unification of patches and revision control.</para> 33.151 - 33.152 - <para>A major reason that patches have persisted in the free 33.153 - software and open source world&emdash;in spite of the 33.154 - availability of increasingly capable revision control tools over 33.155 - the years&emdash;is the <emphasis>agility</emphasis> they 33.156 - offer.</para> 33.157 - 33.158 - <para>Traditional revision control tools make a permanent, 33.159 - irreversible record of everything that you do. While this has 33.160 - great value, it's also somewhat stifling. If you want to 33.161 - perform a wild-eyed experiment, you have to be careful in how 33.162 - you go about it, or you risk leaving unneeded&emdash;or worse, 33.163 - misleading or destabilising&emdash;traces of your missteps and 33.164 - errors in the permanent revision record.</para> 33.165 - 33.166 - <para>By contrast, MQ's marriage of distributed revision control 33.167 - with patches makes it much easier to isolate your work. Your 33.168 - patches live on top of normal revision history, and you can make 33.169 - them disappear or reappear at will. If you don't like a patch, 33.170 - you can drop it. If a patch isn't quite as you want it to be, 33.171 - simply fix it&emdash;as many times as you need to, until you 33.172 - have refined it into the form you desire.</para> 33.173 - 33.174 - <para>As an example, the integration of patches with revision 33.175 - control makes understanding patches and debugging their 33.176 - effects&emdash;and their interplay with the code they're based 33.177 - on&emdash;<emphasis>enormously</emphasis> easier. Since every 33.178 - applied patch has an associated changeset, you can give <command 33.179 - role="hg-cmd">hg log</command> a file name to see which 33.180 - changesets and patches affected the file. You can use the 33.181 - <command role="hg-cmd">hg bisect</command> command to 33.182 - binary-search through all changesets and applied patches to see 33.183 - where a bug got introduced or fixed. You can use the <command 33.184 - role="hg-cmd">hg annotate</command> command to see which 33.185 - changeset or patch modified a particular line of a source file. 33.186 - And so on.</para> 33.187 - 33.188 - </sect1> 33.189 - <sect1 id="sec.mq.patch"> 33.190 - <title>Understanding patches</title> 33.191 - 33.192 - <para>Because MQ doesn't hide its patch-oriented nature, it is 33.193 - helpful to understand what patches are, and a little about the 33.194 - tools that work with them.</para> 33.195 - 33.196 - <para>The traditional Unix <command>diff</command> command 33.197 - compares two files, and prints a list of differences between 33.198 - them. The <command>patch</command> command understands these 33.199 - differences as <emphasis>modifications</emphasis> to make to a 33.200 - file. Take a look below for a simple example of these commands 33.201 - in action.</para> 33.202 - 33.203 -&interaction.mq.dodiff.diff; 33.204 - 33.205 - <para>The type of file that <command>diff</command> generates (and 33.206 - <command>patch</command> takes as input) is called a 33.207 - <quote>patch</quote> or a <quote>diff</quote>; there is no 33.208 - difference between a patch and a diff. (We'll use the term 33.209 - <quote>patch</quote>, since it's more commonly used.)</para> 33.210 - 33.211 - <para>A patch file can start with arbitrary text; the 33.212 - <command>patch</command> command ignores this text, but MQ uses 33.213 - it as the commit message when creating changesets. To find the 33.214 - beginning of the patch content, <command>patch</command> 33.215 - searches for the first line that starts with the string 33.216 - <quote><literal>diff -</literal></quote>.</para> 33.217 - 33.218 - <para>MQ works with <emphasis>unified</emphasis> diffs 33.219 - (<command>patch</command> can accept several other diff formats, 33.220 - but MQ doesn't). A unified diff contains two kinds of header. 33.221 - The <emphasis>file header</emphasis> describes the file being 33.222 - modified; it contains the name of the file to modify. When 33.223 - <command>patch</command> sees a new file header, it looks for a 33.224 - file with that name to start modifying.</para> 33.225 - 33.226 - <para>After the file header comes a series of 33.227 - <emphasis>hunks</emphasis>. Each hunk starts with a header; 33.228 - this identifies the range of line numbers within the file that 33.229 - the hunk should modify. Following the header, a hunk starts and 33.230 - ends with a few (usually three) lines of text from the 33.231 - unmodified file; these are called the 33.232 - <emphasis>context</emphasis> for the hunk. If there's only a 33.233 - small amount of context between successive hunks, 33.234 - <command>diff</command> doesn't print a new hunk header; it just 33.235 - runs the hunks together, with a few lines of context between 33.236 - modifications.</para> 33.237 - 33.238 - <para>Each line of context begins with a space character. Within 33.239 - the hunk, a line that begins with 33.240 - <quote><literal>-</literal></quote> means <quote>remove this 33.241 - line,</quote> while a line that begins with 33.242 - <quote><literal>+</literal></quote> means <quote>insert this 33.243 - line.</quote> For example, a line that is modified is 33.244 - represented by one deletion and one insertion.</para> 33.245 - 33.246 - <para>We will return to some of the more subtle aspects of patches 33.247 - later (in section <xref linkend="sec.mq.adv-patch"/>), but you 33.248 - should have 33.249 - enough information now to use MQ.</para> 33.250 - 33.251 - </sect1> 33.252 - <sect1 id="sec.mq.start"> 33.253 - <title>Getting started with Mercurial Queues</title> 33.254 - 33.255 - <para>Because MQ is implemented as an extension, you must 33.256 - explicitly enable before you can use it. (You don't need to 33.257 - download anything; MQ ships with the standard Mercurial 33.258 - distribution.) To enable MQ, edit your <filename 33.259 - role="home">~/.hgrc</filename> file, and add the lines 33.260 - below.</para> 33.261 - 33.262 - <programlisting>[extensions] 33.263 -hgext.mq =</programlisting> 33.264 - 33.265 - <para>Once the extension is enabled, it will make a number of new 33.266 - commands available. To verify that the extension is working, 33.267 - you can use <command role="hg-cmd">hg help</command> to see if 33.268 - the <command role="hg-ext-mq">qinit</command> command is now 33.269 - available.</para> 33.270 - 33.271 -&interaction.mq.qinit-help.help; 33.272 - 33.273 - <para>You can use MQ with <emphasis>any</emphasis> Mercurial 33.274 - repository, and its commands only operate within that 33.275 - repository. To get started, simply prepare the repository using 33.276 - the <command role="hg-ext-mq">qinit</command> command.</para> 33.277 - 33.278 -&interaction.mq.tutorial.qinit; 33.279 - 33.280 - <para>This command creates an empty directory called <filename 33.281 - role="special" class="directory">.hg/patches</filename>, where 33.282 - MQ will keep its metadata. As with many Mercurial commands, the 33.283 - <command role="hg-ext-mq">qinit</command> command prints nothing 33.284 - if it succeeds.</para> 33.285 - 33.286 - <sect2> 33.287 - <title>Creating a new patch</title> 33.288 - 33.289 - <para>To begin work on a new patch, use the <command 33.290 - role="hg-ext-mq">qnew</command> command. This command takes 33.291 - one argument, the name of the patch to create.</para> 33.292 - 33.293 - <para>MQ will use this as the name of an actual file in the 33.294 - <filename role="special" 33.295 - class="directory">.hg/patches</filename> directory, as you 33.296 - can see below.</para> 33.297 - 33.298 -&interaction.mq.tutorial.qnew; 33.299 - 33.300 - <para>Also newly present in the <filename role="special" 33.301 - class="directory">.hg/patches</filename> directory are two 33.302 - other files, <filename role="special">series</filename> and 33.303 - <filename role="special">status</filename>. The <filename 33.304 - role="special">series</filename> file lists all of the 33.305 - patches that MQ knows about for this repository, with one 33.306 - patch per line. Mercurial uses the <filename 33.307 - role="special">status</filename> file for internal 33.308 - book-keeping; it tracks all of the patches that MQ has 33.309 - <emphasis>applied</emphasis> in this repository.</para> 33.310 - 33.311 - <note> 33.312 - <para> You may sometimes want to edit the <filename 33.313 - role="special">series</filename> file by hand; for 33.314 - example, to change the sequence in which some patches are 33.315 - applied. However, manually editing the <filename 33.316 - role="special">status</filename> file is almost always a 33.317 - bad idea, as it's easy to corrupt MQ's idea of what is 33.318 - happening.</para> 33.319 - </note> 33.320 - 33.321 - <para>Once you have created your new patch, you can edit files 33.322 - in the working directory as you usually would. All of the 33.323 - normal Mercurial commands, such as <command role="hg-cmd">hg 33.324 - diff</command> and <command role="hg-cmd">hg 33.325 - annotate</command>, work exactly as they did before.</para> 33.326 - 33.327 - </sect2> 33.328 - <sect2> 33.329 - <title>Refreshing a patch</title> 33.330 - 33.331 - <para>When you reach a point where you want to save your work, 33.332 - use the <command role="hg-ext-mq">qrefresh</command> command 33.333 - to update the patch you are working on.</para> 33.334 - 33.335 -&interaction.mq.tutorial.qrefresh; 33.336 - 33.337 - <para>This command folds the changes you have made in the 33.338 - working directory into your patch, and updates its 33.339 - corresponding changeset to contain those changes.</para> 33.340 - 33.341 - <para>You can run <command role="hg-ext-mq">qrefresh</command> 33.342 - as often as you like, so it's a good way to 33.343 - <quote>checkpoint</quote> your work. Refresh your patch at an 33.344 - opportune time; try an experiment; and if the experiment 33.345 - doesn't work out, <command role="hg-cmd">hg revert</command> 33.346 - your modifications back to the last time you refreshed.</para> 33.347 - 33.348 -&interaction.mq.tutorial.qrefresh2; 33.349 - 33.350 - </sect2> 33.351 - <sect2> 33.352 - <title>Stacking and tracking patches</title> 33.353 - 33.354 - <para>Once you have finished working on a patch, or need to work 33.355 - on another, you can use the <command 33.356 - role="hg-ext-mq">qnew</command> command again to create a 33.357 - new patch. Mercurial will apply this patch on top of your 33.358 - existing patch.</para> 33.359 - 33.360 -&interaction.mq.tutorial.qnew2; 33.361 - <para>Notice that the patch contains the changes in our prior 33.362 - patch as part of its context (you can see this more clearly in 33.363 - the output of <command role="hg-cmd">hg 33.364 - annotate</command>).</para> 33.365 - 33.366 - <para>So far, with the exception of <command 33.367 - role="hg-ext-mq">qnew</command> and <command 33.368 - role="hg-ext-mq">qrefresh</command>, we've been careful to 33.369 - only use regular Mercurial commands. However, MQ provides 33.370 - many commands that are easier to use when you are thinking 33.371 - about patches, as illustrated below.</para> 33.372 - 33.373 -&interaction.mq.tutorial.qseries; 33.374 - 33.375 - <itemizedlist> 33.376 - <listitem><para>The <command 33.377 - role="hg-ext-mq">qseries</command> command lists every 33.378 - patch that MQ knows about in this repository, from oldest 33.379 - to newest (most recently 33.380 - <emphasis>created</emphasis>).</para> 33.381 - </listitem> 33.382 - <listitem><para>The <command 33.383 - role="hg-ext-mq">qapplied</command> command lists every 33.384 - patch that MQ has <emphasis>applied</emphasis> in this 33.385 - repository, again from oldest to newest (most recently 33.386 - applied).</para> 33.387 - </listitem></itemizedlist> 33.388 - 33.389 - </sect2> 33.390 - <sect2> 33.391 - <title>Manipulating the patch stack</title> 33.392 - 33.393 - <para>The previous discussion implied that there must be a 33.394 - difference between <quote>known</quote> and 33.395 - <quote>applied</quote> patches, and there is. MQ can manage a 33.396 - patch without it being applied in the repository.</para> 33.397 - 33.398 - <para>An <emphasis>applied</emphasis> patch has a corresponding 33.399 - changeset in the repository, and the effects of the patch and 33.400 - changeset are visible in the working directory. You can undo 33.401 - the application of a patch using the <command 33.402 - role="hg-ext-mq">qpop</command> command. MQ still 33.403 - <emphasis>knows about</emphasis>, or manages, a popped patch, 33.404 - but the patch no longer has a corresponding changeset in the 33.405 - repository, and the working directory does not contain the 33.406 - changes made by the patch. Figure <xref 33.407 - endterm="fig.mq.stack.caption" linkend="fig.mq.stack"/> illustrates 33.408 - the difference between applied and tracked patches.</para> 33.409 - 33.410 - <informalfigure id="fig.mq.stack"> 33.411 - <mediaobject> 33.412 - <imageobject><imagedata fileref="images/mq-stack.png"/></imageobject> 33.413 - <textobject><phrase>XXX add text</phrase></textobject> 33.414 - <caption><para id="fig.mq.stack.caption">Applied and unapplied patches 33.415 - in the MQ patch stack</para></caption> 33.416 - </mediaobject> 33.417 - </informalfigure> 33.418 - 33.419 - <para>You can reapply an unapplied, or popped, patch using the 33.420 - <command role="hg-ext-mq">qpush</command> command. This 33.421 - creates a new changeset to correspond to the patch, and the 33.422 - patch's changes once again become present in the working 33.423 - directory. See below for examples of <command 33.424 - role="hg-ext-mq">qpop</command> and <command 33.425 - role="hg-ext-mq">qpush</command> in action.</para> 33.426 -&interaction.mq.tutorial.qpop; 33.427 - 33.428 - <para>Notice that once we have popped a patch or two patches, 33.429 - the output of <command role="hg-ext-mq">qseries</command> 33.430 - remains the same, while that of <command 33.431 - role="hg-ext-mq">qapplied</command> has changed.</para> 33.432 - 33.433 - 33.434 - </sect2> 33.435 - <sect2> 33.436 - <title>Pushing and popping many patches</title> 33.437 - 33.438 - <para>While <command role="hg-ext-mq">qpush</command> and 33.439 - <command role="hg-ext-mq">qpop</command> each operate on a 33.440 - single patch at a time by default, you can push and pop many 33.441 - patches in one go. The <option 33.442 - role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to 33.443 - <command role="hg-ext-mq">qpush</command> causes it to push 33.444 - all unapplied patches, while the <option 33.445 - role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command 33.446 - role="hg-ext-mq">qpop</command> causes it to pop all applied 33.447 - patches. (For some more ways to push and pop many patches, 33.448 - see section <xref linkend="sec.mq.perf"/> 33.449 - below.)</para> 33.450 - 33.451 -&interaction.mq.tutorial.qpush-a; 33.452 - 33.453 - </sect2> 33.454 - <sect2> 33.455 - <title>Safety checks, and overriding them</title> 33.456 - 33.457 - <para>Several MQ commands check the working directory before 33.458 - they do anything, and fail if they find any modifications. 33.459 - They do this to ensure that you won't lose any changes that 33.460 - you have made, but not yet incorporated into a patch. The 33.461 - example below illustrates this; the <command 33.462 - role="hg-ext-mq">qnew</command> command will not create a 33.463 - new patch if there are outstanding changes, caused in this 33.464 - case by the <command role="hg-cmd">hg add</command> of 33.465 - <filename>file3</filename>.</para> 33.466 - 33.467 -&interaction.mq.tutorial.add; 33.468 - 33.469 - <para>Commands that check the working directory all take an 33.470 - <quote>I know what I'm doing</quote> option, which is always 33.471 - named <option>-f</option>. The exact meaning of 33.472 - <option>-f</option> depends on the command. For example, 33.473 - <command role="hg-cmd">hg qnew <option 33.474 - role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command> 33.475 - will incorporate any outstanding changes into the new patch it 33.476 - creates, but <command role="hg-cmd">hg qpop <option 33.477 - role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command> 33.478 - will revert modifications to any files affected by the patch 33.479 - that it is popping. Be sure to read the documentation for a 33.480 - command's <option>-f</option> option before you use it!</para> 33.481 - 33.482 - </sect2> 33.483 - <sect2> 33.484 - <title>Working on several patches at once</title> 33.485 - 33.486 - <para>The <command role="hg-ext-mq">qrefresh</command> command 33.487 - always refreshes the <emphasis>topmost</emphasis> applied 33.488 - patch. This means that you can suspend work on one patch (by 33.489 - refreshing it), pop or push to make a different patch the top, 33.490 - and work on <emphasis>that</emphasis> patch for a 33.491 - while.</para> 33.492 - 33.493 - <para>Here's an example that illustrates how you can use this 33.494 - ability. Let's say you're developing a new feature as two 33.495 - patches. The first is a change to the core of your software, 33.496 - and the second&emdash;layered on top of the 33.497 - first&emdash;changes the user interface to use the code you 33.498 - just added to the core. If you notice a bug in the core while 33.499 - you're working on the UI patch, it's easy to fix the core. 33.500 - Simply <command role="hg-ext-mq">qrefresh</command> the UI 33.501 - patch to save your in-progress changes, and <command 33.502 - role="hg-ext-mq">qpop</command> down to the core patch. Fix 33.503 - the core bug, <command role="hg-ext-mq">qrefresh</command> the 33.504 - core patch, and <command role="hg-ext-mq">qpush</command> back 33.505 - to the UI patch to continue where you left off.</para> 33.506 - 33.507 - </sect2> 33.508 - </sect1> 33.509 - <sect1 id="sec.mq.adv-patch"> 33.510 - <title>More about patches</title> 33.511 - 33.512 - <para>MQ uses the GNU <command>patch</command> command to apply 33.513 - patches, so it's helpful to know a few more detailed aspects of 33.514 - how <command>patch</command> works, and about patches 33.515 - themselves.</para> 33.516 - 33.517 - <sect2> 33.518 - <title>The strip count</title> 33.519 - 33.520 - <para>If you look at the file headers in a patch, you will 33.521 - notice that the pathnames usually have an extra component on 33.522 - the front that isn't present in the actual path name. This is 33.523 - a holdover from the way that people used to generate patches 33.524 - (people still do this, but it's somewhat rare with modern 33.525 - revision control tools).</para> 33.526 - 33.527 - <para>Alice would unpack a tarball, edit her files, then decide 33.528 - that she wanted to create a patch. So she'd rename her 33.529 - working directory, unpack the tarball again (hence the need 33.530 - for the rename), and use the <option 33.531 - role="cmd-opt-diff">-r</option> and <option 33.532 - role="cmd-opt-diff">-N</option> options to 33.533 - <command>diff</command> to recursively generate a patch 33.534 - between the unmodified directory and the modified one. The 33.535 - result would be that the name of the unmodified directory 33.536 - would be at the front of the left-hand path in every file 33.537 - header, and the name of the modified directory would be at the 33.538 - front of the right-hand path.</para> 33.539 - 33.540 - <para>Since someone receiving a patch from the Alices of the net 33.541 - would be unlikely to have unmodified and modified directories 33.542 - with exactly the same names, the <command>patch</command> 33.543 - command has a <option role="cmd-opt-patch">-p</option> option 33.544 - that indicates the number of leading path name components to 33.545 - strip when trying to apply a patch. This number is called the 33.546 - <emphasis>strip count</emphasis>.</para> 33.547 - 33.548 - <para>An option of <quote><literal>-p1</literal></quote> means 33.549 - <quote>use a strip count of one</quote>. If 33.550 - <command>patch</command> sees a file name 33.551 - <filename>foo/bar/baz</filename> in a file header, it will 33.552 - strip <filename>foo</filename> and try to patch a file named 33.553 - <filename>bar/baz</filename>. (Strictly speaking, the strip 33.554 - count refers to the number of <emphasis>path 33.555 - separators</emphasis> (and the components that go with them 33.556 - ) to strip. A strip count of one will turn 33.557 - <filename>foo/bar</filename> into <filename>bar</filename>, 33.558 - but <filename>/foo/bar</filename> (notice the extra leading 33.559 - slash) into <filename>foo/bar</filename>.)</para> 33.560 - 33.561 - <para>The <quote>standard</quote> strip count for patches is 33.562 - one; almost all patches contain one leading path name 33.563 - component that needs to be stripped. Mercurial's <command 33.564 - role="hg-cmd">hg diff</command> command generates path names 33.565 - in this form, and the <command role="hg-cmd">hg 33.566 - import</command> command and MQ expect patches to have a 33.567 - strip count of one.</para> 33.568 - 33.569 - <para>If you receive a patch from someone that you want to add 33.570 - to your patch queue, and the patch needs a strip count other 33.571 - than one, you cannot just <command 33.572 - role="hg-ext-mq">qimport</command> the patch, because 33.573 - <command role="hg-ext-mq">qimport</command> does not yet have 33.574 - a <literal>-p</literal> option (see <ulink role="hg-bug" 33.575 - url="http://www.selenic.com/mercurial/bts/issue311">issue 33.576 - 311</ulink>). Your best bet is to <command 33.577 - role="hg-ext-mq">qnew</command> a patch of your own, then 33.578 - use <command>patch -pN</command> to apply their patch, 33.579 - followed by <command role="hg-cmd">hg addremove</command> to 33.580 - pick up any files added or removed by the patch, followed by 33.581 - <command role="hg-ext-mq">hg qrefresh</command>. This 33.582 - complexity may become unnecessary; see <ulink role="hg-bug" 33.583 - url="http://www.selenic.com/mercurial/bts/issue311">issue 33.584 - 311</ulink> for details. 33.585 - </para> 33.586 - </sect2> 33.587 - <sect2> 33.588 - <title>Strategies for applying a patch</title> 33.589 - 33.590 - <para>When <command>patch</command> applies a hunk, it tries a 33.591 - handful of successively less accurate strategies to try to 33.592 - make the hunk apply. This falling-back technique often makes 33.593 - it possible to take a patch that was generated against an old 33.594 - version of a file, and apply it against a newer version of 33.595 - that file.</para> 33.596 - 33.597 - <para>First, <command>patch</command> tries an exact match, 33.598 - where the line numbers, the context, and the text to be 33.599 - modified must apply exactly. If it cannot make an exact 33.600 - match, it tries to find an exact match for the context, 33.601 - without honouring the line numbering information. If this 33.602 - succeeds, it prints a line of output saying that the hunk was 33.603 - applied, but at some <emphasis>offset</emphasis> from the 33.604 - original line number.</para> 33.605 - 33.606 - <para>If a context-only match fails, <command>patch</command> 33.607 - removes the first and last lines of the context, and tries a 33.608 - <emphasis>reduced</emphasis> context-only match. If the hunk 33.609 - with reduced context succeeds, it prints a message saying that 33.610 - it applied the hunk with a <emphasis>fuzz factor</emphasis> 33.611 - (the number after the fuzz factor indicates how many lines of 33.612 - context <command>patch</command> had to trim before the patch 33.613 - applied).</para> 33.614 - 33.615 - <para>When neither of these techniques works, 33.616 - <command>patch</command> prints a message saying that the hunk 33.617 - in question was rejected. It saves rejected hunks (also 33.618 - simply called <quote>rejects</quote>) to a file with the same 33.619 - name, and an added <filename role="special">.rej</filename> 33.620 - extension. It also saves an unmodified copy of the file with 33.621 - a <filename role="special">.orig</filename> extension; the 33.622 - copy of the file without any extensions will contain any 33.623 - changes made by hunks that <emphasis>did</emphasis> apply 33.624 - cleanly. If you have a patch that modifies 33.625 - <filename>foo</filename> with six hunks, and one of them fails 33.626 - to apply, you will have: an unmodified 33.627 - <filename>foo.orig</filename>, a <filename>foo.rej</filename> 33.628 - containing one hunk, and <filename>foo</filename>, containing 33.629 - the changes made by the five successful hunks.</para> 33.630 - 33.631 - </sect2> 33.632 - <sect2> 33.633 - <title>Some quirks of patch representation</title> 33.634 - 33.635 - <para>There are a few useful things to know about how 33.636 - <command>patch</command> works with files.</para> 33.637 - <itemizedlist> 33.638 - <listitem><para>This should already be obvious, but 33.639 - <command>patch</command> cannot handle binary 33.640 - files.</para> 33.641 - </listitem> 33.642 - <listitem><para>Neither does it care about the executable bit; 33.643 - it creates new files as readable, but not 33.644 - executable.</para> 33.645 - </listitem> 33.646 - <listitem><para><command>patch</command> treats the removal of 33.647 - a file as a diff between the file to be removed and the 33.648 - empty file. So your idea of <quote>I deleted this 33.649 - file</quote> looks like <quote>every line of this file 33.650 - was deleted</quote> in a patch.</para> 33.651 - </listitem> 33.652 - <listitem><para>It treats the addition of a file as a diff 33.653 - between the empty file and the file to be added. So in a 33.654 - patch, your idea of <quote>I added this file</quote> looks 33.655 - like <quote>every line of this file was 33.656 - added</quote>.</para> 33.657 - </listitem> 33.658 - <listitem><para>It treats a renamed file as the removal of the 33.659 - old name, and the addition of the new name. This means 33.660 - that renamed files have a big footprint in patches. (Note 33.661 - also that Mercurial does not currently try to infer when 33.662 - files have been renamed or copied in a patch.)</para> 33.663 - </listitem> 33.664 - <listitem><para><command>patch</command> cannot represent 33.665 - empty files, so you cannot use a patch to represent the 33.666 - notion <quote>I added this empty file to the 33.667 - tree</quote>.</para> 33.668 - </listitem></itemizedlist> 33.669 - </sect2> 33.670 - <sect2> 33.671 - <title>Beware the fuzz</title> 33.672 - 33.673 - <para>While applying a hunk at an offset, or with a fuzz factor, 33.674 - will often be completely successful, these inexact techniques 33.675 - naturally leave open the possibility of corrupting the patched 33.676 - file. The most common cases typically involve applying a 33.677 - patch twice, or at an incorrect location in the file. If 33.678 - <command>patch</command> or <command 33.679 - role="hg-ext-mq">qpush</command> ever mentions an offset or 33.680 - fuzz factor, you should make sure that the modified files are 33.681 - correct afterwards.</para> 33.682 - 33.683 - <para>It's often a good idea to refresh a patch that has applied 33.684 - with an offset or fuzz factor; refreshing the patch generates 33.685 - new context information that will make it apply cleanly. I 33.686 - say <quote>often,</quote> not <quote>always,</quote> because 33.687 - sometimes refreshing a patch will make it fail to apply 33.688 - against a different revision of the underlying files. In some 33.689 - cases, such as when you're maintaining a patch that must sit 33.690 - on top of multiple versions of a source tree, it's acceptable 33.691 - to have a patch apply with some fuzz, provided you've verified 33.692 - the results of the patching process in such cases.</para> 33.693 - 33.694 - </sect2> 33.695 - <sect2> 33.696 - <title>Handling rejection</title> 33.697 - 33.698 - <para>If <command role="hg-ext-mq">qpush</command> fails to 33.699 - apply a patch, it will print an error message and exit. If it 33.700 - has left <filename role="special">.rej</filename> files 33.701 - behind, it is usually best to fix up the rejected hunks before 33.702 - you push more patches or do any further work.</para> 33.703 - 33.704 - <para>If your patch <emphasis>used to</emphasis> apply cleanly, 33.705 - and no longer does because you've changed the underlying code 33.706 - that your patches are based on, Mercurial Queues can help; see 33.707 - section <xref 33.708 - linkend="sec.mq.merge"/> for details.</para> 33.709 - 33.710 - <para>Unfortunately, there aren't any great techniques for 33.711 - dealing with rejected hunks. Most often, you'll need to view 33.712 - the <filename role="special">.rej</filename> file and edit the 33.713 - target file, applying the rejected hunks by hand.</para> 33.714 - 33.715 - <para>If you're feeling adventurous, Neil Brown, a Linux kernel 33.716 - hacker, wrote a tool called <command>wiggle</command> 33.717 - <citation>web:wiggle</citation>, which is more vigorous than 33.718 - <command>patch</command> in its attempts to make a patch 33.719 - apply.</para> 33.720 - 33.721 - <para>Another Linux kernel hacker, Chris Mason (the author of 33.722 - Mercurial Queues), wrote a similar tool called 33.723 - <command>mpatch</command> <citation>web:mpatch</citation>, 33.724 - which takes a simple approach to automating the application of 33.725 - hunks rejected by <command>patch</command>. The 33.726 - <command>mpatch</command> command can help with four common 33.727 - reasons that a hunk may be rejected:</para> 33.728 - 33.729 - <itemizedlist> 33.730 - <listitem><para>The context in the middle of a hunk has 33.731 - changed.</para> 33.732 - </listitem> 33.733 - <listitem><para>A hunk is missing some context at the 33.734 - beginning or end.</para> 33.735 - </listitem> 33.736 - <listitem><para>A large hunk might apply better&emdash;either 33.737 - entirely or in part&emdash;if it was broken up into 33.738 - smaller hunks.</para> 33.739 - </listitem> 33.740 - <listitem><para>A hunk removes lines with slightly different 33.741 - content than those currently present in the file.</para> 33.742 - </listitem></itemizedlist> 33.743 - 33.744 - <para>If you use <command>wiggle</command> or 33.745 - <command>mpatch</command>, you should be doubly careful to 33.746 - check your results when you're done. In fact, 33.747 - <command>mpatch</command> enforces this method of 33.748 - double-checking the tool's output, by automatically dropping 33.749 - you into a merge program when it has done its job, so that you 33.750 - can verify its work and finish off any remaining 33.751 - merges.</para> 33.752 - 33.753 - </sect2> 33.754 - </sect1> 33.755 - <sect1 id="sec.mq.perf"> 33.756 - <title>Getting the best performance out of MQ</title> 33.757 - 33.758 - <para>MQ is very efficient at handling a large number of patches. 33.759 - I ran some performance experiments in mid-2006 for a talk that I 33.760 - gave at the 2006 EuroPython conference 33.761 - <citation>web:europython</citation>. I used as my data set the 33.762 - Linux 2.6.17-mm1 patch series, which consists of 1,738 patches. 33.763 - I applied these on top of a Linux kernel repository containing 33.764 - all 27,472 revisions between Linux 2.6.12-rc2 and Linux 33.765 - 2.6.17.</para> 33.766 - 33.767 - <para>On my old, slow laptop, I was able to <command 33.768 - role="hg-cmd">hg qpush <option 33.769 - role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all 33.770 - 1,738 patches in 3.5 minutes, and <command role="hg-cmd">hg qpop 33.771 - <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> 33.772 - them all in 30 seconds. (On a newer laptop, the time to push 33.773 - all patches dropped to two minutes.) I could <command 33.774 - role="hg-ext-mq">qrefresh</command> one of the biggest patches 33.775 - (which made 22,779 lines of changes to 287 files) in 6.6 33.776 - seconds.</para> 33.777 - 33.778 - <para>Clearly, MQ is well suited to working in large trees, but 33.779 - there are a few tricks you can use to get the best performance 33.780 - of it.</para> 33.781 - 33.782 - <para>First of all, try to <quote>batch</quote> operations 33.783 - together. Every time you run <command 33.784 - role="hg-ext-mq">qpush</command> or <command 33.785 - role="hg-ext-mq">qpop</command>, these commands scan the 33.786 - working directory once to make sure you haven't made some 33.787 - changes and then forgotten to run <command 33.788 - role="hg-ext-mq">qrefresh</command>. On a small tree, the 33.789 - time that this scan takes is unnoticeable. However, on a 33.790 - medium-sized tree (containing tens of thousands of files), it 33.791 - can take a second or more.</para> 33.792 - 33.793 - <para>The <command role="hg-ext-mq">qpush</command> and <command 33.794 - role="hg-ext-mq">qpop</command> commands allow you to push and 33.795 - pop multiple patches at a time. You can identify the 33.796 - <quote>destination patch</quote> that you want to end up at. 33.797 - When you <command role="hg-ext-mq">qpush</command> with a 33.798 - destination specified, it will push patches until that patch is 33.799 - at the top of the applied stack. When you <command 33.800 - role="hg-ext-mq">qpop</command> to a destination, MQ will pop 33.801 - patches until the destination patch is at the top.</para> 33.802 - 33.803 - <para>You can identify a destination patch using either the name 33.804 - of the patch, or by number. If you use numeric addressing, 33.805 - patches are counted from zero; this means that the first patch 33.806 - is zero, the second is one, and so on.</para> 33.807 - 33.808 - </sect1> 33.809 - <sect1 id="sec.mq.merge"> 33.810 - <title>Updating your patches when the underlying code 33.811 - changes</title> 33.812 - 33.813 - <para>It's common to have a stack of patches on top of an 33.814 - underlying repository that you don't modify directly. If you're 33.815 - working on changes to third-party code, or on a feature that is 33.816 - taking longer to develop than the rate of change of the code 33.817 - beneath, you will often need to sync up with the underlying 33.818 - code, and fix up any hunks in your patches that no longer apply. 33.819 - This is called <emphasis>rebasing</emphasis> your patch 33.820 - series.</para> 33.821 - 33.822 - <para>The simplest way to do this is to <command role="hg-cmd">hg 33.823 - qpop <option role="hg-ext-mq-cmd-qpop-opt">hg 33.824 - -a</option></command> your patches, then <command 33.825 - role="hg-cmd">hg pull</command> changes into the underlying 33.826 - repository, and finally <command role="hg-cmd">hg qpush <option 33.827 - role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your 33.828 - patches again. MQ will stop pushing any time it runs across a 33.829 - patch that fails to apply during conflicts, allowing you to fix 33.830 - your conflicts, <command role="hg-ext-mq">qrefresh</command> the 33.831 - affected patch, and continue pushing until you have fixed your 33.832 - entire stack.</para> 33.833 - 33.834 - <para>This approach is easy to use and works well if you don't 33.835 - expect changes to the underlying code to affect how well your 33.836 - patches apply. If your patch stack touches code that is modified 33.837 - frequently or invasively in the underlying repository, however, 33.838 - fixing up rejected hunks by hand quickly becomes 33.839 - tiresome.</para> 33.840 - 33.841 - <para>It's possible to partially automate the rebasing process. 33.842 - If your patches apply cleanly against some revision of the 33.843 - underlying repo, MQ can use this information to help you to 33.844 - resolve conflicts between your patches and a different 33.845 - revision.</para> 33.846 - 33.847 - <para>The process is a little involved.</para> 33.848 - <orderedlist> 33.849 - <listitem><para>To begin, <command role="hg-cmd">hg qpush 33.850 - -a</command> all of your patches on top of the revision 33.851 - where you know that they apply cleanly.</para> 33.852 - </listitem> 33.853 - <listitem><para>Save a backup copy of your patch directory using 33.854 - <command role="hg-cmd">hg qsave <option 33.855 - role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option 33.856 - role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>. 33.857 - This prints the name of the directory that it has saved the 33.858 - patches in. It will save the patches to a directory called 33.859 - <filename role="special" 33.860 - class="directory">.hg/patches.N</filename>, where 33.861 - <literal>N</literal> is a small integer. It also commits a 33.862 - <quote>save changeset</quote> on top of your applied 33.863 - patches; this is for internal book-keeping, and records the 33.864 - states of the <filename role="special">series</filename> and 33.865 - <filename role="special">status</filename> files.</para> 33.866 - </listitem> 33.867 - <listitem><para>Use <command role="hg-cmd">hg pull</command> to 33.868 - bring new changes into the underlying repository. (Don't 33.869 - run <command role="hg-cmd">hg pull -u</command>; see below 33.870 - for why.)</para> 33.871 - </listitem> 33.872 - <listitem><para>Update to the new tip revision, using <command 33.873 - role="hg-cmd">hg update <option 33.874 - role="hg-opt-update">-C</option></command> to override 33.875 - the patches you have pushed.</para> 33.876 - </listitem> 33.877 - <listitem><para>Merge all patches using <command>hg qpush -m 33.878 - -a</command>. The <option 33.879 - role="hg-ext-mq-cmd-qpush-opt">-m</option> option to 33.880 - <command role="hg-ext-mq">qpush</command> tells MQ to 33.881 - perform a three-way merge if the patch fails to 33.882 - apply.</para> 33.883 - </listitem></orderedlist> 33.884 - 33.885 - <para>During the <command role="hg-cmd">hg qpush <option 33.886 - role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>, 33.887 - each patch in the <filename role="special">series</filename> 33.888 - file is applied normally. If a patch applies with fuzz or 33.889 - rejects, MQ looks at the queue you <command 33.890 - role="hg-ext-mq">qsave</command>d, and performs a three-way 33.891 - merge with the corresponding changeset. This merge uses 33.892 - Mercurial's normal merge machinery, so it may pop up a GUI merge 33.893 - tool to help you to resolve problems.</para> 33.894 - 33.895 - <para>When you finish resolving the effects of a patch, MQ 33.896 - refreshes your patch based on the result of the merge.</para> 33.897 - 33.898 - <para>At the end of this process, your repository will have one 33.899 - extra head from the old patch queue, and a copy of the old patch 33.900 - queue will be in <filename role="special" 33.901 - class="directory">.hg/patches.N</filename>. You can remove the 33.902 - extra head using <command role="hg-cmd">hg qpop -a -n 33.903 - patches.N</command> or <command role="hg-cmd">hg 33.904 - strip</command>. You can delete <filename role="special" 33.905 - class="directory">.hg/patches.N</filename> once you are sure 33.906 - that you no longer need it as a backup.</para> 33.907 - 33.908 - </sect1> 33.909 - <sect1> 33.910 - <title>Identifying patches</title> 33.911 - 33.912 - <para>MQ commands that work with patches let you refer to a patch 33.913 - either by using its name or by a number. By name is obvious 33.914 - enough; pass the name <filename>foo.patch</filename> to <command 33.915 - role="hg-ext-mq">qpush</command>, for example, and it will 33.916 - push patches until <filename>foo.patch</filename> is 33.917 - applied.</para> 33.918 - 33.919 - <para>As a shortcut, you can refer to a patch using both a name 33.920 - and a numeric offset; <literal>foo.patch-2</literal> means 33.921 - <quote>two patches before <literal>foo.patch</literal></quote>, 33.922 - while <literal>bar.patch+4</literal> means <quote>four patches 33.923 - after <literal>bar.patch</literal></quote>.</para> 33.924 - 33.925 - <para>Referring to a patch by index isn't much different. The 33.926 - first patch printed in the output of <command 33.927 - role="hg-ext-mq">qseries</command> is patch zero (yes, it's 33.928 - one of those start-at-zero counting systems); the second is 33.929 - patch one; and so on.</para> 33.930 - 33.931 - <para>MQ also makes it easy to work with patches when you are 33.932 - using normal Mercurial commands. Every command that accepts a 33.933 - changeset ID will also accept the name of an applied patch. MQ 33.934 - augments the tags normally in the repository with an eponymous 33.935 - one for each applied patch. In addition, the special tags 33.936 - <literal role="tag">qbase</literal> and 33.937 - <literal role="tag">qtip</literal> identify 33.938 - the <quote>bottom-most</quote> and topmost applied patches, 33.939 - respectively.</para> 33.940 - 33.941 - <para>These additions to Mercurial's normal tagging capabilities 33.942 - make dealing with patches even more of a breeze.</para> 33.943 - <itemizedlist> 33.944 - <listitem><para>Want to patchbomb a mailing list with your 33.945 - latest series of changes?</para> 33.946 - <programlisting>hg email qbase:qtip</programlisting> 33.947 - <para> (Don't know what <quote>patchbombing</quote> is? See 33.948 - section <xref linkend="sec.hgext.patchbomb"/>.)</para> 33.949 - </listitem> 33.950 - <listitem><para>Need to see all of the patches since 33.951 - <literal>foo.patch</literal> that have touched files in a 33.952 - subdirectory of your tree?</para> 33.953 - <programlisting>hg log -r foo.patch:qtip subdir</programlisting> 33.954 - </listitem> 33.955 - </itemizedlist> 33.956 - 33.957 - <para>Because MQ makes the names of patches available to the rest 33.958 - of Mercurial through its normal internal tag machinery, you 33.959 - don't need to type in the entire name of a patch when you want 33.960 - to identify it by name.</para> 33.961 - 33.962 - <para>Another nice consequence of representing patch names as tags 33.963 - is that when you run the <command role="hg-cmd">hg log</command> 33.964 - command, it will display a patch's name as a tag, simply as part 33.965 - of its normal output. This makes it easy to visually 33.966 - distinguish applied patches from underlying 33.967 - <quote>normal</quote> revisions. The following example shows a 33.968 - few normal Mercurial commands in use with applied 33.969 - patches.</para> 33.970 - 33.971 -&interaction.mq.id.output; 33.972 - 33.973 - </sect1> 33.974 - <sect1> 33.975 - <title>Useful things to know about</title> 33.976 - 33.977 - <para>There are a number of aspects of MQ usage that don't fit 33.978 - tidily into sections of their own, but that are good to know. 33.979 - Here they are, in one place.</para> 33.980 - 33.981 - <itemizedlist> 33.982 - <listitem><para>Normally, when you <command 33.983 - role="hg-ext-mq">qpop</command> a patch and <command 33.984 - role="hg-ext-mq">qpush</command> it again, the changeset 33.985 - that represents the patch after the pop/push will have a 33.986 - <emphasis>different identity</emphasis> than the changeset 33.987 - that represented the hash beforehand. See section <xref 33.988 - linkend="sec.mqref.cmd.qpush"/> for 33.989 - information as to why this is.</para> 33.990 - </listitem> 33.991 - <listitem><para>It's not a good idea to <command 33.992 - role="hg-cmd">hg merge</command> changes from another 33.993 - branch with a patch changeset, at least if you want to 33.994 - maintain the <quote>patchiness</quote> of that changeset and 33.995 - changesets below it on the patch stack. If you try to do 33.996 - this, it will appear to succeed, but MQ will become 33.997 - confused.</para> 33.998 - </listitem></itemizedlist> 33.999 - 33.1000 - </sect1> 33.1001 - <sect1 id="sec.mq.repo"> 33.1002 - <title>Managing patches in a repository</title> 33.1003 - 33.1004 - <para>Because MQ's <filename role="special" 33.1005 - class="directory">.hg/patches</filename> directory resides 33.1006 - outside a Mercurial repository's working directory, the 33.1007 - <quote>underlying</quote> Mercurial repository knows nothing 33.1008 - about the management or presence of patches.</para> 33.1009 - 33.1010 - <para>This presents the interesting possibility of managing the 33.1011 - contents of the patch directory as a Mercurial repository in its 33.1012 - own right. This can be a useful way to work. For example, you 33.1013 - can work on a patch for a while, <command 33.1014 - role="hg-ext-mq">qrefresh</command> it, then <command 33.1015 - role="hg-cmd">hg commit</command> the current state of the 33.1016 - patch. This lets you <quote>roll back</quote> to that version 33.1017 - of the patch later on.</para> 33.1018 - 33.1019 - <para>You can then share different versions of the same patch 33.1020 - stack among multiple underlying repositories. I use this when I 33.1021 - am developing a Linux kernel feature. I have a pristine copy of 33.1022 - my kernel sources for each of several CPU architectures, and a 33.1023 - cloned repository under each that contains the patches I am 33.1024 - working on. When I want to test a change on a different 33.1025 - architecture, I push my current patches to the patch repository 33.1026 - associated with that kernel tree, pop and push all of my 33.1027 - patches, and build and test that kernel.</para> 33.1028 - 33.1029 - <para>Managing patches in a repository makes it possible for 33.1030 - multiple developers to work on the same patch series without 33.1031 - colliding with each other, all on top of an underlying source 33.1032 - base that they may or may not control.</para> 33.1033 - 33.1034 - <sect2> 33.1035 - <title>MQ support for patch repositories</title> 33.1036 - 33.1037 - <para>MQ helps you to work with the <filename role="special" 33.1038 - class="directory">.hg/patches</filename> directory as a 33.1039 - repository; when you prepare a repository for working with 33.1040 - patches using <command role="hg-ext-mq">qinit</command>, you 33.1041 - can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg 33.1042 - -c</option> option to create the <filename role="special" 33.1043 - class="directory">.hg/patches</filename> directory as a 33.1044 - Mercurial repository.</para> 33.1045 - 33.1046 - <note> 33.1047 - <para> If you forget to use the <option 33.1048 - role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you 33.1049 - can simply go into the <filename role="special" 33.1050 - class="directory">.hg/patches</filename> directory at any 33.1051 - time and run <command role="hg-cmd">hg init</command>. 33.1052 - Don't forget to add an entry for the <filename 33.1053 - role="special">status</filename> file to the <filename 33.1054 - role="special">.hgignore</filename> file, though</para> 33.1055 - 33.1056 - <para> (<command role="hg-cmd">hg qinit <option 33.1057 - role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command> 33.1058 - does this for you automatically); you 33.1059 - <emphasis>really</emphasis> don't want to manage the 33.1060 - <filename role="special">status</filename> file.</para> 33.1061 - </note> 33.1062 - 33.1063 - <para>As a convenience, if MQ notices that the <filename 33.1064 - class="directory">.hg/patches</filename> directory is a 33.1065 - repository, it will automatically <command role="hg-cmd">hg 33.1066 - add</command> every patch that you create and import.</para> 33.1067 - 33.1068 - <para>MQ provides a shortcut command, <command 33.1069 - role="hg-ext-mq">qcommit</command>, that runs <command 33.1070 - role="hg-cmd">hg commit</command> in the <filename 33.1071 - role="special" class="directory">.hg/patches</filename> 33.1072 - directory. This saves some bothersome typing.</para> 33.1073 - 33.1074 - <para>Finally, as a convenience to manage the patch directory, 33.1075 - you can define the alias <command>mq</command> on Unix 33.1076 - systems. For example, on Linux systems using the 33.1077 - <command>bash</command> shell, you can include the following 33.1078 - snippet in your <filename 33.1079 - role="home">~/.bashrc</filename>.</para> 33.1080 - 33.1081 - <programlisting>alias mq=`hg -R $(hg root)/.hg/patches'</programlisting> 33.1082 - 33.1083 - <para>You can then issue commands of the form <command>mq 33.1084 - pull</command> from the main repository.</para> 33.1085 - 33.1086 - </sect2> 33.1087 - <sect2> 33.1088 - <title>A few things to watch out for</title> 33.1089 - 33.1090 - <para>MQ's support for working with a repository full of patches 33.1091 - is limited in a few small respects.</para> 33.1092 - 33.1093 - <para>MQ cannot automatically detect changes that you make to 33.1094 - the patch directory. If you <command role="hg-cmd">hg 33.1095 - pull</command>, manually edit, or <command role="hg-cmd">hg 33.1096 - update</command> changes to patches or the <filename 33.1097 - role="special">series</filename> file, you will have to 33.1098 - <command role="hg-cmd">hg qpop <option 33.1099 - role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and 33.1100 - then <command role="hg-cmd">hg qpush <option 33.1101 - role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in 33.1102 - the underlying repository to see those changes show up there. 33.1103 - If you forget to do this, you can confuse MQ's idea of which 33.1104 - patches are applied.</para> 33.1105 - 33.1106 - </sect2> 33.1107 - </sect1> 33.1108 - <sect1 id="sec.mq.tools"> 33.1109 - <title>Third party tools for working with patches</title> 33.1110 - 33.1111 - <para>Once you've been working with patches for a while, you'll 33.1112 - find yourself hungry for tools that will help you to understand 33.1113 - and manipulate the patches you're dealing with.</para> 33.1114 - 33.1115 - <para>The <command>diffstat</command> command 33.1116 - <citation>web:diffstat</citation> generates a histogram of the 33.1117 - modifications made to each file in a patch. It provides a good 33.1118 - way to <quote>get a sense of</quote> a patch&emdash;which files 33.1119 - it affects, and how much change it introduces to each file and 33.1120 - as a whole. (I find that it's a good idea to use 33.1121 - <command>diffstat</command>'s <option 33.1122 - role="cmd-opt-diffstat">-p</option> option as a matter of 33.1123 - course, as otherwise it will try to do clever things with 33.1124 - prefixes of file names that inevitably confuse at least 33.1125 - me.)</para> 33.1126 - 33.1127 -&interaction.mq.tools.tools; 33.1128 - 33.1129 - <para>The <literal role="package">patchutils</literal> package 33.1130 - <citation>web:patchutils</citation> is invaluable. It provides a 33.1131 - set of small utilities that follow the <quote>Unix 33.1132 - philosophy;</quote> each does one useful thing with a patch. 33.1133 - The <literal role="package">patchutils</literal> command I use 33.1134 - most is <command>filterdiff</command>, which extracts subsets 33.1135 - from a patch file. For example, given a patch that modifies 33.1136 - hundreds of files across dozens of directories, a single 33.1137 - invocation of <command>filterdiff</command> can generate a 33.1138 - smaller patch that only touches files whose names match a 33.1139 - particular glob pattern. See section <xref 33.1140 - linkend="mq-collab.tips.interdiff"/> for another 33.1141 - example.</para> 33.1142 - 33.1143 - </sect1> 33.1144 - <sect1> 33.1145 - <title>Good ways to work with patches</title> 33.1146 - 33.1147 - <para>Whether you are working on a patch series to submit to a 33.1148 - free software or open source project, or a series that you 33.1149 - intend to treat as a sequence of regular changesets when you're 33.1150 - done, you can use some simple techniques to keep your work well 33.1151 - organised.</para> 33.1152 - 33.1153 - <para>Give your patches descriptive names. A good name for a 33.1154 - patch might be <filename>rework-device-alloc.patch</filename>, 33.1155 - because it will immediately give you a hint what the purpose of 33.1156 - the patch is. Long names shouldn't be a problem; you won't be 33.1157 - typing the names often, but you <emphasis>will</emphasis> be 33.1158 - running commands like <command 33.1159 - role="hg-ext-mq">qapplied</command> and <command 33.1160 - role="hg-ext-mq">qtop</command> over and over. Good naming 33.1161 - becomes especially important when you have a number of patches 33.1162 - to work with, or if you are juggling a number of different tasks 33.1163 - and your patches only get a fraction of your attention.</para> 33.1164 - 33.1165 - <para>Be aware of what patch you're working on. Use the <command 33.1166 - role="hg-ext-mq">qtop</command> command and skim over the text 33.1167 - of your patches frequently&emdash;for example, using <command 33.1168 - role="hg-cmd">hg tip <option 33.1169 - role="hg-opt-tip">-p</option></command>)&emdash;to be sure 33.1170 - of where you stand. I have several times worked on and <command 33.1171 - role="hg-ext-mq">qrefresh</command>ed a patch other than the 33.1172 - one I intended, and it's often tricky to migrate changes into 33.1173 - the right patch after making them in the wrong one.</para> 33.1174 - 33.1175 - <para>For this reason, it is very much worth investing a little 33.1176 - time to learn how to use some of the third-party tools I 33.1177 - described in section <xref linkend="sec.mq.tools"/>, 33.1178 - particularly 33.1179 - <command>diffstat</command> and <command>filterdiff</command>. 33.1180 - The former will give you a quick idea of what changes your patch 33.1181 - is making, while the latter makes it easy to splice hunks 33.1182 - selectively out of one patch and into another.</para> 33.1183 - 33.1184 - </sect1> 33.1185 - <sect1> 33.1186 - <title>MQ cookbook</title> 33.1187 - 33.1188 - <sect2> 33.1189 - <title>Manage <quote>trivial</quote> patches</title> 33.1190 - 33.1191 - <para>Because the overhead of dropping files into a new 33.1192 - Mercurial repository is so low, it makes a lot of sense to 33.1193 - manage patches this way even if you simply want to make a few 33.1194 - changes to a source tarball that you downloaded.</para> 33.1195 - 33.1196 - <para>Begin by downloading and unpacking the source tarball, and 33.1197 - turning it into a Mercurial repository.</para> 33.1198 - 33.1199 - &interaction.mq.tarball.download; 33.1200 - 33.1201 - <para>Continue by creating a patch stack and making your 33.1202 - changes.</para> 33.1203 - 33.1204 - &interaction.mq.tarball.qinit; 33.1205 - 33.1206 - <para>Let's say a few weeks or months pass, and your package 33.1207 - author releases a new version. First, bring their changes 33.1208 - into the repository.</para> 33.1209 - 33.1210 - &interaction.mq.tarball.newsource; 33.1211 - 33.1212 - <para>The pipeline starting with <command role="hg-cmd">hg 33.1213 - locate</command> above deletes all files in the working 33.1214 - directory, so that <command role="hg-cmd">hg 33.1215 - commit</command>'s <option 33.1216 - role="hg-opt-commit">--addremove</option> option can 33.1217 - actually tell which files have really been removed in the 33.1218 - newer version of the source.</para> 33.1219 - 33.1220 - <para>Finally, you can apply your patches on top of the new 33.1221 - tree.</para> 33.1222 - 33.1223 - &interaction.mq.tarball.repush; 33.1224 - 33.1225 - </sect2> 33.1226 - <sect2 id="sec.mq.combine"> 33.1227 - <title>Combining entire patches</title> 33.1228 - 33.1229 - <para>MQ provides a command, <command 33.1230 - role="hg-ext-mq">qfold</command> that lets you combine 33.1231 - entire patches. This <quote>folds</quote> the patches you 33.1232 - name, in the order you name them, into the topmost applied 33.1233 - patch, and concatenates their descriptions onto the end of its 33.1234 - description. The patches that you fold must be unapplied 33.1235 - before you fold them.</para> 33.1236 - 33.1237 - <para>The order in which you fold patches matters. If your 33.1238 - topmost applied patch is <literal>foo</literal>, and you 33.1239 - <command role="hg-ext-mq">qfold</command> 33.1240 - <literal>bar</literal> and <literal>quux</literal> into it, 33.1241 - you will end up with a patch that has the same effect as if 33.1242 - you applied first <literal>foo</literal>, then 33.1243 - <literal>bar</literal>, followed by 33.1244 - <literal>quux</literal>.</para> 33.1245 - 33.1246 - </sect2> 33.1247 - <sect2> 33.1248 - <title>Merging part of one patch into another</title> 33.1249 - 33.1250 - <para>Merging <emphasis>part</emphasis> of one patch into 33.1251 - another is more difficult than combining entire 33.1252 - patches.</para> 33.1253 - 33.1254 - <para>If you want to move changes to entire files, you can use 33.1255 - <command>filterdiff</command>'s <option 33.1256 - role="cmd-opt-filterdiff">-i</option> and <option 33.1257 - role="cmd-opt-filterdiff">-x</option> options to choose the 33.1258 - modifications to snip out of one patch, concatenating its 33.1259 - output onto the end of the patch you want to merge into. You 33.1260 - usually won't need to modify the patch you've merged the 33.1261 - changes from. Instead, MQ will report some rejected hunks 33.1262 - when you <command role="hg-ext-mq">qpush</command> it (from 33.1263 - the hunks you moved into the other patch), and you can simply 33.1264 - <command role="hg-ext-mq">qrefresh</command> the patch to drop 33.1265 - the duplicate hunks.</para> 33.1266 - 33.1267 - <para>If you have a patch that has multiple hunks modifying a 33.1268 - file, and you only want to move a few of those hunks, the job 33.1269 - becomes more messy, but you can still partly automate it. Use 33.1270 - <command>lsdiff -nvv</command> to print some metadata about 33.1271 - the patch.</para> 33.1272 - 33.1273 - &interaction.mq.tools.lsdiff; 33.1274 - 33.1275 - <para>This command prints three different kinds of 33.1276 - number:</para> 33.1277 - <itemizedlist> 33.1278 - <listitem><para>(in the first column) a <emphasis>file 33.1279 - number</emphasis> to identify each file modified in the 33.1280 - patch;</para> 33.1281 - </listitem> 33.1282 - <listitem><para>(on the next line, indented) the line number 33.1283 - within a modified file where a hunk starts; and</para> 33.1284 - </listitem> 33.1285 - <listitem><para>(on the same line) a <emphasis>hunk 33.1286 - number</emphasis> to identify that hunk.</para> 33.1287 - </listitem></itemizedlist> 33.1288 - 33.1289 - <para>You'll have to use some visual inspection, and reading of 33.1290 - the patch, to identify the file and hunk numbers you'll want, 33.1291 - but you can then pass them to to 33.1292 - <command>filterdiff</command>'s <option 33.1293 - role="cmd-opt-filterdiff">--files</option> and <option 33.1294 - role="cmd-opt-filterdiff">--hunks</option> options, to 33.1295 - select exactly the file and hunk you want to extract.</para> 33.1296 - 33.1297 - <para>Once you have this hunk, you can concatenate it onto the 33.1298 - end of your destination patch and continue with the remainder 33.1299 - of section <xref linkend="sec.mq.combine"/>.</para> 33.1300 - 33.1301 - </sect2> 33.1302 - </sect1> 33.1303 - <sect1> 33.1304 - <title>Differences between quilt and MQ</title> 33.1305 - 33.1306 - <para>If you are already familiar with quilt, MQ provides a 33.1307 - similar command set. There are a few differences in the way 33.1308 - that it works.</para> 33.1309 - 33.1310 - <para>You will already have noticed that most quilt commands have 33.1311 - MQ counterparts that simply begin with a 33.1312 - <quote><literal>q</literal></quote>. The exceptions are quilt's 33.1313 - <literal>add</literal> and <literal>remove</literal> commands, 33.1314 - the counterparts for which are the normal Mercurial <command 33.1315 - role="hg-cmd">hg add</command> and <command role="hg-cmd">hg 33.1316 - remove</command> commands. There is no MQ equivalent of the 33.1317 - quilt <literal>edit</literal> command.</para> 33.1318 - 33.1319 - </sect1> 33.1320 -</chapter> 33.1321 - 33.1322 -<!-- 33.1323 -local variables: 33.1324 -sgml-parent-document: ("00book.xml" "book" "chapter") 33.1325 -end: 33.1326 --->
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/en/ch13-hgext.xml Fri Mar 20 16:43:35 2009 +0800 34.3 @@ -0,0 +1,554 @@ 34.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 34.5 + 34.6 +<chapter id="chap.hgext"> 34.7 + <?dbhtml filename="adding-functionality-with-extensions.html"?> 34.8 + <title>Adding functionality with extensions</title> 34.9 + 34.10 + <para>While the core of Mercurial is quite complete from a 34.11 + functionality standpoint, it's deliberately shorn of fancy 34.12 + features. This approach of preserving simplicity keeps the 34.13 + software easy to deal with for both maintainers and users.</para> 34.14 + 34.15 + <para>However, Mercurial doesn't box you in with an inflexible 34.16 + command set: you can add features to it as 34.17 + <emphasis>extensions</emphasis> (sometimes known as 34.18 + <emphasis>plugins</emphasis>). We've already discussed a few of 34.19 + these extensions in earlier chapters.</para> 34.20 + <itemizedlist> 34.21 + <listitem><para>Section <xref linkend="sec.tour-merge.fetch"/> 34.22 + covers the <literal role="hg-ext">fetch</literal> extension; 34.23 + this combines pulling new changes and merging them with local 34.24 + changes into a single command, <command 34.25 + role="hg-ext-fetch">fetch</command>.</para> 34.26 + </listitem> 34.27 + <listitem><para>In chapter <xref linkend="chap.hook"/>, we covered 34.28 + several extensions that are useful for hook-related 34.29 + functionality: <literal role="hg-ext">acl</literal> adds 34.30 + access control lists; <literal 34.31 + role="hg-ext">bugzilla</literal> adds integration with the 34.32 + Bugzilla bug tracking system; and <literal 34.33 + role="hg-ext">notify</literal> sends notification emails on 34.34 + new changes.</para> 34.35 + </listitem> 34.36 + <listitem><para>The Mercurial Queues patch management extension is 34.37 + so invaluable that it merits two chapters and an appendix all 34.38 + to itself. Chapter <xref linkend="chap.mq"/> covers the 34.39 + basics; chapter <xref 34.40 + linkend="chap.mq-collab"/> discusses advanced topics; 34.41 + and appendix <xref linkend="chap.mqref"/> goes into detail on 34.42 + each 34.43 + command.</para> 34.44 + </listitem></itemizedlist> 34.45 + 34.46 + <para>In this chapter, we'll cover some of the other extensions that 34.47 + are available for Mercurial, and briefly touch on some of the 34.48 + machinery you'll need to know about if you want to write an 34.49 + extension of your own.</para> 34.50 + <itemizedlist> 34.51 + <listitem><para>In section <xref linkend="sec.hgext.inotify"/>, 34.52 + we'll discuss the possibility of <emphasis>huge</emphasis> 34.53 + performance improvements using the <literal 34.54 + role="hg-ext">inotify</literal> extension.</para> 34.55 + </listitem></itemizedlist> 34.56 + 34.57 + <sect1 id="sec.hgext.inotify"> 34.58 + <title>Improve performance with the <literal 34.59 + role="hg-ext">inotify</literal> extension</title> 34.60 + 34.61 + <para>Are you interested in having some of the most common 34.62 + Mercurial operations run as much as a hundred times faster? 34.63 + Read on!</para> 34.64 + 34.65 + <para>Mercurial has great performance under normal circumstances. 34.66 + For example, when you run the <command role="hg-cmd">hg 34.67 + status</command> command, Mercurial has to scan almost every 34.68 + directory and file in your repository so that it can display 34.69 + file status. Many other Mercurial commands need to do the same 34.70 + work behind the scenes; for example, the <command 34.71 + role="hg-cmd">hg diff</command> command uses the status 34.72 + machinery to avoid doing an expensive comparison operation on 34.73 + files that obviously haven't changed.</para> 34.74 + 34.75 + <para>Because obtaining file status is crucial to good 34.76 + performance, the authors of Mercurial have optimised this code 34.77 + to within an inch of its life. However, there's no avoiding the 34.78 + fact that when you run <command role="hg-cmd">hg 34.79 + status</command>, Mercurial is going to have to perform at 34.80 + least one expensive system call for each managed file to 34.81 + determine whether it's changed since the last time Mercurial 34.82 + checked. For a sufficiently large repository, this can take a 34.83 + long time.</para> 34.84 + 34.85 + <para>To put a number on the magnitude of this effect, I created a 34.86 + repository containing 150,000 managed files. I timed <command 34.87 + role="hg-cmd">hg status</command> as taking ten seconds to 34.88 + run, even when <emphasis>none</emphasis> of those files had been 34.89 + modified.</para> 34.90 + 34.91 + <para>Many modern operating systems contain a file notification 34.92 + facility. If a program signs up to an appropriate service, the 34.93 + operating system will notify it every time a file of interest is 34.94 + created, modified, or deleted. On Linux systems, the kernel 34.95 + component that does this is called 34.96 + <literal>inotify</literal>.</para> 34.97 + 34.98 + <para>Mercurial's <literal role="hg-ext">inotify</literal> 34.99 + extension talks to the kernel's <literal>inotify</literal> 34.100 + component to optimise <command role="hg-cmd">hg status</command> 34.101 + commands. The extension has two components. A daemon sits in 34.102 + the background and receives notifications from the 34.103 + <literal>inotify</literal> subsystem. It also listens for 34.104 + connections from a regular Mercurial command. The extension 34.105 + modifies Mercurial's behaviour so that instead of scanning the 34.106 + filesystem, it queries the daemon. Since the daemon has perfect 34.107 + information about the state of the repository, it can respond 34.108 + with a result instantaneously, avoiding the need to scan every 34.109 + directory and file in the repository.</para> 34.110 + 34.111 + <para>Recall the ten seconds that I measured plain Mercurial as 34.112 + taking to run <command role="hg-cmd">hg status</command> on a 34.113 + 150,000 file repository. With the <literal 34.114 + role="hg-ext">inotify</literal> extension enabled, the time 34.115 + dropped to 0.1 seconds, a factor of <emphasis>one 34.116 + hundred</emphasis> faster.</para> 34.117 + 34.118 + <para>Before we continue, please pay attention to some 34.119 + caveats.</para> 34.120 + <itemizedlist> 34.121 + <listitem><para>The <literal role="hg-ext">inotify</literal> 34.122 + extension is Linux-specific. Because it interfaces directly 34.123 + to the Linux kernel's <literal>inotify</literal> subsystem, 34.124 + it does not work on other operating systems.</para> 34.125 + </listitem> 34.126 + <listitem><para>It should work on any Linux distribution that 34.127 + was released after early 2005. Older distributions are 34.128 + likely to have a kernel that lacks 34.129 + <literal>inotify</literal>, or a version of 34.130 + <literal>glibc</literal> that does not have the necessary 34.131 + interfacing support.</para> 34.132 + </listitem> 34.133 + <listitem><para>Not all filesystems are suitable for use with 34.134 + the <literal role="hg-ext">inotify</literal> extension. 34.135 + Network filesystems such as NFS are a non-starter, for 34.136 + example, particularly if you're running Mercurial on several 34.137 + systems, all mounting the same network filesystem. The 34.138 + kernel's <literal>inotify</literal> system has no way of 34.139 + knowing about changes made on another system. Most local 34.140 + filesystems (e.g. ext3, XFS, ReiserFS) should work 34.141 + fine.</para> 34.142 + </listitem></itemizedlist> 34.143 + 34.144 + <para>The <literal role="hg-ext">inotify</literal> extension is 34.145 + not yet shipped with Mercurial as of May 2007, so it's a little 34.146 + more involved to set up than other extensions. But the 34.147 + performance improvement is worth it!</para> 34.148 + 34.149 + <para>The extension currently comes in two parts: a set of patches 34.150 + to the Mercurial source code, and a library of Python bindings 34.151 + to the <literal>inotify</literal> subsystem.</para> 34.152 + <note> 34.153 + <para> There are <emphasis>two</emphasis> Python 34.154 + <literal>inotify</literal> binding libraries. One of them is 34.155 + called <literal>pyinotify</literal>, and is packaged by some 34.156 + Linux distributions as <literal>python-inotify</literal>. 34.157 + This is <emphasis>not</emphasis> the one you'll need, as it is 34.158 + too buggy and inefficient to be practical.</para> 34.159 + </note> 34.160 + <para>To get going, it's best to already have a functioning copy 34.161 + of Mercurial installed.</para> 34.162 + <note> 34.163 + <para> If you follow the instructions below, you'll be 34.164 + <emphasis>replacing</emphasis> and overwriting any existing 34.165 + installation of Mercurial that you might already have, using 34.166 + the latest <quote>bleeding edge</quote> Mercurial code. Don't 34.167 + say you weren't warned!</para> 34.168 + </note> 34.169 + <orderedlist> 34.170 + <listitem><para>Clone the Python <literal>inotify</literal> 34.171 + binding repository. Build and install it.</para> 34.172 + <programlisting>hg clone http://hg.kublai.com/python/inotify 34.173 +cd inotify 34.174 +python setup.py build --force 34.175 +sudo python setup.py install --skip-build</programlisting> 34.176 + </listitem> 34.177 + <listitem><para>Clone the <filename 34.178 + class="directory">crew</filename> Mercurial repository. 34.179 + Clone the <literal role="hg-ext">inotify</literal> patch 34.180 + repository so that Mercurial Queues will be able to apply 34.181 + patches to your cope of the <filename 34.182 + class="directory">crew</filename> repository.</para> 34.183 + <programlisting>hg clone http://hg.intevation.org/mercurial/crew 34.184 +hg clone crew inotify 34.185 +hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting> 34.186 + </listitem> 34.187 + <listitem><para>Make sure that you have the Mercurial Queues 34.188 + extension, <literal role="hg-ext">mq</literal>, enabled. If 34.189 + you've never used MQ, read section <xref 34.190 + linkend="sec.mq.start"/> to get started 34.191 + quickly.</para> 34.192 + </listitem> 34.193 + <listitem><para>Go into the <filename 34.194 + class="directory">inotify</filename> repo, and apply all 34.195 + of the <literal role="hg-ext">inotify</literal> patches 34.196 + using the <option role="hg-ext-mq-cmd-qpush-opt">hg 34.197 + -a</option> option to the <command 34.198 + role="hg-ext-mq">qpush</command> command.</para> 34.199 + <programlisting>cd inotify 34.200 +hg qpush -a</programlisting> 34.201 + </listitem> 34.202 + <listitem><para> If you get an error message from <command 34.203 + role="hg-ext-mq">qpush</command>, you should not continue. 34.204 + Instead, ask for help.</para> 34.205 + </listitem> 34.206 + <listitem><para>Build and install the patched version of 34.207 + Mercurial.</para> 34.208 + <programlisting>python setup.py build --force 34.209 +sudo python setup.py install --skip-build</programlisting> 34.210 + </listitem> 34.211 + </orderedlist> 34.212 + <para>Once you've build a suitably patched version of Mercurial, 34.213 + all you need to do to enable the <literal 34.214 + role="hg-ext">inotify</literal> extension is add an entry to 34.215 + your <filename role="special">~/.hgrc</filename>.</para> 34.216 + <programlisting>[extensions] inotify =</programlisting> 34.217 + <para>When the <literal role="hg-ext">inotify</literal> extension 34.218 + is enabled, Mercurial will automatically and transparently start 34.219 + the status daemon the first time you run a command that needs 34.220 + status in a repository. It runs one status daemon per 34.221 + repository.</para> 34.222 + 34.223 + <para>The status daemon is started silently, and runs in the 34.224 + background. If you look at a list of running processes after 34.225 + you've enabled the <literal role="hg-ext">inotify</literal> 34.226 + extension and run a few commands in different repositories, 34.227 + you'll thus see a few <literal>hg</literal> processes sitting 34.228 + around, waiting for updates from the kernel and queries from 34.229 + Mercurial.</para> 34.230 + 34.231 + <para>The first time you run a Mercurial command in a repository 34.232 + when you have the <literal role="hg-ext">inotify</literal> 34.233 + extension enabled, it will run with about the same performance 34.234 + as a normal Mercurial command. This is because the status 34.235 + daemon needs to perform a normal status scan so that it has a 34.236 + baseline against which to apply later updates from the kernel. 34.237 + However, <emphasis>every</emphasis> subsequent command that does 34.238 + any kind of status check should be noticeably faster on 34.239 + repositories of even fairly modest size. Better yet, the bigger 34.240 + your repository is, the greater a performance advantage you'll 34.241 + see. The <literal role="hg-ext">inotify</literal> daemon makes 34.242 + status operations almost instantaneous on repositories of all 34.243 + sizes!</para> 34.244 + 34.245 + <para>If you like, you can manually start a status daemon using 34.246 + the <command role="hg-ext-inotify">inserve</command> command. 34.247 + This gives you slightly finer control over how the daemon ought 34.248 + to run. This command will of course only be available when the 34.249 + <literal role="hg-ext">inotify</literal> extension is 34.250 + enabled.</para> 34.251 + 34.252 + <para>When you're using the <literal 34.253 + role="hg-ext">inotify</literal> extension, you should notice 34.254 + <emphasis>no difference at all</emphasis> in Mercurial's 34.255 + behaviour, with the sole exception of status-related commands 34.256 + running a whole lot faster than they used to. You should 34.257 + specifically expect that commands will not print different 34.258 + output; neither should they give different results. If either of 34.259 + these situations occurs, please report a bug.</para> 34.260 + 34.261 + </sect1> 34.262 + <sect1 id="sec.hgext.extdiff"> 34.263 + <title>Flexible diff support with the <literal 34.264 + role="hg-ext">extdiff</literal> extension</title> 34.265 + 34.266 + <para>Mercurial's built-in <command role="hg-cmd">hg 34.267 + diff</command> command outputs plaintext unified diffs.</para> 34.268 + 34.269 + &interaction.extdiff.diff; 34.270 + 34.271 + <para>If you would like to use an external tool to display 34.272 + modifications, you'll want to use the <literal 34.273 + role="hg-ext">extdiff</literal> extension. This will let you 34.274 + use, for example, a graphical diff tool.</para> 34.275 + 34.276 + <para>The <literal role="hg-ext">extdiff</literal> extension is 34.277 + bundled with Mercurial, so it's easy to set up. In the <literal 34.278 + role="rc-extensions">extensions</literal> section of your 34.279 + <filename role="special">~/.hgrc</filename>, simply add a 34.280 + one-line entry to enable the extension.</para> 34.281 + <programlisting>[extensions] 34.282 +extdiff =</programlisting> 34.283 + <para>This introduces a command named <command 34.284 + role="hg-ext-extdiff">extdiff</command>, which by default uses 34.285 + your system's <command>diff</command> command to generate a 34.286 + unified diff in the same form as the built-in <command 34.287 + role="hg-cmd">hg diff</command> command.</para> 34.288 + 34.289 + &interaction.extdiff.extdiff; 34.290 + 34.291 + <para>The result won't be exactly the same as with the built-in 34.292 + <command role="hg-cmd">hg diff</command> variations, because the 34.293 + output of <command>diff</command> varies from one system to 34.294 + another, even when passed the same options.</para> 34.295 + 34.296 + <para>As the <quote><literal>making snapshot</literal></quote> 34.297 + lines of output above imply, the <command 34.298 + role="hg-ext-extdiff">extdiff</command> command works by 34.299 + creating two snapshots of your source tree. The first snapshot 34.300 + is of the source revision; the second, of the target revision or 34.301 + working directory. The <command 34.302 + role="hg-ext-extdiff">extdiff</command> command generates 34.303 + these snapshots in a temporary directory, passes the name of 34.304 + each directory to an external diff viewer, then deletes the 34.305 + temporary directory. For efficiency, it only snapshots the 34.306 + directories and files that have changed between the two 34.307 + revisions.</para> 34.308 + 34.309 + <para>Snapshot directory names have the same base name as your 34.310 + repository. If your repository path is <filename 34.311 + class="directory">/quux/bar/foo</filename>, then <filename 34.312 + class="directory">foo</filename> will be the name of each 34.313 + snapshot directory. Each snapshot directory name has its 34.314 + changeset ID appended, if appropriate. If a snapshot is of 34.315 + revision <literal>a631aca1083f</literal>, the directory will be 34.316 + named <filename class="directory">foo.a631aca1083f</filename>. 34.317 + A snapshot of the working directory won't have a changeset ID 34.318 + appended, so it would just be <filename 34.319 + class="directory">foo</filename> in this example. To see what 34.320 + this looks like in practice, look again at the <command 34.321 + role="hg-ext-extdiff">extdiff</command> example above. Notice 34.322 + that the diff has the snapshot directory names embedded in its 34.323 + header.</para> 34.324 + 34.325 + <para>The <command role="hg-ext-extdiff">extdiff</command> command 34.326 + accepts two important options. The <option 34.327 + role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option 34.328 + lets you choose a program to view differences with, instead of 34.329 + <command>diff</command>. With the <option 34.330 + role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option, 34.331 + you can change the options that <command 34.332 + role="hg-ext-extdiff">extdiff</command> passes to the program 34.333 + (by default, these options are 34.334 + <quote><literal>-Npru</literal></quote>, which only make sense 34.335 + if you're running <command>diff</command>). In other respects, 34.336 + the <command role="hg-ext-extdiff">extdiff</command> command 34.337 + acts similarly to the built-in <command role="hg-cmd">hg 34.338 + diff</command> command: you use the same option names, syntax, 34.339 + and arguments to specify the revisions you want, the files you 34.340 + want, and so on.</para> 34.341 + 34.342 + <para>As an example, here's how to run the normal system 34.343 + <command>diff</command> command, getting it to generate context 34.344 + diffs (using the <option role="cmd-opt-diff">-c</option> option) 34.345 + instead of unified diffs, and five lines of context instead of 34.346 + the default three (passing <literal>5</literal> as the argument 34.347 + to the <option role="cmd-opt-diff">-C</option> option).</para> 34.348 + 34.349 + &interaction.extdiff.extdiff-ctx; 34.350 + 34.351 + <para>Launching a visual diff tool is just as easy. Here's how to 34.352 + launch the <command>kdiff3</command> viewer.</para> 34.353 + <programlisting>hg extdiff -p kdiff3 -o</programlisting> 34.354 + 34.355 + <para>If your diff viewing command can't deal with directories, 34.356 + you can easily work around this with a little scripting. For an 34.357 + example of such scripting in action with the <literal 34.358 + role="hg-ext">mq</literal> extension and the 34.359 + <command>interdiff</command> command, see section <xref 34.360 + linkend="mq-collab.tips.interdiff"/>.</para> 34.361 + 34.362 + <sect2> 34.363 + <title>Defining command aliases</title> 34.364 + 34.365 + <para>It can be cumbersome to remember the options to both the 34.366 + <command role="hg-ext-extdiff">extdiff</command> command and 34.367 + the diff viewer you want to use, so the <literal 34.368 + role="hg-ext">extdiff</literal> extension lets you define 34.369 + <emphasis>new</emphasis> commands that will invoke your diff 34.370 + viewer with exactly the right options.</para> 34.371 + 34.372 + <para>All you need to do is edit your <filename 34.373 + role="special">~/.hgrc</filename>, and add a section named 34.374 + <literal role="rc-extdiff">extdiff</literal>. Inside this 34.375 + section, you can define multiple commands. Here's how to add 34.376 + a <literal>kdiff3</literal> command. Once you've defined 34.377 + this, you can type <quote><literal>hg kdiff3</literal></quote> 34.378 + and the <literal role="hg-ext">extdiff</literal> extension 34.379 + will run <command>kdiff3</command> for you.</para> 34.380 + <programlisting>[extdiff] 34.381 +cmd.kdiff3 =</programlisting> 34.382 + <para>If you leave the right hand side of the definition empty, 34.383 + as above, the <literal role="hg-ext">extdiff</literal> 34.384 + extension uses the name of the command you defined as the name 34.385 + of the external program to run. But these names don't have to 34.386 + be the same. Here, we define a command named 34.387 + <quote><literal>hg wibble</literal></quote>, which runs 34.388 + <command>kdiff3</command>.</para> 34.389 + <programlisting>[extdiff] 34.390 + cmd.wibble = kdiff3</programlisting> 34.391 + 34.392 + <para>You can also specify the default options that you want to 34.393 + invoke your diff viewing program with. The prefix to use is 34.394 + <quote><literal>opts.</literal></quote>, followed by the name 34.395 + of the command to which the options apply. This example 34.396 + defines a <quote><literal>hg vimdiff</literal></quote> command 34.397 + that runs the <command>vim</command> editor's 34.398 + <literal>DirDiff</literal> extension.</para> 34.399 + <programlisting>[extdiff] 34.400 + cmd.vimdiff = vim 34.401 +opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting> 34.402 + 34.403 + </sect2> 34.404 + </sect1> 34.405 + <sect1 id="sec.hgext.transplant"> 34.406 + <title>Cherrypicking changes with the <literal 34.407 + role="hg-ext">transplant</literal> extension</title> 34.408 + 34.409 + <para>Need to have a long chat with Brendan about this.</para> 34.410 + 34.411 + </sect1> 34.412 + <sect1 id="sec.hgext.patchbomb"> 34.413 + <title>Send changes via email with the <literal 34.414 + role="hg-ext">patchbomb</literal> extension</title> 34.415 + 34.416 + <para>Many projects have a culture of <quote>change 34.417 + review</quote>, in which people send their modifications to a 34.418 + mailing list for others to read and comment on before they 34.419 + commit the final version to a shared repository. Some projects 34.420 + have people who act as gatekeepers; they apply changes from 34.421 + other people to a repository to which those others don't have 34.422 + access.</para> 34.423 + 34.424 + <para>Mercurial makes it easy to send changes over email for 34.425 + review or application, via its <literal 34.426 + role="hg-ext">patchbomb</literal> extension. The extension is 34.427 + so named because changes are formatted as patches, and it's usual 34.428 + to send one changeset per email message. Sending a long series 34.429 + of changes by email is thus much like <quote>bombing</quote> the 34.430 + recipient's inbox, hence <quote>patchbomb</quote>.</para> 34.431 + 34.432 + <para>As usual, the basic configuration of the <literal 34.433 + role="hg-ext">patchbomb</literal> extension takes just one or 34.434 + two lines in your <filename role="special"> 34.435 + /.hgrc</filename>.</para> 34.436 + <programlisting>[extensions] 34.437 +patchbomb =</programlisting> 34.438 + <para>Once you've enabled the extension, you will have a new 34.439 + command available, named <command 34.440 + role="hg-ext-patchbomb">email</command>.</para> 34.441 + 34.442 + <para>The safest and best way to invoke the <command 34.443 + role="hg-ext-patchbomb">email</command> command is to 34.444 + <emphasis>always</emphasis> run it first with the <option 34.445 + role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option. 34.446 + This will show you what the command <emphasis>would</emphasis> 34.447 + send, without actually sending anything. Once you've had a 34.448 + quick glance over the changes and verified that you are sending 34.449 + the right ones, you can rerun the same command, with the <option 34.450 + role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option 34.451 + removed.</para> 34.452 + 34.453 + <para>The <command role="hg-ext-patchbomb">email</command> command 34.454 + accepts the same kind of revision syntax as every other 34.455 + Mercurial command. For example, this command will send every 34.456 + revision between 7 and <literal>tip</literal>, inclusive.</para> 34.457 + <programlisting>hg email -n 7:tip</programlisting> 34.458 + <para>You can also specify a <emphasis>repository</emphasis> to 34.459 + compare with. If you provide a repository but no revisions, the 34.460 + <command role="hg-ext-patchbomb">email</command> command will 34.461 + send all revisions in the local repository that are not present 34.462 + in the remote repository. If you additionally specify revisions 34.463 + or a branch name (the latter using the <option 34.464 + role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option), 34.465 + this will constrain the revisions sent.</para> 34.466 + 34.467 + <para>It's perfectly safe to run the <command 34.468 + role="hg-ext-patchbomb">email</command> command without the 34.469 + names of the people you want to send to: if you do this, it will 34.470 + just prompt you for those values interactively. (If you're 34.471 + using a Linux or Unix-like system, you should have enhanced 34.472 + <literal>readline</literal>-style editing capabilities when 34.473 + entering those headers, too, which is useful.)</para> 34.474 + 34.475 + <para>When you are sending just one revision, the <command 34.476 + role="hg-ext-patchbomb">email</command> command will by 34.477 + default use the first line of the changeset description as the 34.478 + subject of the single email message it sends.</para> 34.479 + 34.480 + <para>If you send multiple revisions, the <command 34.481 + role="hg-ext-patchbomb">email</command> command will usually 34.482 + send one message per changeset. It will preface the series with 34.483 + an introductory message, in which you should describe the 34.484 + purpose of the series of changes you're sending.</para> 34.485 + 34.486 + <sect2> 34.487 + <title>Changing the behaviour of patchbombs</title> 34.488 + 34.489 + <para>Not every project has exactly the same conventions for 34.490 + sending changes in email; the <literal 34.491 + role="hg-ext">patchbomb</literal> extension tries to 34.492 + accommodate a number of variations through command line 34.493 + options.</para> 34.494 + <itemizedlist> 34.495 + <listitem><para>You can write a subject for the introductory 34.496 + message on the command line using the <option 34.497 + role="hg-ext-patchbomb-cmd-email-opt">hg -s</option> 34.498 + option. This takes one argument, the text of the subject 34.499 + to use.</para> 34.500 + </listitem> 34.501 + <listitem><para>To change the email address from which the 34.502 + messages originate, use the <option 34.503 + role="hg-ext-patchbomb-cmd-email-opt">hg -f</option> 34.504 + option. This takes one argument, the email address to 34.505 + use.</para> 34.506 + </listitem> 34.507 + <listitem><para>The default behaviour is to send unified diffs 34.508 + (see section <xref linkend="sec.mq.patch"/> for a 34.509 + description of the 34.510 + format), one per message. You can send a binary bundle 34.511 + instead with the <option 34.512 + role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> 34.513 + option.</para> 34.514 + </listitem> 34.515 + <listitem><para>Unified diffs are normally prefaced with a 34.516 + metadata header. You can omit this, and send unadorned 34.517 + diffs, with the <option 34.518 + role="hg-ext-patchbomb-cmd-email-opt">hg 34.519 + --plain</option> option.</para> 34.520 + </listitem> 34.521 + <listitem><para>Diffs are normally sent <quote>inline</quote>, 34.522 + in the same body part as the description of a patch. This 34.523 + makes it easiest for the largest number of readers to 34.524 + quote and respond to parts of a diff, as some mail clients 34.525 + will only quote the first MIME body part in a message. If 34.526 + you'd prefer to send the description and the diff in 34.527 + separate body parts, use the <option 34.528 + role="hg-ext-patchbomb-cmd-email-opt">hg -a</option> 34.529 + option.</para> 34.530 + </listitem> 34.531 + <listitem><para>Instead of sending mail messages, you can 34.532 + write them to an <literal>mbox</literal>-format mail 34.533 + folder using the <option 34.534 + role="hg-ext-patchbomb-cmd-email-opt">hg -m</option> 34.535 + option. That option takes one argument, the name of the 34.536 + file to write to.</para> 34.537 + </listitem> 34.538 + <listitem><para>If you would like to add a 34.539 + <command>diffstat</command>-format summary to each patch, 34.540 + and one to the introductory message, use the <option 34.541 + role="hg-ext-patchbomb-cmd-email-opt">hg -d</option> 34.542 + option. The <command>diffstat</command> command displays 34.543 + a table containing the name of each file patched, the 34.544 + number of lines affected, and a histogram showing how much 34.545 + each file is modified. This gives readers a qualitative 34.546 + glance at how complex a patch is.</para> 34.547 + </listitem></itemizedlist> 34.548 + 34.549 + </sect2> 34.550 + </sect1> 34.551 +</chapter> 34.552 + 34.553 +<!-- 34.554 +local variables: 34.555 +sgml-parent-document: ("00book.xml" "book" "chapter") 34.556 +end: 34.557 +-->
35.1 --- a/en/ch13-mq-collab.xml Fri Mar 20 15:40:06 2009 +0800 35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 35.3 @@ -1,518 +0,0 @@ 35.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 35.5 - 35.6 -<chapter id="chap.mq-collab"> 35.7 - <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?> 35.8 - <title>Advanced uses of Mercurial Queues</title> 35.9 - 35.10 - <para>While it's easy to pick up straightforward uses of Mercurial 35.11 - Queues, use of a little discipline and some of MQ's less 35.12 - frequently used capabilities makes it possible to work in 35.13 - complicated development environments.</para> 35.14 - 35.15 - <para>In this chapter, I will use as an example a technique I have 35.16 - used to manage the development of an Infiniband device driver for 35.17 - the Linux kernel. The driver in question is large (at least as 35.18 - drivers go), with 25,000 lines of code spread across 35 source 35.19 - files. It is maintained by a small team of developers.</para> 35.20 - 35.21 - <para>While much of the material in this chapter is specific to 35.22 - Linux, the same principles apply to any code base for which you're 35.23 - not the primary owner, and upon which you need to do a lot of 35.24 - development.</para> 35.25 - 35.26 - <sect1> 35.27 - <title>The problem of many targets</title> 35.28 - 35.29 - <para>The Linux kernel changes rapidly, and has never been 35.30 - internally stable; developers frequently make drastic changes 35.31 - between releases. This means that a version of the driver that 35.32 - works well with a particular released version of the kernel will 35.33 - not even <emphasis>compile</emphasis> correctly against, 35.34 - typically, any other version.</para> 35.35 - 35.36 - <para>To maintain a driver, we have to keep a number of distinct 35.37 - versions of Linux in mind.</para> 35.38 - <itemizedlist> 35.39 - <listitem><para>One target is the main Linux kernel development 35.40 - tree. Maintenance of the code is in this case partly shared 35.41 - by other developers in the kernel community, who make 35.42 - <quote>drive-by</quote> modifications to the driver as they 35.43 - develop and refine kernel subsystems.</para> 35.44 - </listitem> 35.45 - <listitem><para>We also maintain a number of 35.46 - <quote>backports</quote> to older versions of the Linux 35.47 - kernel, to support the needs of customers who are running 35.48 - older Linux distributions that do not incorporate our 35.49 - drivers. (To <emphasis>backport</emphasis> a piece of code 35.50 - is to modify it to work in an older version of its target 35.51 - environment than the version it was developed for.)</para> 35.52 - </listitem> 35.53 - <listitem><para>Finally, we make software releases on a schedule 35.54 - that is necessarily not aligned with those used by Linux 35.55 - distributors and kernel developers, so that we can deliver 35.56 - new features to customers without forcing them to upgrade 35.57 - their entire kernels or distributions.</para> 35.58 - </listitem></itemizedlist> 35.59 - 35.60 - <sect2> 35.61 - <title>Tempting approaches that don't work well</title> 35.62 - 35.63 - <para>There are two <quote>standard</quote> ways to maintain a 35.64 - piece of software that has to target many different 35.65 - environments.</para> 35.66 - 35.67 - <para>The first is to maintain a number of branches, each 35.68 - intended for a single target. The trouble with this approach 35.69 - is that you must maintain iron discipline in the flow of 35.70 - changes between repositories. A new feature or bug fix must 35.71 - start life in a <quote>pristine</quote> repository, then 35.72 - percolate out to every backport repository. Backport changes 35.73 - are more limited in the branches they should propagate to; a 35.74 - backport change that is applied to a branch where it doesn't 35.75 - belong will probably stop the driver from compiling.</para> 35.76 - 35.77 - <para>The second is to maintain a single source tree filled with 35.78 - conditional statements that turn chunks of code on or off 35.79 - depending on the intended target. Because these 35.80 - <quote>ifdefs</quote> are not allowed in the Linux kernel 35.81 - tree, a manual or automatic process must be followed to strip 35.82 - them out and yield a clean tree. A code base maintained in 35.83 - this fashion rapidly becomes a rat's nest of conditional 35.84 - blocks that are difficult to understand and maintain.</para> 35.85 - 35.86 - <para>Neither of these approaches is well suited to a situation 35.87 - where you don't <quote>own</quote> the canonical copy of a 35.88 - source tree. In the case of a Linux driver that is 35.89 - distributed with the standard kernel, Linus's tree contains 35.90 - the copy of the code that will be treated by the world as 35.91 - canonical. The upstream version of <quote>my</quote> driver 35.92 - can be modified by people I don't know, without me even 35.93 - finding out about it until after the changes show up in 35.94 - Linus's tree.</para> 35.95 - 35.96 - <para>These approaches have the added weakness of making it 35.97 - difficult to generate well-formed patches to submit 35.98 - upstream.</para> 35.99 - 35.100 - <para>In principle, Mercurial Queues seems like a good candidate 35.101 - to manage a development scenario such as the above. While 35.102 - this is indeed the case, MQ contains a few added features that 35.103 - make the job more pleasant.</para> 35.104 - 35.105 - </sect2> 35.106 - </sect1> 35.107 - <sect1> 35.108 - <title>Conditionally applying patches with guards</title> 35.109 - 35.110 - <para>Perhaps the best way to maintain sanity with so many targets 35.111 - is to be able to choose specific patches to apply for a given 35.112 - situation. MQ provides a feature called <quote>guards</quote> 35.113 - (which originates with quilt's <literal>guards</literal> 35.114 - command) that does just this. To start off, let's create a 35.115 - simple repository for experimenting in.</para> 35.116 - 35.117 - &interaction.mq.guards.init; 35.118 - 35.119 - <para>This gives us a tiny repository that contains two patches 35.120 - that don't have any dependencies on each other, because they 35.121 - touch different files.</para> 35.122 - 35.123 - <para>The idea behind conditional application is that you can 35.124 - <quote>tag</quote> a patch with a <emphasis>guard</emphasis>, 35.125 - which is simply a text string of your choosing, then tell MQ to 35.126 - select specific guards to use when applying patches. MQ will 35.127 - then either apply, or skip over, a guarded patch, depending on 35.128 - the guards that you have selected.</para> 35.129 - 35.130 - <para>A patch can have an arbitrary number of guards; each one is 35.131 - <emphasis>positive</emphasis> (<quote>apply this patch if this 35.132 - guard is selected</quote>) or <emphasis>negative</emphasis> 35.133 - (<quote>skip this patch if this guard is selected</quote>). A 35.134 - patch with no guards is always applied.</para> 35.135 - 35.136 - </sect1> 35.137 - <sect1> 35.138 - <title>Controlling the guards on a patch</title> 35.139 - 35.140 - <para>The <command role="hg-ext-mq">qguard</command> command lets 35.141 - you determine which guards should apply to a patch, or display 35.142 - the guards that are already in effect. Without any arguments, it 35.143 - displays the guards on the current topmost patch.</para> 35.144 - 35.145 - &interaction.mq.guards.qguard; 35.146 - 35.147 - <para>To set a positive guard on a patch, prefix the name of the 35.148 - guard with a <quote><literal>+</literal></quote>.</para> 35.149 - 35.150 - &interaction.mq.guards.qguard.pos; 35.151 - 35.152 - <para>To set a negative guard 35.153 - on a patch, prefix the name of the guard with a 35.154 - <quote><literal>-</literal></quote>.</para> 35.155 - 35.156 - &interaction.mq.guards.qguard.neg; 35.157 - 35.158 - <note> 35.159 - <para> The <command role="hg-ext-mq">qguard</command> command 35.160 - <emphasis>sets</emphasis> the guards on a patch; it doesn't 35.161 - <emphasis>modify</emphasis> them. What this means is that if 35.162 - you run <command role="hg-cmd">hg qguard +a +b</command> on a 35.163 - patch, then <command role="hg-cmd">hg qguard +c</command> on 35.164 - the same patch, the <emphasis>only</emphasis> guard that will 35.165 - be set on it afterwards is <literal>+c</literal>.</para> 35.166 - </note> 35.167 - 35.168 - <para>Mercurial stores guards in the <filename 35.169 - role="special">series</filename> file; the form in which they 35.170 - are stored is easy both to understand and to edit by hand. (In 35.171 - other words, you don't have to use the <command 35.172 - role="hg-ext-mq">qguard</command> command if you don't want 35.173 - to; it's okay to simply edit the <filename 35.174 - role="special">series</filename> file.)</para> 35.175 - 35.176 - &interaction.mq.guards.series; 35.177 - 35.178 - </sect1> 35.179 - <sect1> 35.180 - <title>Selecting the guards to use</title> 35.181 - 35.182 - <para>The <command role="hg-ext-mq">qselect</command> command 35.183 - determines which guards are active at a given time. The effect 35.184 - of this is to determine which patches MQ will apply the next 35.185 - time you run <command role="hg-ext-mq">qpush</command>. It has 35.186 - no other effect; in particular, it doesn't do anything to 35.187 - patches that are already applied.</para> 35.188 - 35.189 - <para>With no arguments, the <command 35.190 - role="hg-ext-mq">qselect</command> command lists the guards 35.191 - currently in effect, one per line of output. Each argument is 35.192 - treated as the name of a guard to apply.</para> 35.193 - 35.194 - &interaction.mq.guards.qselect.foo; 35.195 - 35.196 - <para>In case you're interested, the currently selected guards are 35.197 - stored in the <filename role="special">guards</filename> file.</para> 35.198 - 35.199 - &interaction.mq.guards.qselect.cat; 35.200 - 35.201 - <para>We can see the effect the selected guards have when we run 35.202 - <command role="hg-ext-mq">qpush</command>.</para> 35.203 - 35.204 - &interaction.mq.guards.qselect.qpush; 35.205 - 35.206 - <para>A guard cannot start with a 35.207 - <quote><literal>+</literal></quote> or 35.208 - <quote><literal>-</literal></quote> character. The name of a 35.209 - guard must not contain white space, but most other characters 35.210 - are acceptable. If you try to use a guard with an invalid name, 35.211 - MQ will complain:</para> 35.212 - 35.213 - &interaction.mq.guards.qselect.error; 35.214 - 35.215 - <para>Changing the selected guards changes the patches that are 35.216 - applied.</para> 35.217 - 35.218 - &interaction.mq.guards.qselect.quux; 35.219 - 35.220 - <para>You can see in the example below that negative guards take 35.221 - precedence over positive guards.</para> 35.222 - 35.223 - &interaction.mq.guards.qselect.foobar; 35.224 - 35.225 - </sect1> 35.226 - <sect1> 35.227 - <title>MQ's rules for applying patches</title> 35.228 - 35.229 - <para>The rules that MQ uses when deciding whether to apply a 35.230 - patch are as follows.</para> 35.231 - <itemizedlist> 35.232 - <listitem><para>A patch that has no guards is always 35.233 - applied.</para> 35.234 - </listitem> 35.235 - <listitem><para>If the patch has any negative guard that matches 35.236 - any currently selected guard, the patch is skipped.</para> 35.237 - </listitem> 35.238 - <listitem><para>If the patch has any positive guard that matches 35.239 - any currently selected guard, the patch is applied.</para> 35.240 - </listitem> 35.241 - <listitem><para>If the patch has positive or negative guards, 35.242 - but none matches any currently selected guard, the patch is 35.243 - skipped.</para> 35.244 - </listitem></itemizedlist> 35.245 - 35.246 - </sect1> 35.247 - <sect1> 35.248 - <title>Trimming the work environment</title> 35.249 - 35.250 - <para>In working on the device driver I mentioned earlier, I don't 35.251 - apply the patches to a normal Linux kernel tree. Instead, I use 35.252 - a repository that contains only a snapshot of the source files 35.253 - and headers that are relevant to Infiniband development. This 35.254 - repository is 1% the size of a kernel repository, so it's easier 35.255 - to work with.</para> 35.256 - 35.257 - <para>I then choose a <quote>base</quote> version on top of which 35.258 - the patches are applied. This is a snapshot of the Linux kernel 35.259 - tree as of a revision of my choosing. When I take the snapshot, 35.260 - I record the changeset ID from the kernel repository in the 35.261 - commit message. Since the snapshot preserves the 35.262 - <quote>shape</quote> and content of the relevant parts of the 35.263 - kernel tree, I can apply my patches on top of either my tiny 35.264 - repository or a normal kernel tree.</para> 35.265 - 35.266 - <para>Normally, the base tree atop which the patches apply should 35.267 - be a snapshot of a very recent upstream tree. This best 35.268 - facilitates the development of patches that can easily be 35.269 - submitted upstream with few or no modifications.</para> 35.270 - 35.271 - </sect1> 35.272 - <sect1> 35.273 - <title>Dividing up the <filename role="special">series</filename> 35.274 - file</title> 35.275 - 35.276 - <para>I categorise the patches in the <filename 35.277 - role="special">series</filename> file into a number of logical 35.278 - groups. Each section of like patches begins with a block of 35.279 - comments that describes the purpose of the patches that 35.280 - follow.</para> 35.281 - 35.282 - <para>The sequence of patch groups that I maintain follows. The 35.283 - ordering of these groups is important; I'll describe why after I 35.284 - introduce the groups.</para> 35.285 - <itemizedlist> 35.286 - <listitem><para>The <quote>accepted</quote> group. Patches that 35.287 - the development team has submitted to the maintainer of the 35.288 - Infiniband subsystem, and which he has accepted, but which 35.289 - are not present in the snapshot that the tiny repository is 35.290 - based on. These are <quote>read only</quote> patches, 35.291 - present only to transform the tree into a similar state as 35.292 - it is in the upstream maintainer's repository.</para> 35.293 - </listitem> 35.294 - <listitem><para>The <quote>rework</quote> group. Patches that I 35.295 - have submitted, but that the upstream maintainer has 35.296 - requested modifications to before he will accept 35.297 - them.</para> 35.298 - </listitem> 35.299 - <listitem><para>The <quote>pending</quote> group. Patches that 35.300 - I have not yet submitted to the upstream maintainer, but 35.301 - which we have finished working on. These will be <quote>read 35.302 - only</quote> for a while. If the upstream maintainer 35.303 - accepts them upon submission, I'll move them to the end of 35.304 - the <quote>accepted</quote> group. If he requests that I 35.305 - modify any, I'll move them to the beginning of the 35.306 - <quote>rework</quote> group.</para> 35.307 - </listitem> 35.308 - <listitem><para>The <quote>in progress</quote> group. Patches 35.309 - that are actively being developed, and should not be 35.310 - submitted anywhere yet.</para> 35.311 - </listitem> 35.312 - <listitem><para>The <quote>backport</quote> group. Patches that 35.313 - adapt the source tree to older versions of the kernel 35.314 - tree.</para> 35.315 - </listitem> 35.316 - <listitem><para>The <quote>do not ship</quote> group. Patches 35.317 - that for some reason should never be submitted upstream. 35.318 - For example, one such patch might change embedded driver 35.319 - identification strings to make it easier to distinguish, in 35.320 - the field, between an out-of-tree version of the driver and 35.321 - a version shipped by a distribution vendor.</para> 35.322 - </listitem></itemizedlist> 35.323 - 35.324 - <para>Now to return to the reasons for ordering groups of patches 35.325 - in this way. We would like the lowest patches in the stack to 35.326 - be as stable as possible, so that we will not need to rework 35.327 - higher patches due to changes in context. Putting patches that 35.328 - will never be changed first in the <filename 35.329 - role="special">series</filename> file serves this 35.330 - purpose.</para> 35.331 - 35.332 - <para>We would also like the patches that we know we'll need to 35.333 - modify to be applied on top of a source tree that resembles the 35.334 - upstream tree as closely as possible. This is why we keep 35.335 - accepted patches around for a while.</para> 35.336 - 35.337 - <para>The <quote>backport</quote> and <quote>do not ship</quote> 35.338 - patches float at the end of the <filename 35.339 - role="special">series</filename> file. The backport patches 35.340 - must be applied on top of all other patches, and the <quote>do 35.341 - not ship</quote> patches might as well stay out of harm's 35.342 - way.</para> 35.343 - 35.344 - </sect1> 35.345 - <sect1> 35.346 - <title>Maintaining the patch series</title> 35.347 - 35.348 - <para>In my work, I use a number of guards to control which 35.349 - patches are to be applied.</para> 35.350 - 35.351 - <itemizedlist> 35.352 - <listitem><para><quote>Accepted</quote> patches are guarded with 35.353 - <literal>accepted</literal>. I enable this guard most of 35.354 - the time. When I'm applying the patches on top of a tree 35.355 - where the patches are already present, I can turn this patch 35.356 - off, and the patches that follow it will apply 35.357 - cleanly.</para> 35.358 - </listitem> 35.359 - <listitem><para>Patches that are <quote>finished</quote>, but 35.360 - not yet submitted, have no guards. If I'm applying the 35.361 - patch stack to a copy of the upstream tree, I don't need to 35.362 - enable any guards in order to get a reasonably safe source 35.363 - tree.</para> 35.364 - </listitem> 35.365 - <listitem><para>Those patches that need reworking before being 35.366 - resubmitted are guarded with 35.367 - <literal>rework</literal>.</para> 35.368 - </listitem> 35.369 - <listitem><para>For those patches that are still under 35.370 - development, I use <literal>devel</literal>.</para> 35.371 - </listitem> 35.372 - <listitem><para>A backport patch may have several guards, one 35.373 - for each version of the kernel to which it applies. For 35.374 - example, a patch that backports a piece of code to 2.6.9 35.375 - will have a <literal>2.6.9</literal> guard.</para> 35.376 - </listitem></itemizedlist> 35.377 - <para>This variety of guards gives me considerable flexibility in 35.378 - determining what kind of source tree I want to end up with. For 35.379 - most situations, the selection of appropriate guards is 35.380 - automated during the build process, but I can manually tune the 35.381 - guards to use for less common circumstances.</para> 35.382 - 35.383 - <sect2> 35.384 - <title>The art of writing backport patches</title> 35.385 - 35.386 - <para>Using MQ, writing a backport patch is a simple process. 35.387 - All such a patch has to do is modify a piece of code that uses 35.388 - a kernel feature not present in the older version of the 35.389 - kernel, so that the driver continues to work correctly under 35.390 - that older version.</para> 35.391 - 35.392 - <para>A useful goal when writing a good backport patch is to 35.393 - make your code look as if it was written for the older version 35.394 - of the kernel you're targeting. The less obtrusive the patch, 35.395 - the easier it will be to understand and maintain. If you're 35.396 - writing a collection of backport patches to avoid the 35.397 - <quote>rat's nest</quote> effect of lots of 35.398 - <literal>#ifdef</literal>s (hunks of source code that are only 35.399 - used conditionally) in your code, don't introduce 35.400 - version-dependent <literal>#ifdef</literal>s into the patches. 35.401 - Instead, write several patches, each of which makes 35.402 - unconditional changes, and control their application using 35.403 - guards.</para> 35.404 - 35.405 - <para>There are two reasons to divide backport patches into a 35.406 - distinct group, away from the <quote>regular</quote> patches 35.407 - whose effects they modify. The first is that intermingling the 35.408 - two makes it more difficult to use a tool like the <literal 35.409 - role="hg-ext">patchbomb</literal> extension to automate the 35.410 - process of submitting the patches to an upstream maintainer. 35.411 - The second is that a backport patch could perturb the context 35.412 - in which a subsequent regular patch is applied, making it 35.413 - impossible to apply the regular patch cleanly 35.414 - <emphasis>without</emphasis> the earlier backport patch 35.415 - already being applied.</para> 35.416 - 35.417 - </sect2> 35.418 - </sect1> 35.419 - <sect1> 35.420 - <title>Useful tips for developing with MQ</title> 35.421 - 35.422 - <sect2> 35.423 - <title>Organising patches in directories</title> 35.424 - 35.425 - <para>If you're working on a substantial project with MQ, it's 35.426 - not difficult to accumulate a large number of patches. For 35.427 - example, I have one patch repository that contains over 250 35.428 - patches.</para> 35.429 - 35.430 - <para>If you can group these patches into separate logical 35.431 - categories, you can if you like store them in different 35.432 - directories; MQ has no problems with patch names that contain 35.433 - path separators.</para> 35.434 - 35.435 - </sect2> 35.436 - <sect2 id="mq-collab.tips.interdiff"> 35.437 - <title>Viewing the history of a patch</title> 35.438 - 35.439 - <para>If you're developing a set of patches over a long time, 35.440 - it's a good idea to maintain them in a repository, as 35.441 - discussed in section <xref linkend="sec.mq.repo"/>. If you do 35.442 - so, you'll quickly 35.443 - discover that using the <command role="hg-cmd">hg 35.444 - diff</command> command to look at the history of changes to 35.445 - a patch is unworkable. This is in part because you're looking 35.446 - at the second derivative of the real code (a diff of a diff), 35.447 - but also because MQ adds noise to the process by modifying 35.448 - time stamps and directory names when it updates a 35.449 - patch.</para> 35.450 - 35.451 - <para>However, you can use the <literal 35.452 - role="hg-ext">extdiff</literal> extension, which is bundled 35.453 - with Mercurial, to turn a diff of two versions of a patch into 35.454 - something readable. To do this, you will need a third-party 35.455 - package called <literal role="package">patchutils</literal> 35.456 - <citation>web:patchutils</citation>. This provides a command 35.457 - named <command>interdiff</command>, which shows the 35.458 - differences between two diffs as a diff. Used on two versions 35.459 - of the same diff, it generates a diff that represents the diff 35.460 - from the first to the second version.</para> 35.461 - 35.462 - <para>You can enable the <literal 35.463 - role="hg-ext">extdiff</literal> extension in the usual way, 35.464 - by adding a line to the <literal 35.465 - role="rc-extensions">extensions</literal> section of your 35.466 - <filename role="special">~/.hgrc</filename>.</para> 35.467 - <programlisting>[extensions] 35.468 -extdiff =</programlisting> 35.469 - <para>The <command>interdiff</command> command expects to be 35.470 - passed the names of two files, but the <literal 35.471 - role="hg-ext">extdiff</literal> extension passes the program 35.472 - it runs a pair of directories, each of which can contain an 35.473 - arbitrary number of files. We thus need a small program that 35.474 - will run <command>interdiff</command> on each pair of files in 35.475 - these two directories. This program is available as <filename 35.476 - role="special">hg-interdiff</filename> in the <filename 35.477 - class="directory">examples</filename> directory of the 35.478 - source code repository that accompanies this book. <!-- 35.479 - &example.hg-interdiff; --></para> 35.480 - 35.481 - <para>With the <filename role="special">hg-interdiff</filename> 35.482 - program in your shell's search path, you can run it as 35.483 - follows, from inside an MQ patch directory:</para> 35.484 - <programlisting>hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting> 35.485 - <para>Since you'll probably want to use this long-winded command 35.486 - a lot, you can get <literal role="hg-ext">hgext</literal> to 35.487 - make it available as a normal Mercurial command, again by 35.488 - editing your <filename 35.489 - role="special">~/.hgrc</filename>.</para> 35.490 - <programlisting>[extdiff] 35.491 -cmd.interdiff = hg-interdiff</programlisting> 35.492 - <para>This directs <literal role="hg-ext">hgext</literal> to 35.493 - make an <literal>interdiff</literal> command available, so you 35.494 - can now shorten the previous invocation of <command 35.495 - role="hg-ext-extdiff">extdiff</command> to something a 35.496 - little more wieldy.</para> 35.497 - <programlisting>hg interdiff -r A:B my-change.patch</programlisting> 35.498 - 35.499 - <note> 35.500 - <para> The <command>interdiff</command> command works well 35.501 - only if the underlying files against which versions of a 35.502 - patch are generated remain the same. If you create a patch, 35.503 - modify the underlying files, and then regenerate the patch, 35.504 - <command>interdiff</command> may not produce useful 35.505 - output.</para> 35.506 - </note> 35.507 - 35.508 - <para>The <literal role="hg-ext">extdiff</literal> extension is 35.509 - useful for more than merely improving the presentation of MQ 35.510 - patches. To read more about it, go to section <xref 35.511 - linkend="sec.hgext.extdiff"/>.</para> 35.512 - 35.513 - </sect2> 35.514 - </sect1> 35.515 -</chapter> 35.516 - 35.517 -<!-- 35.518 -local variables: 35.519 -sgml-parent-document: ("00book.xml" "book" "chapter") 35.520 -end: 35.521 --->
36.1 --- a/en/ch14-hgext.xml Fri Mar 20 15:40:06 2009 +0800 36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 36.3 @@ -1,554 +0,0 @@ 36.4 -<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 36.5 - 36.6 -<chapter id="chap.hgext"> 36.7 - <?dbhtml filename="adding-functionality-with-extensions.html"?> 36.8 - <title>Adding functionality with extensions</title> 36.9 - 36.10 - <para>While the core of Mercurial is quite complete from a 36.11 - functionality standpoint, it's deliberately shorn of fancy 36.12 - features. This approach of preserving simplicity keeps the 36.13 - software easy to deal with for both maintainers and users.</para> 36.14 - 36.15 - <para>However, Mercurial doesn't box you in with an inflexible 36.16 - command set: you can add features to it as 36.17 - <emphasis>extensions</emphasis> (sometimes known as 36.18 - <emphasis>plugins</emphasis>). We've already discussed a few of 36.19 - these extensions in earlier chapters.</para> 36.20 - <itemizedlist> 36.21 - <listitem><para>Section <xref linkend="sec.tour-merge.fetch"/> 36.22 - covers the <literal role="hg-ext">fetch</literal> extension; 36.23 - this combines pulling new changes and merging them with local 36.24 - changes into a single command, <command 36.25 - role="hg-ext-fetch">fetch</command>.</para> 36.26 - </listitem> 36.27 - <listitem><para>In chapter <xref linkend="chap.hook"/>, we covered 36.28 - several extensions that are useful for hook-related 36.29 - functionality: <literal role="hg-ext">acl</literal> adds 36.30 - access control lists; <literal 36.31 - role="hg-ext">bugzilla</literal> adds integration with the 36.32 - Bugzilla bug tracking system; and <literal 36.33 - role="hg-ext">notify</literal> sends notification emails on 36.34 - new changes.</para> 36.35 - </listitem> 36.36 - <listitem><para>The Mercurial Queues patch management extension is 36.37 - so invaluable that it merits two chapters and an appendix all 36.38 - to itself. Chapter <xref linkend="chap.mq"/> covers the 36.39 - basics; chapter <xref 36.40 - linkend="chap.mq-collab"/> discusses advanced topics; 36.41 - and appendix <xref linkend="chap.mqref"/> goes into detail on 36.42 - each 36.43 - command.</para> 36.44 - </listitem></itemizedlist> 36.45 - 36.46 - <para>In this chapter, we'll cover some of the other extensions that 36.47 - are available for Mercurial, and briefly touch on some of the 36.48 - machinery you'll need to know about if you want to write an 36.49 - extension of your own.</para> 36.50 - <itemizedlist> 36.51 - <listitem><para>In section <xref linkend="sec.hgext.inotify"/>, 36.52 - we'll discuss the possibility of <emphasis>huge</emphasis> 36.53 - performance improvements using the <literal 36.54 - role="hg-ext">inotify</literal> extension.</para> 36.55 - </listitem></itemizedlist> 36.56 - 36.57 - <sect1 id="sec.hgext.inotify"> 36.58 - <title>Improve performance with the <literal 36.59 - role="hg-ext">inotify</literal> extension</title> 36.60 - 36.61 - <para>Are you interested in having some of the most common 36.62 - Mercurial operations run as much as a hundred times faster? 36.63 - Read on!</para> 36.64 - 36.65 - <para>Mercurial has great performance under normal circumstances. 36.66 - For example, when you run the <command role="hg-cmd">hg 36.67 - status</command> command, Mercurial has to scan almost every 36.68 - directory and file in your repository so that it can display 36.69 - file status. Many other Mercurial commands need to do the same 36.70 - work behind the scenes; for example, the <command 36.71 - role="hg-cmd">hg diff</command> command uses the status 36.72 - machinery to avoid doing an expensive comparison operation on 36.73 - files that obviously haven't changed.</para> 36.74 - 36.75 - <para>Because obtaining file status is crucial to good 36.76 - performance, the authors of Mercurial have optimised this code 36.77 - to within an inch of its life. However, there's no avoiding the 36.78 - fact that when you run <command role="hg-cmd">hg 36.79 - status</command>, Mercurial is going to have to perform at 36.80 - least one expensive system call for each managed file to 36.81 - determine whether it's changed since the last time Mercurial 36.82 - checked. For a sufficiently large repository, this can take a 36.83 - long time.</para> 36.84 - 36.85 - <para>To put a number on the magnitude of this effect, I created a 36.86 - repository containing 150,000 managed files. I timed <command 36.87 - role="hg-cmd">hg status</command> as taking ten seconds to 36.88 - run, even when <emphasis>none</emphasis> of those files had been 36.89 - modified.</para> 36.90 - 36.91 - <para>Many modern operating systems contain a file notification 36.92 - facility. If a program signs up to an appropriate service, the 36.93 - operating system will notify it every time a file of interest is 36.94 - created, modified, or deleted. On Linux systems, the kernel 36.95 - component that does this is called 36.96 - <literal>inotify</literal>.</para> 36.97 - 36.98 - <para>Mercurial's <literal role="hg-ext">inotify</literal> 36.99 - extension talks to the kernel's <literal>inotify</literal> 36.100 - component to optimise <command role="hg-cmd">hg status</command> 36.101 - commands. The extension has two components. A daemon sits in 36.102 - the background and receives notifications from the 36.103 - <literal>inotify</literal> subsystem. It also listens for 36.104 - connections from a regular Mercurial command. The extension 36.105 - modifies Mercurial's behaviour so that instead of scanning the 36.106 - filesystem, it queries the daemon. Since the daemon has perfect 36.107 - information about the state of the repository, it can respond 36.108 - with a result instantaneously, avoiding the need to scan every 36.109 - directory and file in the repository.</para> 36.110 - 36.111 - <para>Recall the ten seconds that I measured plain Mercurial as 36.112 - taking to run <command role="hg-cmd">hg status</command> on a 36.113 - 150,000 file repository. With the <literal 36.114 - role="hg-ext">inotify</literal> extension enabled, the time 36.115 - dropped to 0.1 seconds, a factor of <emphasis>one 36.116 - hundred</emphasis> faster.</para> 36.117 - 36.118 - <para>Before we continue, please pay attention to some 36.119 - caveats.</para> 36.120 - <itemizedlist> 36.121 - <listitem><para>The <literal role="hg-ext">inotify</literal> 36.122 - extension is Linux-specific. Because it interfaces directly 36.123 - to the Linux kernel's <literal>inotify</literal> subsystem, 36.124 - it does not work on other operating systems.</para> 36.125 - </listitem> 36.126 - <listitem><para>It should work on any Linux distribution that 36.127 - was released after early 2005. Older distributions are 36.128 - likely to have a kernel that lacks 36.129 - <literal>inotify</literal>, or a version of 36.130 - <literal>glibc</literal> that does not have the necessary 36.131 - interfacing support.</para> 36.132 - </listitem> 36.133 - <listitem><para>Not all filesystems are suitable for use with 36.134 - the <literal role="hg-ext">inotify</literal> extension. 36.135 - Network filesystems such as NFS are a non-starter, for 36.136 - example, particularly if you're running Mercurial on several 36.137 - systems, all mounting the same network filesystem. The 36.138 - kernel's <literal>inotify</literal> system has no way of 36.139 - knowing about changes made on another system. Most local 36.140 - filesystems (e.g. ext3, XFS, ReiserFS) should work 36.141 - fine.</para> 36.142 - </listitem></itemizedlist> 36.143 - 36.144 - <para>The <literal role="hg-ext">inotify</literal> extension is 36.145 - not yet shipped with Mercurial as of May 2007, so it's a little 36.146 - more involved to set up than other extensions. But the 36.147 - performance improvement is worth it!</para> 36.148 - 36.149 - <para>The extension currently comes in two parts: a set of patches 36.150 - to the Mercurial source code, and a library of Python bindings 36.151 - to the <literal>inotify</literal> subsystem.</para> 36.152 - <note> 36.153 - <para> There are <emphasis>two</emphasis> Python 36.154 - <literal>inotify</literal> binding libraries. One of them is 36.155 - called <literal>pyinotify</literal>, and is packaged by some 36.156 - Linux distributions as <literal>python-inotify</literal>. 36.157 - This is <emphasis>not</emphasis> the one you'll need, as it is 36.158 - too buggy and inefficient to be practical.</para> 36.159 - </note> 36.160 - <para>To get going, it's best to already have a functioning copy 36.161 - of Mercurial installed.</para> 36.162 - <note> 36.163 - <para> If you follow the instructions below, you'll be 36.164 - <emphasis>replacing</emphasis> and overwriting any existing 36.165 - installation of Mercurial that you might already have, using 36.166 - the latest <quote>bleeding edge</quote> Mercurial code. Don't 36.167 - say you weren't warned!</para> 36.168 - </note> 36.169 - <orderedlist> 36.170 - <listitem><para>Clone the Python <literal>inotify</literal> 36.171 - binding repository. Build and install it.</para> 36.172 - <programlisting>hg clone http://hg.kublai.com/python/inotify 36.173 -cd inotify 36.174 -python setup.py build --force 36.175 -sudo python setup.py install --skip-build</programlisting> 36.176 - </listitem> 36.177 - <listitem><para>Clone the <filename 36.178 - class="directory">crew</filename> Mercurial repository. 36.179 - Clone the <literal role="hg-ext">inotify</literal> patch 36.180 - repository so that Mercurial Queues will be able to apply 36.181 - patches to your cope of the <filename 36.182 - class="directory">crew</filename> repository.</para> 36.183 - <programlisting>hg clone http://hg.intevation.org/mercurial/crew 36.184 -hg clone crew inotify 36.185 -hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting> 36.186 - </listitem> 36.187 - <listitem><para>Make sure that you have the Mercurial Queues 36.188 - extension, <literal role="hg-ext">mq</literal>, enabled. If 36.189 - you've never used MQ, read section <xref 36.190 - linkend="sec.mq.start"/> to get started 36.191 - quickly.</para> 36.192 - </listitem> 36.193 - <listitem><para>Go into the <filename 36.194 - class="directory">inotify</filename> repo, and apply all 36.195 - of the <literal role="hg-ext">inotify</literal> patches 36.196 - using the <option role="hg-ext-mq-cmd-qpush-opt">hg 36.197 - -a</option> option to the <command 36.198 - role="hg-ext-mq">qpush</command> command.</para> 36.199 - <programlisting>cd inotify 36.200 -hg qpush -a</programlisting> 36.201 - </listitem> 36.202 - <listitem><para> If you get an error message from <command 36.203 - role="hg-ext-mq">qpush</command>, you should not continue. 36.204 - Instead, ask for help.</para> 36.205 - </listitem> 36.206 - <listitem><para>Build and install the patched version of 36.207 - Mercurial.</para> 36.208 - <programlisting>python setup.py build --force 36.209 -sudo python setup.py install --skip-build</programlisting> 36.210 - </listitem> 36.211 - </orderedlist> 36.212 - <para>Once you've build a suitably patched version of Mercurial, 36.213 - all you need to do to enable the <literal 36.214 - role="hg-ext">inotify</literal> extension is add an entry to 36.215 - your <filename role="special">~/.hgrc</filename>.</para> 36.216 - <programlisting>[extensions] inotify =</programlisting> 36.217 - <para>When the <literal role="hg-ext">inotify</literal> extension 36.218 - is enabled, Mercurial will automatically and transparently start 36.219 - the status daemon the first time you run a command that needs 36.220 - status in a repository. It runs one status daemon per 36.221 - repository.</para> 36.222 - 36.223 - <para>The status daemon is started silently, and runs in the 36.224 - background. If you look at a list of running processes after 36.225 - you've enabled the <literal role="hg-ext">inotify</literal> 36.226 - extension and run a few commands in different repositories, 36.227 - you'll thus see a few <literal>hg</literal> processes sitting 36.228 - around, waiting for updates from the kernel and queries from 36.229 - Mercurial.</para> 36.230 - 36.231 - <para>The first time you run a Mercurial command in a repository 36.232 - when you have the <literal role="hg-ext">inotify</literal> 36.233 - extension enabled, it will run with about the same performance 36.234 - as a normal Mercurial command. This is because the status 36.235 - daemon needs to perform a normal status scan so that it has a 36.236 - baseline against which to apply later updates from the kernel. 36.237 - However, <emphasis>every</emphasis> subsequent command that does 36.238 - any kind of status check should be noticeably faster on 36.239 - repositories of even fairly modest size. Better yet, the bigger 36.240 - your repository is, the greater a performance advantage you'll 36.241 - see. The <literal role="hg-ext">inotify</literal> daemon makes 36.242 - status operations almost instantaneous on repositories of all 36.243 - sizes!</para> 36.244 - 36.245 - <para>If you like, you can manually start a status daemon using 36.246 - the <command role="hg-ext-inotify">inserve</command> command. 36.247 - This gives you slightly finer control over how the daemon ought 36.248 - to run. This command will of course only be available when the 36.249 - <literal role="hg-ext">inotify</literal> extension is 36.250 - enabled.</para> 36.251 - 36.252 - <para>When you're using the <literal 36.253 - role="hg-ext">inotify</literal> extension, you should notice 36.254 - <emphasis>no difference at all</emphasis> in Mercurial's 36.255 - behaviour, with the sole exception of status-related commands 36.256 - running a whole lot faster than they used to. You should 36.257 - specifically expect that commands will not print different 36.258 - output; neither should they give different results. If either of 36.259 - these situations occurs, please report a bug.</para> 36.260 - 36.261 - </sect1> 36.262 - <sect1 id="sec.hgext.extdiff"> 36.263 - <title>Flexible diff support with the <literal 36.264 - role="hg-ext">extdiff</literal> extension</title> 36.265 - 36.266 - <para>Mercurial's built-in <command role="hg-cmd">hg 36.267 - diff</command> command outputs plaintext unified diffs.</para> 36.268 - 36.269 - &interaction.extdiff.diff; 36.270 - 36.271 - <para>If you would like to use an external tool to display 36.272 - modifications, you'll want to use the <literal 36.273 - role="hg-ext">extdiff</literal> extension. This will let you 36.274 - use, for example, a graphical diff tool.</para> 36.275 - 36.276 - <para>The <literal role="hg-ext">extdiff</literal> extension is 36.277 - bundled with Mercurial, so it's easy to set up. In the <literal 36.278 - role="rc-extensions">extensions</literal> section of your 36.279 - <filename role="special">~/.hgrc</filename>, simply add a 36.280 - one-line entry to enable the extension.</para> 36.281 - <programlisting>[extensions] 36.282 -extdiff =</programlisting> 36.283 - <para>This introduces a command named <command 36.284 - role="hg-ext-extdiff">extdiff</command>, which by default uses 36.285 - your system's <command>diff</command> command to generate a 36.286 - unified diff in the same form as the built-in <command 36.287 - role="hg-cmd">hg diff</command> command.</para> 36.288 - 36.289 - &interaction.extdiff.extdiff; 36.290 - 36.291 - <para>The result won't be exactly the same as with the built-in 36.292 - <command role="hg-cmd">hg diff</command> variations, because the 36.293 - output of <command>diff</command> varies from one system to 36.294 - another, even when passed the same options.</para> 36.295 - 36.296 - <para>As the <quote><literal>making snapshot</literal></quote> 36.297 - lines of output above imply, the <command 36.298 - role="hg-ext-extdiff">extdiff</command> command works by 36.299 - creating two snapshots of your source tree. The first snapshot 36.300 - is of the source revision; the second, of the target revision or 36.301 - working directory. The <command 36.302 - role="hg-ext-extdiff">extdiff</command> command generates 36.303 - these snapshots in a temporary directory, passes the name of 36.304 - each directory to an external diff viewer, then deletes the 36.305 - temporary directory. For efficiency, it only snapshots the 36.306 - directories and files that have changed between the two 36.307 - revisions.</para> 36.308 - 36.309 - <para>Snapshot directory names have the same base name as your 36.310 - repository. If your repository path is <filename 36.311 - class="directory">/quux/bar/foo</filename>, then <filename 36.312 - class="directory">foo</filename> will be the name of each 36.313 - snapshot directory. Each snapshot directory name has its 36.314 - changeset ID appended, if appropriate. If a snapshot is of 36.315 - revision <literal>a631aca1083f</literal>, the directory will be 36.316 - named <filename class="directory">foo.a631aca1083f</filename>. 36.317 - A snapshot of the working directory won't have a changeset ID 36.318 - appended, so it would just be <filename 36.319 - class="directory">foo</filename> in this example. To see what 36.320 - this looks like in practice, look again at the <command 36.321 - role="hg-ext-extdiff">extdiff</command> example above. Notice 36.322 - that the diff has the snapshot directory names embedded in its 36.323 - header.</para> 36.324 - 36.325 - <para>The <command role="hg-ext-extdiff">extdiff</command> command 36.326 - accepts two important options. The <option 36.327 - role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option 36.328 - lets you choose a program to view differences with, instead of 36.329 - <command>diff</command>. With the <option 36.330 - role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option, 36.331 - you can change the options that <command 36.332 - role="hg-ext-extdiff">extdiff</command> passes to the program 36.333 - (by default, these options are 36.334 - <quote><literal>-Npru</literal></quote>, which only make sense 36.335 - if you're running <command>diff</command>). In other respects, 36.336 - the <command role="hg-ext-extdiff">extdiff</command> command 36.337 - acts similarly to the built-in <command role="hg-cmd">hg 36.338 - diff</command> command: you use the same option names, syntax, 36.339 - and arguments to specify the revisions you want, the files you 36.340 - want, and so on.</para> 36.341 - 36.342 - <para>As an example, here's how to run the normal system 36.343 - <command>diff</command> command, getting it to generate context 36.344 - diffs (using the <option role="cmd-opt-diff">-c</option> option) 36.345 - instead of unified diffs, and five lines of context instead of 36.346 - the default three (passing <literal>5</literal> as the argument 36.347 - to the <option role="cmd-opt-diff">-C</option> option).</para> 36.348 - 36.349 - &interaction.extdiff.extdiff-ctx; 36.350 - 36.351 - <para>Launching a visual diff tool is just as easy. Here's how to 36.352 - launch the <command>kdiff3</command> viewer.</para> 36.353 - <programlisting>hg extdiff -p kdiff3 -o</programlisting> 36.354 - 36.355 - <para>If your diff viewing command can't deal with directories, 36.356 - you can easily work around this with a little scripting. For an 36.357 - example of such scripting in action with the <literal 36.358 - role="hg-ext">mq</literal> extension and the 36.359 - <command>interdiff</command> command, see section <xref 36.360 - linkend="mq-collab.tips.interdiff"/>.</para> 36.361 - 36.362 - <sect2> 36.363 - <title>Defining command aliases</title> 36.364 - 36.365 - <para>It can be cumbersome to remember the options to both the 36.366 - <command role="hg-ext-extdiff">extdiff</command> command and 36.367 - the diff viewer you want to use, so the <literal 36.368 - role="hg-ext">extdiff</literal> extension lets you define 36.369 - <emphasis>new</emphasis> commands that will invoke your diff 36.370 - viewer with exactly the right options.</para> 36.371 - 36.372 - <para>All you need to do is edit your <filename 36.373 - role="special">~/.hgrc</filename>, and add a section named 36.374 - <literal role="rc-extdiff">extdiff</literal>. Inside this 36.375 - section, you can define multiple commands. Here's how to add 36.376 - a <literal>kdiff3</literal> command. Once you've defined 36.377 - this, you can type <quote><literal>hg kdiff3</literal></quote> 36.378 - and the <literal role="hg-ext">extdiff</literal> extension 36.379 - will run <command>kdiff3</command> for you.</para> 36.380 - <programlisting>[extdiff] 36.381 -cmd.kdiff3 =</programlisting> 36.382 - <para>If you leave the right hand side of the definition empty, 36.383 - as above, the <literal role="hg-ext">extdiff</literal> 36.384 - extension uses the name of the command you defined as the name 36.385 - of the external program to run. But these names don't have to 36.386 - be the same. Here, we define a command named 36.387 - <quote><literal>hg wibble</literal></quote>, which runs 36.388 - <command>kdiff3</command>.</para> 36.389 - <programlisting>[extdiff] 36.390 - cmd.wibble = kdiff3</programlisting> 36.391 - 36.392 - <para>You can also specify the default options that you want to 36.393 - invoke your diff viewing program with. The prefix to use is 36.394 - <quote><literal>opts.</literal></quote>, followed by the name 36.395 - of the command to which the options apply. This example 36.396 - defines a <quote><literal>hg vimdiff</literal></quote> command 36.397 - that runs the <command>vim</command> editor's 36.398 - <literal>DirDiff</literal> extension.</para> 36.399 - <programlisting>[extdiff] 36.400 - cmd.vimdiff = vim 36.401 -opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting> 36.402 - 36.403 - </sect2> 36.404 - </sect1> 36.405 - <sect1 id="sec.hgext.transplant"> 36.406 - <title>Cherrypicking changes with the <literal 36.407 - role="hg-ext">transplant</literal> extension</title> 36.408 - 36.409 - <para>Need to have a long chat with Brendan about this.</para> 36.410 - 36.411 - </sect1> 36.412 - <sect1 id="sec.hgext.patchbomb"> 36.413 - <title>Send changes via email with the <literal 36.414 - role="hg-ext">patchbomb</literal> extension</title> 36.415 - 36.416 - <para>Many projects have a culture of <quote>change 36.417 - review</quote>, in which people send their modifications to a 36.418 - mailing list for others to read and comment on before they 36.419 - commit the final version to a shared repository. Some projects 36.420 - have people who act as gatekeepers; they apply changes from 36.421 - other people to a repository to which those others don't have 36.422 - access.</para> 36.423 - 36.424 - <para>Mercurial makes it easy to send changes over email for 36.425 - review or application, via its <literal 36.426 - role="hg-ext">patchbomb</literal> extension. The extension is 36.427 - so named because changes are formatted as patches, and it's usual 36.428 - to send one changeset per email message. Sending a long series 36.429 - of changes by email is thus much like <quote>bombing</quote> the 36.430 - recipient's inbox, hence <quote>patchbomb</quote>.</para> 36.431 - 36.432 - <para>As usual, the basic configuration of the <literal 36.433 - role="hg-ext">patchbomb</literal> extension takes just one or 36.434 - two lines in your <filename role="special"> 36.435 - /.hgrc</filename>.</para> 36.436 - <programlisting>[extensions] 36.437 -patchbomb =</programlisting> 36.438 - <para>Once you've enabled the extension, you will have a new 36.439 - command available, named <command 36.440 - role="hg-ext-patchbomb">email</command>.</para> 36.441 - 36.442 - <para>The safest and best way to invoke the <command 36.443 - role="hg-ext-patchbomb">email</command> command is to 36.444 - <emphasis>always</emphasis> run it first with the <option 36.445 - role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option. 36.446 - This will show you what the command <emphasis>would</emphasis> 36.447 - send, without actually sending anything. Once you've had a 36.448 - quick glance over the changes and verified that you are sending 36.449 - the right ones, you can rerun the same command, with the <option 36.450 - role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option 36.451 - removed.</para> 36.452 - 36.453 - <para>The <command role="hg-ext-patchbomb">email</command> command 36.454 - accepts the same kind of revision syntax as every other 36.455 - Mercurial command. For example, this command will send every 36.456 - revision between 7 and <literal>tip</literal>, inclusive.</para> 36.457 - <programlisting>hg email -n 7:tip</programlisting> 36.458 - <para>You can also specify a <emphasis>repository</emphasis> to 36.459 - compare with. If you provide a repository but no revisions, the 36.460 - <command role="hg-ext-patchbomb">email</command> command will 36.461 - send all revisions in the local repository that are not present 36.462 - in the remote repository. If you additionally specify revisions 36.463 - or a branch name (the latter using the <option 36.464 - role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option), 36.465 - this will constrain the revisions sent.</para> 36.466 - 36.467 - <para>It's perfectly safe to run the <command 36.468 - role="hg-ext-patchbomb">email</command> command without the 36.469 - names of the people you want to send to: if you do this, it will 36.470 - just prompt you for those values interactively. (If you're 36.471 - using a Linux or Unix-like system, you should have enhanced 36.472 - <literal>readline</literal>-style editing capabilities when 36.473 - entering those headers, too, which is useful.)</para> 36.474 - 36.475 - <para>When you are sending just one revision, the <command 36.476 - role="hg-ext-patchbomb">email</command> command will by 36.477 - default use the first line of the changeset description as the 36.478 - subject of the single email message it sends.</para> 36.479 - 36.480 - <para>If you send multiple revisions, the <command 36.481 - role="hg-ext-patchbomb">email</command> command will usually 36.482 - send one message per changeset. It will preface the series with 36.483 - an introductory message, in which you should describe the 36.484 - purpose of the series of changes you're sending.</para> 36.485 - 36.486 - <sect2> 36.487 - <title>Changing the behaviour of patchbombs</title> 36.488 - 36.489 - <para>Not every project has exactly the same conventions for 36.490 - sending changes in email; the <literal 36.491 - role="hg-ext">patchbomb</literal> extension tries to 36.492 - accommodate a number of variations through command line 36.493 - options.</para> 36.494 - <itemizedlist> 36.495 - <listitem><para>You can write a subject for the introductory 36.496 - message on the command line using the <option 36.497 - role="hg-ext-patchbomb-cmd-email-opt">hg -s</option> 36.498 - option. This takes one argument, the text of the subject 36.499 - to use.</para> 36.500 - </listitem> 36.501 - <listitem><para>To change the email address from which the 36.502 - messages originate, use the <option 36.503 - role="hg-ext-patchbomb-cmd-email-opt">hg -f</option> 36.504 - option. This takes one argument, the email address to 36.505 - use.</para> 36.506 - </listitem> 36.507 - <listitem><para>The default behaviour is to send unified diffs 36.508 - (see section <xref linkend="sec.mq.patch"/> for a 36.509 - description of the 36.510 - format), one per message. You can send a binary bundle 36.511 - instead with the <option 36.512 - role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> 36.513 - option.</para> 36.514 - </listitem> 36.515 - <listitem><para>Unified diffs are normally prefaced with a 36.516 - metadata header. You can omit this, and send unadorned 36.517 - diffs, with the <option 36.518 - role="hg-ext-patchbomb-cmd-email-opt">hg 36.519 - --plain</option> option.</para> 36.520 - </listitem> 36.521 - <listitem><para>Diffs are normally sent <quote>inline</quote>, 36.522 - in the same body part as the description of a patch. This 36.523 - makes it easiest for the largest number of readers to 36.524 - quote and respond to parts of a diff, as some mail clients 36.525 - will only quote the first MIME body part in a message. If 36.526 - you'd prefer to send the description and the diff in 36.527 - separate body parts, use the <option 36.528 - role="hg-ext-patchbomb-cmd-email-opt">hg -a</option> 36.529 - option.</para> 36.530 - </listitem> 36.531 - <listitem><para>Instead of sending mail messages, you can 36.532 - write them to an <literal>mbox</literal>-format mail 36.533 - folder using the <option 36.534 - role="hg-ext-patchbomb-cmd-email-opt">hg -m</option> 36.535 - option. That option takes one argument, the name of the 36.536 - file to write to.</para> 36.537 - </listitem> 36.538 - <listitem><para>If you would like to add a 36.539 - <command>diffstat</command>-format summary to each patch, 36.540 - and one to the introductory message, use the <option 36.541 - role="hg-ext-patchbomb-cmd-email-opt">hg -d</option> 36.542 - option. The <command>diffstat</command> command displays 36.543 - a table containing the name of each file patched, the 36.544 - number of lines affected, and a histogram showing how much 36.545 - each file is modified. This gives readers a qualitative 36.546 - glance at how complex a patch is.</para> 36.547 - </listitem></itemizedlist> 36.548 - 36.549 - </sect2> 36.550 - </sect1> 36.551 -</chapter> 36.552 - 36.553 -<!-- 36.554 -local variables: 36.555 -sgml-parent-document: ("00book.xml" "book" "chapter") 36.556 -end: 36.557 --->
37.1 --- a/po/zh.po Fri Mar 20 15:40:06 2009 +0800 37.2 +++ b/po/zh.po Fri Mar 20 16:43:35 2009 +0800 37.3 @@ -41,7 +41,7 @@ 37.4 msgid "" 37.5 msgstr "" 37.6 "Project-Id-Version: hgbook 1.2\n" 37.7 -"POT-Creation-Date: 2009-03-18 19:48+0800\n" 37.8 +"POT-Creation-Date: 2009-03-20 15:47+0800\n" 37.9 "PO-Revision-Date: 2009-03-18 19:50+0800\n" 37.10 "Last-Translator: \n" 37.11 "Language-Team: Simplified Chinese <i18n-zh@googlegroups.com >\n" 37.12 @@ -475,15 +475,16 @@ 37.13 "patches</command>." 37.14 msgstr "" 37.15 37.16 +#. type: Content of: <book><appendix><sect1><sect2><title> 37.17 +#: ../en/appB-mq-ref.xml:43 37.18 +#, fuzzy 37.19 +msgid "" 37.20 +"<command role=\"hg-ext-mq\">qdelete</command>&emdash;delete a patch from the " 37.21 +"<filename role=\"special\">series</filename> file}" 37.22 +msgstr "<command role=\"hg-ext-mq\">qseries</command>&emdash;显示补丁序列" 37.23 + 37.24 #. type: Content of: <book><appendix><sect1><sect2><para> 37.25 -#: ../en/appB-mq-ref.xml:42 37.26 -msgid "" 37.27 -"\\subsection{<command role=\"hg-ext-mq\">qdelete</command>&emdash;delete a " 37.28 -"patch from the <filename role=\"special\">series</filename> file}" 37.29 -msgstr "" 37.30 - 37.31 -#. type: Content of: <book><appendix><sect1><sect2><para> 37.32 -#: ../en/appB-mq-ref.xml:47 37.33 +#: ../en/appB-mq-ref.xml:48 37.34 msgid "" 37.35 "The <command role=\"hg-ext-mq\">qdelete</command> command removes the entry " 37.36 "for a patch from the <filename role=\"special\">series</filename> file in the " 37.37 @@ -494,21 +495,21 @@ 37.38 msgstr "" 37.39 37.40 #. type: Content of: <book><appendix><sect1><sect2><para> 37.41 -#: ../en/appB-mq-ref.xml:56 ../en/appB-mq-ref.xml:98 ../en/appB-mq-ref.xml:156 37.42 -#: ../en/appB-mq-ref.xml:196 ../en/appB-mq-ref.xml:263 37.43 -#: ../en/appB-mq-ref.xml:334 ../en/appB-mq-ref.xml:403 37.44 -#: ../en/appB-mq-ref.xml:496 37.45 +#: ../en/appB-mq-ref.xml:57 ../en/appB-mq-ref.xml:99 ../en/appB-mq-ref.xml:157 37.46 +#: ../en/appB-mq-ref.xml:197 ../en/appB-mq-ref.xml:264 37.47 +#: ../en/appB-mq-ref.xml:335 ../en/appB-mq-ref.xml:404 37.48 +#: ../en/appB-mq-ref.xml:497 37.49 msgid "Options:" 37.50 msgstr "" 37.51 37.52 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.53 -#: ../en/appB-mq-ref.xml:58 37.54 +#: ../en/appB-mq-ref.xml:59 37.55 msgid "" 37.56 "<option role=\"hg-ext-mq-cmd-qdel-opt\">-f</option>: Delete the patch file." 37.57 msgstr "" 37.58 37.59 #. type: Content of: <book><appendix><sect1><sect2><title> 37.60 -#: ../en/appB-mq-ref.xml:65 37.61 +#: ../en/appB-mq-ref.xml:66 37.62 msgid "" 37.63 "<command role=\"hg-ext-mq\">qdiff</command>&emdash;print a diff of the " 37.64 "topmost applied patch" 37.65 @@ -516,7 +517,7 @@ 37.66 "<command role=\"hg-ext-mq\">qdiff</command>&emdash;显示最新应用补丁的差异" 37.67 37.68 #. type: Content of: <book><appendix><sect1><sect2><para> 37.69 -#: ../en/appB-mq-ref.xml:68 37.70 +#: ../en/appB-mq-ref.xml:69 37.71 msgid "" 37.72 "The <command role=\"hg-ext-mq\">qdiff</command> command prints a diff of the " 37.73 "topmost applied patch. It is equivalent to <command role=\"hg-cmd\">hg diff -" 37.74 @@ -524,7 +525,7 @@ 37.75 msgstr "" 37.76 37.77 #. type: Content of: <book><appendix><sect1><sect2><title> 37.78 -#: ../en/appB-mq-ref.xml:74 37.79 +#: ../en/appB-mq-ref.xml:75 37.80 msgid "" 37.81 "<command role=\"hg-ext-mq\">qfold</command>&emdash;merge (<quote>fold</" 37.82 "quote>) several patches into one" 37.83 @@ -533,7 +534,7 @@ 37.84 "</quote>)成一个" 37.85 37.86 #. type: Content of: <book><appendix><sect1><sect2><para> 37.87 -#: ../en/appB-mq-ref.xml:77 37.88 +#: ../en/appB-mq-ref.xml:78 37.89 msgid "" 37.90 "The <command role=\"hg-ext-mq\">qfold</command> command merges multiple " 37.91 "patches into the topmost applied patch, so that the topmost applied patch " 37.92 @@ -541,7 +542,7 @@ 37.93 msgstr "" 37.94 37.95 #. type: Content of: <book><appendix><sect1><sect2><para> 37.96 -#: ../en/appB-mq-ref.xml:82 37.97 +#: ../en/appB-mq-ref.xml:83 37.98 msgid "" 37.99 "The patches to fold must not be applied; <command role=\"hg-ext-mq\">qfold</" 37.100 "command> will exit with an error if any is. The order in which patches are " 37.101 @@ -551,7 +552,7 @@ 37.102 msgstr "" 37.103 37.104 #. type: Content of: <book><appendix><sect1><sect2><para> 37.105 -#: ../en/appB-mq-ref.xml:90 37.106 +#: ../en/appB-mq-ref.xml:91 37.107 msgid "" 37.108 "The comments from the folded patches are appended to the comments of the " 37.109 "destination patch, with each block of comments separated by three asterisk " 37.110 @@ -561,14 +562,14 @@ 37.111 msgstr "" 37.112 37.113 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.114 -#: ../en/appB-mq-ref.xml:100 37.115 +#: ../en/appB-mq-ref.xml:101 37.116 msgid "" 37.117 "<option role=\"hg-ext-mq-cmd-qfold-opt\">-e</option>: Edit the commit message " 37.118 "and patch description for the newly folded patch." 37.119 msgstr "" 37.120 37.121 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.122 -#: ../en/appB-mq-ref.xml:105 37.123 +#: ../en/appB-mq-ref.xml:106 37.124 msgid "" 37.125 "<option role=\"hg-ext-mq-cmd-qfold-opt\">-l</option>: Use the contents of the " 37.126 "given file as the new commit message and patch description for the folded " 37.127 @@ -576,21 +577,21 @@ 37.128 msgstr "" 37.129 37.130 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.131 -#: ../en/appB-mq-ref.xml:110 37.132 +#: ../en/appB-mq-ref.xml:111 37.133 msgid "" 37.134 "<option role=\"hg-ext-mq-cmd-qfold-opt\">-m</option>: Use the given text as " 37.135 "the new commit message and patch description for the folded patch." 37.136 msgstr "" 37.137 37.138 #. type: Content of: <book><appendix><sect1><sect2><title> 37.139 -#: ../en/appB-mq-ref.xml:118 37.140 +#: ../en/appB-mq-ref.xml:119 37.141 msgid "" 37.142 "<command role=\"hg-ext-mq\">qheader</command>&emdash;display the header/" 37.143 "description of a patch" 37.144 msgstr "<command role=\"hg-ext-mq\">qheader</command>&emdash;显示补丁头部描述" 37.145 37.146 #. type: Content of: <book><appendix><sect1><sect2><para> 37.147 -#: ../en/appB-mq-ref.xml:122 37.148 +#: ../en/appB-mq-ref.xml:123 37.149 msgid "" 37.150 "The <command role=\"hg-ext-mq\">qheader</command> command prints the header, " 37.151 "or description, of a patch. By default, it prints the header of the topmost " 37.152 @@ -598,7 +599,7 @@ 37.153 msgstr "" 37.154 37.155 #. type: Content of: <book><appendix><sect1><sect2><title> 37.156 -#: ../en/appB-mq-ref.xml:129 37.157 +#: ../en/appB-mq-ref.xml:130 37.158 msgid "" 37.159 "<command role=\"hg-ext-mq\">qimport</command>&emdash;import a third-party " 37.160 "patch into the queue" 37.161 @@ -606,7 +607,7 @@ 37.162 "<command role=\"hg-ext-mq\">qimport</command>&emdash;将第三方补丁导入队列" 37.163 37.164 #. type: Content of: <book><appendix><sect1><sect2><para> 37.165 -#: ../en/appB-mq-ref.xml:132 37.166 +#: ../en/appB-mq-ref.xml:133 37.167 msgid "" 37.168 "The <command role=\"hg-ext-mq\">qimport</command> command adds an entry for " 37.169 "an external patch to the <filename role=\"special\">series</filename> file, " 37.170 @@ -616,7 +617,7 @@ 37.171 msgstr "" 37.172 37.173 #. type: Content of: <book><appendix><sect1><sect2><para> 37.174 -#: ../en/appB-mq-ref.xml:140 37.175 +#: ../en/appB-mq-ref.xml:141 37.176 msgid "" 37.177 "If the <filename role=\"special\" class=\"directory\">.hg/patches</filename> " 37.178 "directory is a repository, <command role=\"hg-ext-mq\">qimport</command> " 37.179 @@ -625,14 +626,14 @@ 37.180 msgstr "" 37.181 37.182 #. type: Content of: <book><appendix><sect1><sect2><title> 37.183 -#: ../en/appB-mq-ref.xml:148 37.184 +#: ../en/appB-mq-ref.xml:149 37.185 msgid "" 37.186 "<command role=\"hg-ext-mq\">qinit</command>&emdash;prepare a repository to " 37.187 "work with MQ" 37.188 msgstr "<command role=\"hg-ext-mq\">qinit</command>&emdash;为使用 MQ 配置版本库" 37.189 37.190 #. type: Content of: <book><appendix><sect1><sect2><para> 37.191 -#: ../en/appB-mq-ref.xml:151 37.192 +#: ../en/appB-mq-ref.xml:152 37.193 msgid "" 37.194 "The <command role=\"hg-ext-mq\">qinit</command> command prepares a repository " 37.195 "to work with MQ. It creates a directory called <filename role=\"special\" " 37.196 @@ -640,7 +641,7 @@ 37.197 msgstr "" 37.198 37.199 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.200 -#: ../en/appB-mq-ref.xml:158 37.201 +#: ../en/appB-mq-ref.xml:159 37.202 msgid "" 37.203 "<option role=\"hg-ext-mq-cmd-qinit-opt\">-c</option>: Create <filename role=" 37.204 "\"special\" class=\"directory\">.hg/patches</filename> as a repository in its " 37.205 @@ -649,7 +650,7 @@ 37.206 msgstr "" 37.207 37.208 #. type: Content of: <book><appendix><sect1><sect2><para> 37.209 -#: ../en/appB-mq-ref.xml:168 37.210 +#: ../en/appB-mq-ref.xml:169 37.211 msgid "" 37.212 "When the <filename role=\"special\" class=\"directory\">.hg/patches</" 37.213 "filename> directory is a repository, the <command role=\"hg-ext-mq\">qimport</" 37.214 @@ -658,12 +659,12 @@ 37.215 msgstr "" 37.216 37.217 #. type: Content of: <book><appendix><sect1><sect2><title> 37.218 -#: ../en/appB-mq-ref.xml:177 37.219 +#: ../en/appB-mq-ref.xml:178 37.220 msgid "<command role=\"hg-ext-mq\">qnew</command>&emdash;create a new patch" 37.221 msgstr "<command role=\"hg-ext-mq\">qnew</command>&emdash;创建新补丁" 37.222 37.223 #. type: Content of: <book><appendix><sect1><sect2><para> 37.224 -#: ../en/appB-mq-ref.xml:180 37.225 +#: ../en/appB-mq-ref.xml:181 37.226 msgid "" 37.227 "The <command role=\"hg-ext-mq\">qnew</command> command creates a new patch. " 37.228 "It takes one mandatory argument, the name to use for the patch file. The " 37.229 @@ -673,7 +674,7 @@ 37.230 msgstr "" 37.231 37.232 #. type: Content of: <book><appendix><sect1><sect2><para> 37.233 -#: ../en/appB-mq-ref.xml:188 37.234 +#: ../en/appB-mq-ref.xml:189 37.235 msgid "" 37.236 "If <command role=\"hg-ext-mq\">qnew</command> finds modified files in the " 37.237 "working directory, it will refuse to create a new patch unless the <option " 37.238 @@ -683,7 +684,7 @@ 37.239 msgstr "" 37.240 37.241 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.242 -#: ../en/appB-mq-ref.xml:198 37.243 +#: ../en/appB-mq-ref.xml:199 37.244 msgid "" 37.245 "<option role=\"hg-ext-mq-cmd-qnew-opt\">-f</option>: Create a new patch if " 37.246 "the contents of the working directory are modified. Any outstanding " 37.247 @@ -692,7 +693,7 @@ 37.248 msgstr "" 37.249 37.250 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.251 -#: ../en/appB-mq-ref.xml:205 37.252 +#: ../en/appB-mq-ref.xml:206 37.253 msgid "" 37.254 "<option role=\"hg-ext-mq-cmd-qnew-opt\">-m</option>: Use the given text as " 37.255 "the commit message. This text will be stored at the beginning of the patch " 37.256 @@ -700,14 +701,14 @@ 37.257 msgstr "" 37.258 37.259 #. type: Content of: <book><appendix><sect1><sect2><title> 37.260 -#: ../en/appB-mq-ref.xml:214 37.261 +#: ../en/appB-mq-ref.xml:215 37.262 msgid "" 37.263 "<command role=\"hg-ext-mq\">qnext</command>&emdash;print the name of the next " 37.264 "patch" 37.265 msgstr "<command role=\"hg-ext-mq\">qnext</command>&emdash;显示下个补丁的名称" 37.266 37.267 #. type: Content of: <book><appendix><sect1><sect2><para> 37.268 -#: ../en/appB-mq-ref.xml:217 37.269 +#: ../en/appB-mq-ref.xml:218 37.270 msgid "" 37.271 "The <command role=\"hg-ext-mq\">qnext</command> command prints the name name " 37.272 "of the next patch in the <filename role=\"special\">series</filename> file " 37.273 @@ -716,13 +717,13 @@ 37.274 msgstr "" 37.275 37.276 #. type: Content of: <book><appendix><sect1><sect2><title> 37.277 -#: ../en/appB-mq-ref.xml:226 37.278 +#: ../en/appB-mq-ref.xml:227 37.279 msgid "" 37.280 "<command role=\"hg-ext-mq\">qpop</command>&emdash;pop patches off the stack" 37.281 msgstr "<command role=\"hg-ext-mq\">qpop</command>&emdash;删除堆栈顶部的补丁" 37.282 37.283 #. type: Content of: <book><appendix><sect1><sect2><para> 37.284 -#: ../en/appB-mq-ref.xml:229 37.285 +#: ../en/appB-mq-ref.xml:230 37.286 msgid "" 37.287 "The <command role=\"hg-ext-mq\">qpop</command> command removes applied " 37.288 "patches from the top of the stack of applied patches. By default, it removes " 37.289 @@ -730,7 +731,7 @@ 37.290 msgstr "" 37.291 37.292 #. type: Content of: <book><appendix><sect1><sect2><para> 37.293 -#: ../en/appB-mq-ref.xml:233 37.294 +#: ../en/appB-mq-ref.xml:234 37.295 msgid "" 37.296 "This command removes the changesets that represent the popped patches from " 37.297 "the repository, and updates the working directory to undo the effects of the " 37.298 @@ -738,7 +739,7 @@ 37.299 msgstr "" 37.300 37.301 #. type: Content of: <book><appendix><sect1><sect2><para> 37.302 -#: ../en/appB-mq-ref.xml:237 37.303 +#: ../en/appB-mq-ref.xml:238 37.304 msgid "" 37.305 "This command takes an optional argument, which it uses as the name or index " 37.306 "of the patch to pop to. If given a name, it will pop patches until the named " 37.307 @@ -750,7 +751,7 @@ 37.308 msgstr "" 37.309 37.310 #. type: Content of: <book><appendix><sect1><sect2><para> 37.311 -#: ../en/appB-mq-ref.xml:247 37.312 +#: ../en/appB-mq-ref.xml:248 37.313 msgid "" 37.314 "The <command role=\"hg-ext-mq\">qpop</command> command does not read or write " 37.315 "patches or the <filename role=\"special\">series</filename> file. It is thus " 37.316 @@ -761,7 +762,7 @@ 37.317 msgstr "" 37.318 37.319 #. type: Content of: <book><appendix><sect1><sect2><para> 37.320 -#: ../en/appB-mq-ref.xml:256 37.321 +#: ../en/appB-mq-ref.xml:257 37.322 msgid "" 37.323 "By default, the <command role=\"hg-ext-mq\">qpop</command> command will not " 37.324 "pop any patches if the working directory has been modified. You can override " 37.325 @@ -770,7 +771,7 @@ 37.326 msgstr "" 37.327 37.328 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.329 -#: ../en/appB-mq-ref.xml:265 37.330 +#: ../en/appB-mq-ref.xml:266 37.331 msgid "" 37.332 "<option role=\"hg-ext-mq-cmd-qpop-opt\">-a</option>: Pop all applied " 37.333 "patches. This returns the repository to its state before you applied any " 37.334 @@ -778,21 +779,21 @@ 37.335 msgstr "" 37.336 37.337 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.338 -#: ../en/appB-mq-ref.xml:270 37.339 +#: ../en/appB-mq-ref.xml:271 37.340 msgid "" 37.341 "<option role=\"hg-ext-mq-cmd-qpop-opt\">-f</option>: Forcibly revert any " 37.342 "modifications to the working directory when popping." 37.343 msgstr "" 37.344 37.345 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.346 -#: ../en/appB-mq-ref.xml:275 37.347 +#: ../en/appB-mq-ref.xml:276 37.348 msgid "" 37.349 "<option role=\"hg-ext-mq-cmd-qpop-opt\">-n</option>: Pop a patch from the " 37.350 "named queue." 37.351 msgstr "" 37.352 37.353 #. type: Content of: <book><appendix><sect1><sect2><para> 37.354 -#: ../en/appB-mq-ref.xml:280 37.355 +#: ../en/appB-mq-ref.xml:281 37.356 msgid "" 37.357 "The <command role=\"hg-ext-mq\">qpop</command> command removes one line from " 37.358 "the end of the <filename role=\"special\">status</filename> file for each " 37.359 @@ -800,14 +801,14 @@ 37.360 msgstr "" 37.361 37.362 #. type: Content of: <book><appendix><sect1><sect2><title> 37.363 -#: ../en/appB-mq-ref.xml:287 37.364 +#: ../en/appB-mq-ref.xml:288 37.365 msgid "" 37.366 "<command role=\"hg-ext-mq\">qprev</command>&emdash;print the name of the " 37.367 "previous patch" 37.368 msgstr "<command role=\"hg-ext-mq\">qprev</command>&emdash;显示上个补丁的名称" 37.369 37.370 #. type: Content of: <book><appendix><sect1><sect2><para> 37.371 -#: ../en/appB-mq-ref.xml:290 37.372 +#: ../en/appB-mq-ref.xml:291 37.373 msgid "" 37.374 "The <command role=\"hg-ext-mq\">qprev</command> command prints the name of " 37.375 "the patch in the <filename role=\"special\">series</filename> file that comes " 37.376 @@ -816,32 +817,32 @@ 37.377 msgstr "" 37.378 37.379 #. type: Content of: <book><appendix><sect1><sect2><title> 37.380 -#: ../en/appB-mq-ref.xml:299 37.381 +#: ../en/appB-mq-ref.xml:300 37.382 msgid "" 37.383 "<command role=\"hg-ext-mq\">qpush</command>&emdash;push patches onto the stack" 37.384 msgstr "<command role=\"hg-ext-mq\">qpush</command>&emdash;增加补丁到堆栈" 37.385 37.386 #. type: Content of: <book><appendix><sect1><sect2><para> 37.387 -#: ../en/appB-mq-ref.xml:302 37.388 +#: ../en/appB-mq-ref.xml:303 37.389 msgid "" 37.390 "The <command role=\"hg-ext-mq\">qpush</command> command adds patches onto the " 37.391 "applied stack. By default, it adds only one patch." 37.392 msgstr "" 37.393 37.394 #. type: Content of: <book><appendix><sect1><sect2><para> 37.395 -#: ../en/appB-mq-ref.xml:306 37.396 +#: ../en/appB-mq-ref.xml:307 37.397 msgid "" 37.398 "This command creates a new changeset to represent each applied patch, and " 37.399 "updates the working directory to apply the effects of the patches." 37.400 msgstr "" 37.401 37.402 #. type: Content of: <book><appendix><sect1><sect2><para> 37.403 -#: ../en/appB-mq-ref.xml:310 37.404 +#: ../en/appB-mq-ref.xml:311 37.405 msgid "The default data used when creating a changeset are as follows:" 37.406 msgstr "" 37.407 37.408 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.409 -#: ../en/appB-mq-ref.xml:313 37.410 +#: ../en/appB-mq-ref.xml:314 37.411 msgid "" 37.412 "The commit date and time zone are the current date and time zone. Because " 37.413 "these data are used to compute the identity of a changeset, this means that " 37.414 @@ -851,14 +852,14 @@ 37.415 msgstr "" 37.416 37.417 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.418 -#: ../en/appB-mq-ref.xml:321 37.419 +#: ../en/appB-mq-ref.xml:322 37.420 msgid "" 37.421 "The author is the same as the default used by the <command role=\"hg-cmd\">hg " 37.422 "commit</command> command." 37.423 msgstr "" 37.424 37.425 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.426 -#: ../en/appB-mq-ref.xml:325 37.427 +#: ../en/appB-mq-ref.xml:326 37.428 msgid "" 37.429 "The commit message is any text from the patch file that comes before the " 37.430 "first diff header. If there is no such text, a default commit message is " 37.431 @@ -866,14 +867,14 @@ 37.432 msgstr "" 37.433 37.434 #. type: Content of: <book><appendix><sect1><sect2><para> 37.435 -#: ../en/appB-mq-ref.xml:330 37.436 +#: ../en/appB-mq-ref.xml:331 37.437 msgid "" 37.438 "If a patch contains a Mercurial patch header (XXX add link), the information " 37.439 "in the patch header overrides these defaults." 37.440 msgstr "" 37.441 37.442 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.443 -#: ../en/appB-mq-ref.xml:336 37.444 +#: ../en/appB-mq-ref.xml:337 37.445 msgid "" 37.446 "<option role=\"hg-ext-mq-cmd-qpush-opt\">-a</option>: Push all unapplied " 37.447 "patches from the <filename role=\"special\">series</filename> file until " 37.448 @@ -881,14 +882,14 @@ 37.449 msgstr "" 37.450 37.451 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.452 -#: ../en/appB-mq-ref.xml:342 37.453 +#: ../en/appB-mq-ref.xml:343 37.454 msgid "" 37.455 "<option role=\"hg-ext-mq-cmd-qpush-opt\">-l</option>: Add the name of the " 37.456 "patch to the end of the commit message." 37.457 msgstr "" 37.458 37.459 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.460 -#: ../en/appB-mq-ref.xml:346 37.461 +#: ../en/appB-mq-ref.xml:347 37.462 msgid "" 37.463 "<option role=\"hg-ext-mq-cmd-qpush-opt\">-m</option>: If a patch fails to " 37.464 "apply cleanly, use the entry for the patch in another saved queue to compute " 37.465 @@ -898,14 +899,14 @@ 37.466 msgstr "" 37.467 37.468 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.469 -#: ../en/appB-mq-ref.xml:354 37.470 +#: ../en/appB-mq-ref.xml:355 37.471 msgid "" 37.472 "<option role=\"hg-ext-mq-cmd-qpush-opt\">-n</option>: Use the named queue if " 37.473 "merging while pushing." 37.474 msgstr "" 37.475 37.476 #. type: Content of: <book><appendix><sect1><sect2><para> 37.477 -#: ../en/appB-mq-ref.xml:359 37.478 +#: ../en/appB-mq-ref.xml:360 37.479 msgid "" 37.480 "The <command role=\"hg-ext-mq\">qpush</command> command reads, but does not " 37.481 "modify, the <filename role=\"special\">series</filename> file. It appends " 37.482 @@ -914,14 +915,14 @@ 37.483 msgstr "" 37.484 37.485 #. type: Content of: <book><appendix><sect1><sect2><title> 37.486 -#: ../en/appB-mq-ref.xml:367 37.487 +#: ../en/appB-mq-ref.xml:368 37.488 msgid "" 37.489 "<command role=\"hg-ext-mq\">qrefresh</command>&emdash;update the topmost " 37.490 "applied patch" 37.491 msgstr "<command role=\"hg-ext-mq\">qrefresh</command>&emdash;更新最新的补丁" 37.492 37.493 #. type: Content of: <book><appendix><sect1><sect2><para> 37.494 -#: ../en/appB-mq-ref.xml:371 37.495 +#: ../en/appB-mq-ref.xml:372 37.496 msgid "" 37.497 "The <command role=\"hg-ext-mq\">qrefresh</command> command updates the " 37.498 "topmost applied patch. It modifies the patch, removes the old changeset that " 37.499 @@ -930,28 +931,28 @@ 37.500 msgstr "" 37.501 37.502 #. type: Content of: <book><appendix><sect1><sect2><para> 37.503 -#: ../en/appB-mq-ref.xml:377 37.504 +#: ../en/appB-mq-ref.xml:378 37.505 msgid "" 37.506 "The <command role=\"hg-ext-mq\">qrefresh</command> command looks for the " 37.507 "following modifications:" 37.508 msgstr "" 37.509 37.510 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.511 -#: ../en/appB-mq-ref.xml:380 37.512 +#: ../en/appB-mq-ref.xml:381 37.513 msgid "" 37.514 "Changes to the commit message, i.e. the text before the first diff header in " 37.515 "the patch file, are reflected in the new changeset that represents the patch." 37.516 msgstr "" 37.517 37.518 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.519 -#: ../en/appB-mq-ref.xml:385 37.520 +#: ../en/appB-mq-ref.xml:386 37.521 msgid "" 37.522 "Modifications to tracked files in the working directory are added to the " 37.523 "patch." 37.524 msgstr "" 37.525 37.526 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.527 -#: ../en/appB-mq-ref.xml:388 37.528 +#: ../en/appB-mq-ref.xml:389 37.529 msgid "" 37.530 "Changes to the files tracked using <command role=\"hg-cmd\">hg add</command>, " 37.531 "<command role=\"hg-cmd\">hg copy</command>, <command role=\"hg-cmd\">hg " 37.532 @@ -961,7 +962,7 @@ 37.533 msgstr "" 37.534 37.535 #. type: Content of: <book><appendix><sect1><sect2><para> 37.536 -#: ../en/appB-mq-ref.xml:397 37.537 +#: ../en/appB-mq-ref.xml:398 37.538 msgid "" 37.539 "Even if <command role=\"hg-ext-mq\">qrefresh</command> detects no changes, it " 37.540 "still recreates the changeset that represents the patch. This causes the " 37.541 @@ -970,33 +971,33 @@ 37.542 msgstr "" 37.543 37.544 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.545 -#: ../en/appB-mq-ref.xml:405 37.546 +#: ../en/appB-mq-ref.xml:406 37.547 msgid "" 37.548 "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-e</option>: Modify the commit " 37.549 "and patch description, using the preferred text editor." 37.550 msgstr "" 37.551 37.552 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.553 -#: ../en/appB-mq-ref.xml:410 37.554 +#: ../en/appB-mq-ref.xml:411 37.555 msgid "" 37.556 "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-m</option>: Modify the commit " 37.557 "message and patch description, using the given text." 37.558 msgstr "" 37.559 37.560 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.561 -#: ../en/appB-mq-ref.xml:415 37.562 +#: ../en/appB-mq-ref.xml:416 37.563 msgid "" 37.564 "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-l</option>: Modify the commit " 37.565 "message and patch description, using text from the given file." 37.566 msgstr "" 37.567 37.568 #. type: Content of: <book><appendix><sect1><sect2><title> 37.569 -#: ../en/appB-mq-ref.xml:423 37.570 +#: ../en/appB-mq-ref.xml:424 37.571 msgid "<command role=\"hg-ext-mq\">qrename</command>&emdash;rename a patch" 37.572 msgstr "<command role=\"hg-ext-mq\">qrename</command>&emdash;改名补丁" 37.573 37.574 #. type: Content of: <book><appendix><sect1><sect2><para> 37.575 -#: ../en/appB-mq-ref.xml:426 37.576 +#: ../en/appB-mq-ref.xml:427 37.577 msgid "" 37.578 "The <command role=\"hg-ext-mq\">qrename</command> command renames a patch, " 37.579 "and changes the entry for the patch in the <filename role=\"special\">series</" 37.580 @@ -1004,7 +1005,7 @@ 37.581 msgstr "" 37.582 37.583 #. type: Content of: <book><appendix><sect1><sect2><para> 37.584 -#: ../en/appB-mq-ref.xml:430 37.585 +#: ../en/appB-mq-ref.xml:431 37.586 msgid "" 37.587 "With a single argument, <command role=\"hg-ext-mq\">qrename</command> renames " 37.588 "the topmost applied patch. With two arguments, it renames its first argument " 37.589 @@ -1012,37 +1013,37 @@ 37.590 msgstr "" 37.591 37.592 #. type: Content of: <book><appendix><sect1><sect2><title> 37.593 -#: ../en/appB-mq-ref.xml:437 37.594 +#: ../en/appB-mq-ref.xml:438 37.595 msgid "" 37.596 "<command role=\"hg-ext-mq\">qrestore</command>&emdash;restore saved queue " 37.597 "state" 37.598 msgstr "<command role=\"hg-ext-mq\">qrestore</command>&emdash;恢复保存的队列" 37.599 37.600 #. type: Content of: <book><appendix><sect1><sect2><para> 37.601 -#: ../en/appB-mq-ref.xml:441 37.602 +#: ../en/appB-mq-ref.xml:442 37.603 msgid "XXX No idea what this does." 37.604 msgstr "" 37.605 37.606 #. type: Content of: <book><appendix><sect1><sect2><title> 37.607 -#: ../en/appB-mq-ref.xml:445 37.608 +#: ../en/appB-mq-ref.xml:446 37.609 msgid "" 37.610 "<command role=\"hg-ext-mq\">qsave</command>&emdash;save current queue state" 37.611 msgstr "<command role=\"hg-ext-mq\">qsave</command>&emdash;保存当前的队列状态" 37.612 37.613 #. type: Content of: <book><appendix><sect1><sect2><para> 37.614 -#: ../en/appB-mq-ref.xml:448 37.615 +#: ../en/appB-mq-ref.xml:449 37.616 msgid "XXX Likewise." 37.617 msgstr "" 37.618 37.619 #. type: Content of: <book><appendix><sect1><sect2><title> 37.620 -#: ../en/appB-mq-ref.xml:452 37.621 +#: ../en/appB-mq-ref.xml:453 37.622 msgid "" 37.623 "<command role=\"hg-ext-mq\">qseries</command>&emdash;print the entire patch " 37.624 "series" 37.625 msgstr "<command role=\"hg-ext-mq\">qseries</command>&emdash;显示补丁序列" 37.626 37.627 #. type: Content of: <book><appendix><sect1><sect2><para> 37.628 -#: ../en/appB-mq-ref.xml:455 37.629 +#: ../en/appB-mq-ref.xml:456 37.630 msgid "" 37.631 "The <command role=\"hg-ext-mq\">qseries</command> command prints the entire " 37.632 "patch series from the <filename role=\"special\">series</filename> file. It " 37.633 @@ -1051,21 +1052,21 @@ 37.634 msgstr "" 37.635 37.636 #. type: Content of: <book><appendix><sect1><sect2><title> 37.637 -#: ../en/appB-mq-ref.xml:463 37.638 +#: ../en/appB-mq-ref.xml:464 37.639 msgid "" 37.640 "<command role=\"hg-ext-mq\">qtop</command>&emdash;print the name of the " 37.641 "current patch" 37.642 msgstr "<command role=\"hg-ext-mq\">qtop</command>&emdash;显示当前补丁的名称" 37.643 37.644 #. type: Content of: <book><appendix><sect1><sect2><para> 37.645 -#: ../en/appB-mq-ref.xml:466 37.646 +#: ../en/appB-mq-ref.xml:467 37.647 msgid "" 37.648 "The <command role=\"hg-ext-mq\">qtop</command> prints the name of the topmost " 37.649 "currently applied patch." 37.650 msgstr "" 37.651 37.652 #. type: Content of: <book><appendix><sect1><sect2><title> 37.653 -#: ../en/appB-mq-ref.xml:471 37.654 +#: ../en/appB-mq-ref.xml:472 37.655 msgid "" 37.656 "<command role=\"hg-ext-mq\">qunapplied</command>&emdash;print patches not yet " 37.657 "applied" 37.658 @@ -1073,7 +1074,7 @@ 37.659 "<command role=\"hg-ext-mq\">qunapplied</command>&emdash;显示尚未应用的补丁" 37.660 37.661 #. type: Content of: <book><appendix><sect1><sect2><para> 37.662 -#: ../en/appB-mq-ref.xml:475 37.663 +#: ../en/appB-mq-ref.xml:476 37.664 msgid "" 37.665 "The <command role=\"hg-ext-mq\">qunapplied</command> command prints the names " 37.666 "of patches from the <filename role=\"special\">series</filename> file that " 37.667 @@ -1082,14 +1083,14 @@ 37.668 msgstr "" 37.669 37.670 #. type: Content of: <book><appendix><sect1><sect2><title> 37.671 -#: ../en/appB-mq-ref.xml:483 37.672 +#: ../en/appB-mq-ref.xml:484 37.673 msgid "" 37.674 "<command role=\"hg-cmd\">hg strip</command>&emdash;remove a revision and " 37.675 "descendants" 37.676 msgstr "<command role=\"hg-cmd\">hg strip</command>&emdash;删除一个版本及其后继" 37.677 37.678 #. type: Content of: <book><appendix><sect1><sect2><para> 37.679 -#: ../en/appB-mq-ref.xml:486 37.680 +#: ../en/appB-mq-ref.xml:487 37.681 msgid "" 37.682 "The <command role=\"hg-cmd\">hg strip</command> command removes a revision, " 37.683 "and all of its descendants, from the repository. It undoes the effects of " 37.684 @@ -1098,7 +1099,7 @@ 37.685 msgstr "" 37.686 37.687 #. type: Content of: <book><appendix><sect1><sect2><para> 37.688 -#: ../en/appB-mq-ref.xml:492 37.689 +#: ../en/appB-mq-ref.xml:493 37.690 msgid "" 37.691 "The <command role=\"hg-cmd\">hg strip</command> command saves a backup of the " 37.692 "removed changesets in a bundle, so that they can be reapplied if removed in " 37.693 @@ -1106,14 +1107,14 @@ 37.694 msgstr "" 37.695 37.696 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.697 -#: ../en/appB-mq-ref.xml:498 37.698 +#: ../en/appB-mq-ref.xml:499 37.699 msgid "" 37.700 "<option role=\"hg-opt-strip\">-b</option>: Save unrelated changesets that are " 37.701 "intermixed with the stripped changesets in the backup bundle." 37.702 msgstr "" 37.703 37.704 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.705 -#: ../en/appB-mq-ref.xml:502 37.706 +#: ../en/appB-mq-ref.xml:503 37.707 msgid "" 37.708 "<option role=\"hg-opt-strip\">-f</option>: If a branch has multiple heads, " 37.709 "remove all heads. XXX This should be renamed, and use <literal>-f</literal> " 37.710 @@ -1121,22 +1122,22 @@ 37.711 msgstr "" 37.712 37.713 #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> 37.714 -#: ../en/appB-mq-ref.xml:507 37.715 +#: ../en/appB-mq-ref.xml:508 37.716 msgid "<option role=\"hg-opt-strip\">-n</option>: Do not save a backup bundle." 37.717 msgstr "" 37.718 37.719 #. type: Content of: <book><appendix><sect1><title> 37.720 -#: ../en/appB-mq-ref.xml:514 37.721 +#: ../en/appB-mq-ref.xml:515 37.722 msgid "MQ file reference" 37.723 msgstr "MQ 文件参考" 37.724 37.725 #. type: Content of: <book><appendix><sect1><sect2><title> 37.726 -#: ../en/appB-mq-ref.xml:517 37.727 +#: ../en/appB-mq-ref.xml:518 37.728 msgid "The <filename role=\"special\">series</filename> file" 37.729 msgstr "<filename role=\"special\">序列</filename>文件" 37.730 37.731 #. type: Content of: <book><appendix><sect1><sect2><para> 37.732 -#: ../en/appB-mq-ref.xml:520 37.733 +#: ../en/appB-mq-ref.xml:521 37.734 msgid "" 37.735 "The <filename role=\"special\">series</filename> file contains a list of the " 37.736 "names of all patches that MQ can apply. It is represented as a list of " 37.737 @@ -1145,7 +1146,7 @@ 37.738 msgstr "" 37.739 37.740 #. type: Content of: <book><appendix><sect1><sect2><para> 37.741 -#: ../en/appB-mq-ref.xml:526 37.742 +#: ../en/appB-mq-ref.xml:527 37.743 msgid "" 37.744 "Lines may contain comments. A comment begins with the <quote><literal>#</" 37.745 "literal></quote> character, and extends to the end of the line. Empty lines, " 37.746 @@ -1153,7 +1154,7 @@ 37.747 msgstr "" 37.748 37.749 #. type: Content of: <book><appendix><sect1><sect2><para> 37.750 -#: ../en/appB-mq-ref.xml:531 37.751 +#: ../en/appB-mq-ref.xml:532 37.752 msgid "" 37.753 "You will often need to edit the <filename role=\"special\">series</filename> " 37.754 "file by hand, hence the support for comments and empty lines noted above. " 37.755 @@ -1164,7 +1165,7 @@ 37.756 msgstr "" 37.757 37.758 #. type: Content of: <book><appendix><sect1><sect2><para> 37.759 -#: ../en/appB-mq-ref.xml:540 37.760 +#: ../en/appB-mq-ref.xml:541 37.761 msgid "" 37.762 "Placing the <filename role=\"special\">series</filename> file under revision " 37.763 "control is also supported; it is a good idea to place all of the patches that " 37.764 @@ -1175,12 +1176,12 @@ 37.765 msgstr "" 37.766 37.767 #. type: Content of: <book><appendix><sect1><sect2><title> 37.768 -#: ../en/appB-mq-ref.xml:550 37.769 +#: ../en/appB-mq-ref.xml:551 37.770 msgid "The <filename role=\"special\">status</filename> file" 37.771 msgstr "<filename role=\"special\">状态</filename>文件" 37.772 37.773 #. type: Content of: <book><appendix><sect1><sect2><para> 37.774 -#: ../en/appB-mq-ref.xml:553 37.775 +#: ../en/appB-mq-ref.xml:554 37.776 msgid "" 37.777 "The <filename role=\"special\">status</filename> file contains the names and " 37.778 "changeset hashes of all patches that MQ currently has applied. Unlike the " 37.779 @@ -1519,941 +1520,17 @@ 37.780 msgstr "" 37.781 37.782 #. type: Content of: <book><chapter><title> 37.783 -#: ../en/ch01-intro.xml:5 37.784 -msgid "Introduction" 37.785 -msgstr "简介" 37.786 - 37.787 -#. type: Content of: <book><chapter><sect1><title> 37.788 -#: ../en/ch01-intro.xml:8 37.789 -msgid "About revision control" 37.790 -msgstr "关于版本控制" 37.791 - 37.792 -#. type: Content of: <book><chapter><sect1><para> 37.793 -#: ../en/ch01-intro.xml:10 37.794 -msgid "" 37.795 -"Revision control is the process of managing multiple versions of a piece of " 37.796 -"information. In its simplest form, this is something that many people do by " 37.797 -"hand: every time you modify a file, save it under a new name that contains a " 37.798 -"number, each one higher than the number of the preceding version." 37.799 -msgstr "" 37.800 - 37.801 -#. type: Content of: <book><chapter><sect1><para> 37.802 -#: ../en/ch01-intro.xml:16 37.803 -msgid "" 37.804 -"Manually managing multiple versions of even a single file is an error-prone " 37.805 -"task, though, so software tools to help automate this process have long been " 37.806 -"available. The earliest automated revision control tools were intended to " 37.807 -"help a single user to manage revisions of a single file. Over the past few " 37.808 -"decades, the scope of revision control tools has expanded greatly; they now " 37.809 -"manage multiple files, and help multiple people to work together. The best " 37.810 -"modern revision control tools have no problem coping with thousands of people " 37.811 -"working together on projects that consist of hundreds of thousands of files." 37.812 -msgstr "" 37.813 - 37.814 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.815 -#: ../en/ch01-intro.xml:28 37.816 -msgid "Why use revision control?" 37.817 -msgstr "为什么使用版本控制?" 37.818 - 37.819 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.820 -#: ../en/ch01-intro.xml:30 37.821 -msgid "" 37.822 -"There are a number of reasons why you or your team might want to use an " 37.823 -"automated revision control tool for a project." 37.824 -msgstr "" 37.825 - 37.826 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.827 -#: ../en/ch01-intro.xml:34 37.828 -msgid "" 37.829 -"It will track the history and evolution of your project, so you don't have " 37.830 -"to. For every change, you'll have a log of <emphasis>who</emphasis> made it; " 37.831 -"<emphasis>why</emphasis> they made it; <emphasis>when</emphasis> they made " 37.832 -"it; and <emphasis>what</emphasis> the change was." 37.833 -msgstr "" 37.834 - 37.835 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.836 -#: ../en/ch01-intro.xml:41 37.837 -msgid "" 37.838 -"When you're working with other people, revision control software makes it " 37.839 -"easier for you to collaborate. For example, when people more or less " 37.840 -"simultaneously make potentially incompatible changes, the software will help " 37.841 -"you to identify and resolve those conflicts." 37.842 -msgstr "" 37.843 - 37.844 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.845 -#: ../en/ch01-intro.xml:47 37.846 -msgid "" 37.847 -"It can help you to recover from mistakes. If you make a change that later " 37.848 -"turns out to be in error, you can revert to an earlier version of one or more " 37.849 -"files. In fact, a <emphasis>really</emphasis> good revision control tool " 37.850 -"will even help you to efficiently figure out exactly when a problem was " 37.851 -"introduced (see section <xref linkend=\"sec.undo.bisect\"/> for details)." 37.852 -msgstr "" 37.853 - 37.854 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.855 -#: ../en/ch01-intro.xml:54 37.856 -msgid "" 37.857 -"It will help you to work simultaneously on, and manage the drift between, " 37.858 -"multiple versions of your project." 37.859 -msgstr "" 37.860 - 37.861 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.862 -#: ../en/ch01-intro.xml:57 37.863 -msgid "" 37.864 -"Most of these reasons are equally valid---at least in theory---whether you're " 37.865 -"working on a project by yourself, or with a hundred other people." 37.866 -msgstr "" 37.867 - 37.868 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.869 -#: ../en/ch01-intro.xml:61 37.870 -msgid "" 37.871 -"A key question about the practicality of revision control at these two " 37.872 -"different scales (<quote>lone hacker</quote> and <quote>huge team</quote>) is " 37.873 -"how its <emphasis>benefits</emphasis> compare to its <emphasis>costs</" 37.874 -"emphasis>. A revision control tool that's difficult to understand or use is " 37.875 -"going to impose a high cost." 37.876 -msgstr "" 37.877 - 37.878 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.879 -#: ../en/ch01-intro.xml:69 37.880 -msgid "" 37.881 -"A five-hundred-person project is likely to collapse under its own weight " 37.882 -"almost immediately without a revision control tool and process. In this case, " 37.883 -"the cost of using revision control might hardly seem worth considering, since " 37.884 -"<emphasis>without</emphasis> it, failure is almost guaranteed." 37.885 -msgstr "" 37.886 - 37.887 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.888 -#: ../en/ch01-intro.xml:76 37.889 -msgid "" 37.890 -"On the other hand, a one-person <quote>quick hack</quote> might seem like a " 37.891 -"poor place to use a revision control tool, because surely the cost of using " 37.892 -"one must be close to the overall cost of the project. Right?" 37.893 -msgstr "" 37.894 - 37.895 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.896 -#: ../en/ch01-intro.xml:81 37.897 -msgid "" 37.898 -"Mercurial uniquely supports <emphasis>both</emphasis> of these scales of " 37.899 -"development. You can learn the basics in just a few minutes, and due to its " 37.900 -"low overhead, you can apply revision control to the smallest of projects with " 37.901 -"ease. Its simplicity means you won't have a lot of abstruse concepts or " 37.902 -"command sequences competing for mental space with whatever you're " 37.903 -"<emphasis>really</emphasis> trying to do. At the same time, Mercurial's high " 37.904 -"performance and peer-to-peer nature let you scale painlessly to handle large " 37.905 -"projects." 37.906 -msgstr "" 37.907 - 37.908 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.909 -#: ../en/ch01-intro.xml:91 37.910 -msgid "" 37.911 -"No revision control tool can rescue a poorly run project, but a good choice " 37.912 -"of tools can make a huge difference to the fluidity with which you can work " 37.913 -"on a project." 37.914 -msgstr "" 37.915 - 37.916 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.917 -#: ../en/ch01-intro.xml:97 37.918 -msgid "The many names of revision control" 37.919 -msgstr "版本控制的别名" 37.920 - 37.921 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.922 -#: ../en/ch01-intro.xml:99 37.923 -msgid "" 37.924 -"Revision control is a diverse field, so much so that it doesn't actually have " 37.925 -"a single name or acronym. Here are a few of the more common names and " 37.926 -"acronyms you'll encounter:" 37.927 -msgstr "" 37.928 - 37.929 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.930 -#: ../en/ch01-intro.xml:104 37.931 -msgid "Revision control (RCS)" 37.932 -msgstr "版本控制(RCS)" 37.933 - 37.934 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.935 -#: ../en/ch01-intro.xml:105 37.936 -msgid "Software configuration management (SCM), or configuration management" 37.937 -msgstr "软件配置管理(SCM),或配置管理" 37.938 - 37.939 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.940 -#: ../en/ch01-intro.xml:107 37.941 -msgid "Source code management" 37.942 -msgstr "源代码管理" 37.943 - 37.944 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.945 -#: ../en/ch01-intro.xml:108 37.946 -msgid "Source code control, or source control" 37.947 -msgstr "源代码控制,或源控制" 37.948 - 37.949 -#. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.950 -#: ../en/ch01-intro.xml:110 37.951 -msgid "Version control (VCS)" 37.952 -msgstr "版本控制(VCS)" 37.953 - 37.954 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.955 -#: ../en/ch01-intro.xml:112 37.956 -msgid "" 37.957 -"Some people claim that these terms actually have different meanings, but in " 37.958 -"practice they overlap so much that there's no agreed or even useful way to " 37.959 -"tease them apart." 37.960 -msgstr "" 37.961 - 37.962 -#. type: Content of: <book><chapter><sect1><title> 37.963 -#: ../en/ch01-intro.xml:119 37.964 -msgid "A short history of revision control" 37.965 -msgstr "版本控制简史" 37.966 - 37.967 -#. type: Content of: <book><chapter><sect1><para> 37.968 -#: ../en/ch01-intro.xml:121 37.969 -msgid "" 37.970 -"The best known of the old-time revision control tools is SCCS (Source Code " 37.971 -"Control System), which Marc Rochkind wrote at Bell Labs, in the early 1970s. " 37.972 -"SCCS operated on individual files, and required every person working on a " 37.973 -"project to have access to a shared workspace on a single system. Only one " 37.974 -"person could modify a file at any time; arbitration for access to files was " 37.975 -"via locks. It was common for people to lock files, and later forget to " 37.976 -"unlock them, preventing anyone else from modifying those files without the " 37.977 -"help of an administrator." 37.978 -msgstr "" 37.979 - 37.980 -#. type: Content of: <book><chapter><sect1><para> 37.981 -#: ../en/ch01-intro.xml:132 37.982 -msgid "" 37.983 -"Walter Tichy developed a free alternative to SCCS in the early 1980s; he " 37.984 -"called his program RCS (Revision Control System). Like SCCS, RCS required " 37.985 -"developers to work in a single shared workspace, and to lock files to prevent " 37.986 -"multiple people from modifying them simultaneously." 37.987 -msgstr "" 37.988 - 37.989 -#. type: Content of: <book><chapter><sect1><para> 37.990 -#: ../en/ch01-intro.xml:138 37.991 -msgid "" 37.992 -"Later in the 1980s, Dick Grune used RCS as a building block for a set of " 37.993 -"shell scripts he initially called cmt, but then renamed to CVS (Concurrent " 37.994 -"Versions System). The big innovation of CVS was that it let developers work " 37.995 -"simultaneously and somewhat independently in their own personal workspaces. " 37.996 -"The personal workspaces prevented developers from stepping on each other's " 37.997 -"toes all the time, as was common with SCCS and RCS. Each developer had a copy " 37.998 -"of every project file, and could modify their copies independently. They had " 37.999 -"to merge their edits prior to committing changes to the central repository." 37.1000 -msgstr "" 37.1001 - 37.1002 -#. type: Content of: <book><chapter><sect1><para> 37.1003 -#: ../en/ch01-intro.xml:149 37.1004 -msgid "" 37.1005 -"Brian Berliner took Grune's original scripts and rewrote them in C, releasing " 37.1006 -"in 1989 the code that has since developed into the modern version of CVS. " 37.1007 -"CVS subsequently acquired the ability to operate over a network connection, " 37.1008 -"giving it a client/server architecture. CVS's architecture is centralised; " 37.1009 -"only the server has a copy of the history of the project. Client workspaces " 37.1010 -"just contain copies of recent versions of the project's files, and a little " 37.1011 -"metadata to tell them where the server is. CVS has been enormously " 37.1012 -"successful; it is probably the world's most widely used revision control " 37.1013 -"system." 37.1014 -msgstr "" 37.1015 - 37.1016 -#. type: Content of: <book><chapter><sect1><para> 37.1017 -#: ../en/ch01-intro.xml:160 37.1018 -msgid "" 37.1019 -"In the early 1990s, Sun Microsystems developed an early distributed revision " 37.1020 -"control system, called TeamWare. A TeamWare workspace contains a complete " 37.1021 -"copy of the project's history. TeamWare has no notion of a central " 37.1022 -"repository. (CVS relied upon RCS for its history storage; TeamWare used " 37.1023 -"SCCS.)" 37.1024 -msgstr "" 37.1025 - 37.1026 -#. type: Content of: <book><chapter><sect1><para> 37.1027 -#: ../en/ch01-intro.xml:167 37.1028 -msgid "" 37.1029 -"As the 1990s progressed, awareness grew of a number of problems with CVS. It " 37.1030 -"records simultaneous changes to multiple files individually, instead of " 37.1031 -"grouping them together as a single logically atomic operation. It does not " 37.1032 -"manage its file hierarchy well; it is easy to make a mess of a repository by " 37.1033 -"renaming files and directories. Worse, its source code is difficult to read " 37.1034 -"and maintain, which made the <quote>pain level</quote> of fixing these " 37.1035 -"architectural problems prohibitive." 37.1036 -msgstr "" 37.1037 - 37.1038 -#. type: Content of: <book><chapter><sect1><para> 37.1039 -#: ../en/ch01-intro.xml:177 37.1040 -msgid "" 37.1041 -"In 2001, Jim Blandy and Karl Fogel, two developers who had worked on CVS, " 37.1042 -"started a project to replace it with a tool that would have a better " 37.1043 -"architecture and cleaner code. The result, Subversion, does not stray from " 37.1044 -"CVS's centralised client/server model, but it adds multi-file atomic commits, " 37.1045 -"better namespace management, and a number of other features that make it a " 37.1046 -"generally better tool than CVS. Since its initial release, it has rapidly " 37.1047 -"grown in popularity." 37.1048 -msgstr "" 37.1049 - 37.1050 -#. type: Content of: <book><chapter><sect1><para> 37.1051 -#: ../en/ch01-intro.xml:186 37.1052 -msgid "" 37.1053 -"More or less simultaneously, Graydon Hoare began working on an ambitious " 37.1054 -"distributed revision control system that he named Monotone. While Monotone " 37.1055 -"addresses many of CVS's design flaws and has a peer-to-peer architecture, it " 37.1056 -"goes beyond earlier (and subsequent) revision control tools in a number of " 37.1057 -"innovative ways. It uses cryptographic hashes as identifiers, and has an " 37.1058 -"integral notion of <quote>trust</quote> for code from different sources." 37.1059 -msgstr "" 37.1060 - 37.1061 -#. type: Content of: <book><chapter><sect1><para> 37.1062 -#: ../en/ch01-intro.xml:195 37.1063 -msgid "" 37.1064 -"Mercurial began life in 2005. While a few aspects of its design are " 37.1065 -"influenced by Monotone, Mercurial focuses on ease of use, high performance, " 37.1066 -"and scalability to very large projects." 37.1067 -msgstr "" 37.1068 - 37.1069 -#. type: Content of: <book><chapter><sect1><title> 37.1070 -#: ../en/ch01-intro.xml:202 37.1071 -msgid "Trends in revision control" 37.1072 -msgstr "版本控制的发展趋势" 37.1073 - 37.1074 -#. type: Content of: <book><chapter><sect1><para> 37.1075 -#: ../en/ch01-intro.xml:204 37.1076 -msgid "" 37.1077 -"There has been an unmistakable trend in the development and use of revision " 37.1078 -"control tools over the past four decades, as people have become familiar with " 37.1079 -"the capabilities of their tools and constrained by their limitations." 37.1080 -msgstr "" 37.1081 - 37.1082 -#. type: Content of: <book><chapter><sect1><para> 37.1083 -#: ../en/ch01-intro.xml:209 37.1084 -msgid "" 37.1085 -"The first generation began by managing single files on individual computers. " 37.1086 -"Although these tools represented a huge advance over ad-hoc manual revision " 37.1087 -"control, their locking model and reliance on a single computer limited them " 37.1088 -"to small, tightly-knit teams." 37.1089 -msgstr "" 37.1090 - 37.1091 -#. type: Content of: <book><chapter><sect1><para> 37.1092 -#: ../en/ch01-intro.xml:215 37.1093 -msgid "" 37.1094 -"The second generation loosened these constraints by moving to network-" 37.1095 -"centered architectures, and managing entire projects at a time. As projects " 37.1096 -"grew larger, they ran into new problems. With clients needing to talk to " 37.1097 -"servers very frequently, server scaling became an issue for large projects. " 37.1098 -"An unreliable network connection could prevent remote users from being able " 37.1099 -"to talk to the server at all. As open source projects started making read-" 37.1100 -"only access available anonymously to anyone, people without commit privileges " 37.1101 -"found that they could not use the tools to interact with a project in a " 37.1102 -"natural way, as they could not record their changes." 37.1103 -msgstr "" 37.1104 - 37.1105 -#. type: Content of: <book><chapter><sect1><para> 37.1106 -#: ../en/ch01-intro.xml:227 37.1107 -msgid "" 37.1108 -"The current generation of revision control tools is peer-to-peer in nature. " 37.1109 -"All of these systems have dropped the dependency on a single central server, " 37.1110 -"and allow people to distribute their revision control data to where it's " 37.1111 -"actually needed. Collaboration over the Internet has moved from constrained " 37.1112 -"by technology to a matter of choice and consensus. Modern tools can operate " 37.1113 -"offline indefinitely and autonomously, with a network connection only needed " 37.1114 -"when syncing changes with another repository." 37.1115 -msgstr "" 37.1116 - 37.1117 -#. type: Content of: <book><chapter><sect1><title> 37.1118 -#: ../en/ch01-intro.xml:239 37.1119 -msgid "A few of the advantages of distributed revision control" 37.1120 -msgstr "分布版本控制的优点" 37.1121 - 37.1122 -#. type: Content of: <book><chapter><sect1><para> 37.1123 -#: ../en/ch01-intro.xml:242 37.1124 -msgid "" 37.1125 -"Even though distributed revision control tools have for several years been as " 37.1126 -"robust and usable as their previous-generation counterparts, people using " 37.1127 -"older tools have not yet necessarily woken up to their advantages. There are " 37.1128 -"a number of ways in which distributed tools shine relative to centralised " 37.1129 -"ones." 37.1130 -msgstr "" 37.1131 - 37.1132 -#. type: Content of: <book><chapter><sect1><para> 37.1133 -#: ../en/ch01-intro.xml:249 37.1134 -msgid "" 37.1135 -"For an individual developer, distributed tools are almost always much faster " 37.1136 -"than centralised tools. This is for a simple reason: a centralised tool " 37.1137 -"needs to talk over the network for many common operations, because most " 37.1138 -"metadata is stored in a single copy on the central server. A distributed " 37.1139 -"tool stores all of its metadata locally. All else being equal, talking over " 37.1140 -"the network adds overhead to a centralised tool. Don't underestimate the " 37.1141 -"value of a snappy, responsive tool: you're going to spend a lot of time " 37.1142 -"interacting with your revision control software." 37.1143 -msgstr "" 37.1144 - 37.1145 -#. type: Content of: <book><chapter><sect1><para> 37.1146 -#: ../en/ch01-intro.xml:260 37.1147 -msgid "" 37.1148 -"Distributed tools are indifferent to the vagaries of your server " 37.1149 -"infrastructure, again because they replicate metadata to so many locations. " 37.1150 -"If you use a centralised system and your server catches fire, you'd better " 37.1151 -"hope that your backup media are reliable, and that your last backup was " 37.1152 -"recent and actually worked. With a distributed tool, you have many backups " 37.1153 -"available on every contributor's computer." 37.1154 -msgstr "" 37.1155 - 37.1156 -#. type: Content of: <book><chapter><sect1><para> 37.1157 -#: ../en/ch01-intro.xml:268 37.1158 -msgid "" 37.1159 -"The reliability of your network will affect distributed tools far less than " 37.1160 -"it will centralised tools. You can't even use a centralised tool without a " 37.1161 -"network connection, except for a few highly constrained commands. With a " 37.1162 -"distributed tool, if your network connection goes down while you're working, " 37.1163 -"you may not even notice. The only thing you won't be able to do is talk to " 37.1164 -"repositories on other computers, something that is relatively rare compared " 37.1165 -"with local operations. If you have a far-flung team of collaborators, this " 37.1166 -"may be significant." 37.1167 -msgstr "" 37.1168 - 37.1169 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.1170 -#: ../en/ch01-intro.xml:279 37.1171 -msgid "Advantages for open source projects" 37.1172 -msgstr "开源项目的优点" 37.1173 - 37.1174 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1175 -#: ../en/ch01-intro.xml:281 37.1176 -msgid "" 37.1177 -"If you take a shine to an open source project and decide that you would like " 37.1178 -"to start hacking on it, and that project uses a distributed revision control " 37.1179 -"tool, you are at once a peer with the people who consider themselves the " 37.1180 -"<quote>core</quote> of that project. If they publish their repositories, you " 37.1181 -"can immediately copy their project history, start making changes, and record " 37.1182 -"your work, using the same tools in the same ways as insiders. By contrast, " 37.1183 -"with a centralised tool, you must use the software in a <quote>read only</" 37.1184 -"quote> mode unless someone grants you permission to commit changes to their " 37.1185 -"central server. Until then, you won't be able to record changes, and your " 37.1186 -"local modifications will be at risk of corruption any time you try to update " 37.1187 -"your client's view of the repository." 37.1188 -msgstr "" 37.1189 - 37.1190 -#. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.1191 -#: ../en/ch01-intro.xml:297 37.1192 -msgid "The forking non-problem" 37.1193 -msgstr "" 37.1194 - 37.1195 -#. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.1196 -#: ../en/ch01-intro.xml:299 37.1197 -msgid "" 37.1198 -"It has been suggested that distributed revision control tools pose some sort " 37.1199 -"of risk to open source projects because they make it easy to <quote>fork</" 37.1200 -"quote> the development of a project. A fork happens when there are " 37.1201 -"differences in opinion or attitude between groups of developers that cause " 37.1202 -"them to decide that they can't work together any longer. Each side takes a " 37.1203 -"more or less complete copy of the project's source code, and goes off in its " 37.1204 -"own direction." 37.1205 -msgstr "" 37.1206 - 37.1207 -#. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.1208 -#: ../en/ch01-intro.xml:309 37.1209 -msgid "" 37.1210 -"Sometimes the camps in a fork decide to reconcile their differences. With a " 37.1211 -"centralised revision control system, the <emphasis>technical</emphasis> " 37.1212 -"process of reconciliation is painful, and has to be performed largely by " 37.1213 -"hand. You have to decide whose revision history is going to <quote>win</" 37.1214 -"quote>, and graft the other team's changes into the tree somehow. This " 37.1215 -"usually loses some or all of one side's revision history." 37.1216 -msgstr "" 37.1217 - 37.1218 -#. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.1219 -#: ../en/ch01-intro.xml:318 37.1220 -msgid "" 37.1221 -"What distributed tools do with respect to forking is they make forking the " 37.1222 -"<emphasis>only</emphasis> way to develop a project. Every single change that " 37.1223 -"you make is potentially a fork point. The great strength of this approach is " 37.1224 -"that a distributed revision control tool has to be really good at " 37.1225 -"<emphasis>merging</emphasis> forks, because forks are absolutely fundamental: " 37.1226 -"they happen all the time." 37.1227 -msgstr "" 37.1228 - 37.1229 -#. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.1230 -#: ../en/ch01-intro.xml:327 37.1231 -msgid "" 37.1232 -"If every piece of work that everybody does, all the time, is framed in terms " 37.1233 -"of forking and merging, then what the open source world refers to as a " 37.1234 -"<quote>fork</quote> becomes <emphasis>purely</emphasis> a social issue. If " 37.1235 -"anything, distributed tools <emphasis>lower</emphasis> the likelihood of a " 37.1236 -"fork:" 37.1237 -msgstr "" 37.1238 - 37.1239 -#. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.1240 -#: ../en/ch01-intro.xml:334 37.1241 -msgid "" 37.1242 -"They eliminate the social distinction that centralised tools impose: that " 37.1243 -"between insiders (people with commit access) and outsiders (people without)." 37.1244 -msgstr "" 37.1245 - 37.1246 -#. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.1247 -#: ../en/ch01-intro.xml:338 37.1248 -msgid "" 37.1249 -"They make it easier to reconcile after a social fork, because all that's " 37.1250 -"involved from the perspective of the revision control software is just " 37.1251 -"another merge." 37.1252 -msgstr "" 37.1253 - 37.1254 -#. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.1255 -#: ../en/ch01-intro.xml:343 37.1256 -msgid "" 37.1257 -"Some people resist distributed tools because they want to retain tight " 37.1258 -"control over their projects, and they believe that centralised tools give " 37.1259 -"them this control. However, if you're of this belief, and you publish your " 37.1260 -"CVS or Subversion repositories publicly, there are plenty of tools available " 37.1261 -"that can pull out your entire project's history (albeit slowly) and recreate " 37.1262 -"it somewhere that you don't control. So while your control in this case is " 37.1263 -"illusory, you are forgoing the ability to fluidly collaborate with whatever " 37.1264 -"people feel compelled to mirror and fork your history." 37.1265 -msgstr "" 37.1266 - 37.1267 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.1268 -#: ../en/ch01-intro.xml:358 37.1269 -msgid "Advantages for commercial projects" 37.1270 -msgstr "商业项目的优点" 37.1271 - 37.1272 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1273 -#: ../en/ch01-intro.xml:360 37.1274 -msgid "" 37.1275 -"Many commercial projects are undertaken by teams that are scattered across " 37.1276 -"the globe. Contributors who are far from a central server will see slower " 37.1277 -"command execution and perhaps less reliability. Commercial revision control " 37.1278 -"systems attempt to ameliorate these problems with remote-site replication add-" 37.1279 -"ons that are typically expensive to buy and cantankerous to administer. A " 37.1280 -"distributed system doesn't suffer from these problems in the first place. " 37.1281 -"Better yet, you can easily set up multiple authoritative servers, say one per " 37.1282 -"site, so that there's no redundant communication between repositories over " 37.1283 -"expensive long-haul network links." 37.1284 -msgstr "" 37.1285 - 37.1286 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1287 -#: ../en/ch01-intro.xml:372 37.1288 -msgid "" 37.1289 -"Centralised revision control systems tend to have relatively low " 37.1290 -"scalability. It's not unusual for an expensive centralised system to fall " 37.1291 -"over under the combined load of just a few dozen concurrent users. Once " 37.1292 -"again, the typical response tends to be an expensive and clunky replication " 37.1293 -"facility. Since the load on a central server---if you have one at all---is " 37.1294 -"many times lower with a distributed tool (because all of the data is " 37.1295 -"replicated everywhere), a single cheap server can handle the needs of a much " 37.1296 -"larger team, and replication to balance load becomes a simple matter of " 37.1297 -"scripting." 37.1298 -msgstr "" 37.1299 - 37.1300 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1301 -#: ../en/ch01-intro.xml:384 37.1302 -msgid "" 37.1303 -"If you have an employee in the field, troubleshooting a problem at a " 37.1304 -"customer's site, they'll benefit from distributed revision control. The tool " 37.1305 -"will let them generate custom builds, try different fixes in isolation from " 37.1306 -"each other, and search efficiently through history for the sources of bugs " 37.1307 -"and regressions in the customer's environment, all without needing to connect " 37.1308 -"to your company's network." 37.1309 -msgstr "" 37.1310 - 37.1311 -#. type: Content of: <book><chapter><sect1><title> 37.1312 -#: ../en/ch01-intro.xml:395 37.1313 -msgid "Why choose Mercurial?" 37.1314 -msgstr "为什么选择 Mercurial?" 37.1315 - 37.1316 -#. type: Content of: <book><chapter><sect1><para> 37.1317 -#: ../en/ch01-intro.xml:397 37.1318 -msgid "" 37.1319 -"Mercurial has a unique set of properties that make it a particularly good " 37.1320 -"choice as a revision control system." 37.1321 -msgstr "" 37.1322 - 37.1323 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1324 -#: ../en/ch01-intro.xml:400 37.1325 -msgid "It is easy to learn and use." 37.1326 -msgstr "" 37.1327 - 37.1328 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1329 -#: ../en/ch01-intro.xml:401 37.1330 -msgid "It is lightweight." 37.1331 -msgstr "" 37.1332 - 37.1333 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1334 -#: ../en/ch01-intro.xml:402 37.1335 -msgid "It scales excellently." 37.1336 -msgstr "" 37.1337 - 37.1338 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1339 -#: ../en/ch01-intro.xml:403 37.1340 -msgid "It is easy to customise." 37.1341 -msgstr "" 37.1342 - 37.1343 -#. type: Content of: <book><chapter><sect1><para> 37.1344 -#: ../en/ch01-intro.xml:406 37.1345 -msgid "" 37.1346 -"If you are at all familiar with revision control systems, you should be able " 37.1347 -"to get up and running with Mercurial in less than five minutes. Even if not, " 37.1348 -"it will take no more than a few minutes longer. Mercurial's command and " 37.1349 -"feature sets are generally uniform and consistent, so you can keep track of a " 37.1350 -"few general rules instead of a host of exceptions." 37.1351 -msgstr "" 37.1352 - 37.1353 -#. type: Content of: <book><chapter><sect1><para> 37.1354 -#: ../en/ch01-intro.xml:413 37.1355 -msgid "" 37.1356 -"On a small project, you can start working with Mercurial in moments. Creating " 37.1357 -"new changes and branches; transferring changes around (whether locally or " 37.1358 -"over a network); and history and status operations are all fast. Mercurial " 37.1359 -"attempts to stay nimble and largely out of your way by combining low " 37.1360 -"cognitive overhead with blazingly fast operations." 37.1361 -msgstr "" 37.1362 - 37.1363 -#. type: Content of: <book><chapter><sect1><para> 37.1364 -#: ../en/ch01-intro.xml:420 37.1365 -msgid "" 37.1366 -"The usefulness of Mercurial is not limited to small projects: it is used by " 37.1367 -"projects with hundreds to thousands of contributors, each containing tens of " 37.1368 -"thousands of files and hundreds of megabytes of source code." 37.1369 -msgstr "" 37.1370 - 37.1371 -#. type: Content of: <book><chapter><sect1><para> 37.1372 -#: ../en/ch01-intro.xml:425 37.1373 -msgid "" 37.1374 -"If the core functionality of Mercurial is not enough for you, it's easy to " 37.1375 -"build on. Mercurial is well suited to scripting tasks, and its clean " 37.1376 -"internals and implementation in Python make it easy to add features in the " 37.1377 -"form of extensions. There are a number of popular and useful extensions " 37.1378 -"already available, ranging from helping to identify bugs to improving " 37.1379 -"performance." 37.1380 -msgstr "" 37.1381 - 37.1382 -#. type: Content of: <book><chapter><sect1><title> 37.1383 -#: ../en/ch01-intro.xml:435 37.1384 -msgid "Mercurial compared with other tools" 37.1385 -msgstr "Mercurial 与其它工具的比较" 37.1386 - 37.1387 -#. type: Content of: <book><chapter><sect1><para> 37.1388 -#: ../en/ch01-intro.xml:437 37.1389 -msgid "" 37.1390 -"Before you read on, please understand that this section necessarily reflects " 37.1391 -"my own experiences, interests, and (dare I say it) biases. I have used every " 37.1392 -"one of the revision control tools listed below, in most cases for several " 37.1393 -"years at a time." 37.1394 -msgstr "" 37.1395 - 37.1396 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1397 -#: ../en/ch01-intro.xml:445 ../en/ch01-intro.xml:656 37.1398 -msgid "Subversion" 37.1399 -msgstr "" 37.1400 - 37.1401 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1402 -#: ../en/ch01-intro.xml:447 37.1403 -msgid "" 37.1404 -"Subversion is a popular revision control tool, developed to replace CVS. It " 37.1405 -"has a centralised client/server architecture." 37.1406 -msgstr "" 37.1407 - 37.1408 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1409 -#: ../en/ch01-intro.xml:451 37.1410 -msgid "" 37.1411 -"Subversion and Mercurial have similarly named commands for performing the " 37.1412 -"same operations, so if you're familiar with one, it is easy to learn to use " 37.1413 -"the other. Both tools are portable to all popular operating systems." 37.1414 -msgstr "" 37.1415 - 37.1416 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1417 -#: ../en/ch01-intro.xml:456 37.1418 -msgid "" 37.1419 -"Prior to version 1.5, Subversion had no useful support for merges. At the " 37.1420 -"time of writing, its merge tracking capability is new, and known to be <ulink " 37.1421 -"url=\"http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced." 37.1422 -"html#svn.branchmerge.advanced.finalword\">complicated and buggy</ulink>." 37.1423 -msgstr "" 37.1424 - 37.1425 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1426 -#: ../en/ch01-intro.xml:462 37.1427 -msgid "" 37.1428 -"Mercurial has a substantial performance advantage over Subversion on every " 37.1429 -"revision control operation I have benchmarked. I have measured its advantage " 37.1430 -"as ranging from a factor of two to a factor of six when compared with " 37.1431 -"Subversion 1.4.3's <emphasis>ra_local</emphasis> file store, which is the " 37.1432 -"fastest access method available. In more realistic deployments involving a " 37.1433 -"network-based store, Subversion will be at a substantially larger " 37.1434 -"disadvantage. Because many Subversion commands must talk to the server and " 37.1435 -"Subversion does not have useful replication facilities, server capacity and " 37.1436 -"network bandwidth become bottlenecks for modestly large projects." 37.1437 -msgstr "" 37.1438 - 37.1439 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1440 -#: ../en/ch01-intro.xml:475 37.1441 -msgid "" 37.1442 -"Additionally, Subversion incurs substantial storage overhead to avoid network " 37.1443 -"transactions for a few common operations, such as finding modified files " 37.1444 -"(<literal>status</literal>) and displaying modifications against the current " 37.1445 -"revision (<literal>diff</literal>). As a result, a Subversion working copy " 37.1446 -"is often the same size as, or larger than, a Mercurial repository and working " 37.1447 -"directory, even though the Mercurial repository contains a complete history " 37.1448 -"of the project." 37.1449 -msgstr "" 37.1450 - 37.1451 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1452 -#: ../en/ch01-intro.xml:485 37.1453 -msgid "" 37.1454 -"Subversion is widely supported by third party tools. Mercurial currently " 37.1455 -"lags considerably in this area. This gap is closing, however, and indeed " 37.1456 -"some of Mercurial's GUI tools now outshine their Subversion equivalents. " 37.1457 -"Like Mercurial, Subversion has an excellent user manual." 37.1458 -msgstr "" 37.1459 - 37.1460 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1461 -#: ../en/ch01-intro.xml:491 37.1462 -msgid "" 37.1463 -"Because Subversion doesn't store revision history on the client, it is well " 37.1464 -"suited to managing projects that deal with lots of large, opaque binary " 37.1465 -"files. If you check in fifty revisions to an incompressible 10MB file, " 37.1466 -"Subversion's client-side space usage stays constant The space used by any " 37.1467 -"distributed SCM will grow rapidly in proportion to the number of revisions, " 37.1468 -"because the differences between each revision are large." 37.1469 -msgstr "" 37.1470 - 37.1471 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1472 -#: ../en/ch01-intro.xml:500 37.1473 -msgid "" 37.1474 -"In addition, it's often difficult or, more usually, impossible to merge " 37.1475 -"different versions of a binary file. Subversion's ability to let a user lock " 37.1476 -"a file, so that they temporarily have the exclusive right to commit changes " 37.1477 -"to it, can be a significant advantage to a project where binary files are " 37.1478 -"widely used." 37.1479 -msgstr "" 37.1480 - 37.1481 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1482 -#: ../en/ch01-intro.xml:507 37.1483 -msgid "" 37.1484 -"Mercurial can import revision history from a Subversion repository. It can " 37.1485 -"also export revision history to a Subversion repository. This makes it easy " 37.1486 -"to <quote>test the waters</quote> and use Mercurial and Subversion in " 37.1487 -"parallel before deciding to switch. History conversion is incremental, so " 37.1488 -"you can perform an initial conversion, then small additional conversions " 37.1489 -"afterwards to bring in new changes." 37.1490 -msgstr "" 37.1491 - 37.1492 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1493 -#: ../en/ch01-intro.xml:519 ../en/ch01-intro.xml:658 37.1494 -msgid "Git" 37.1495 -msgstr "" 37.1496 - 37.1497 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1498 -#: ../en/ch01-intro.xml:521 37.1499 -msgid "" 37.1500 -"Git is a distributed revision control tool that was developed for managing " 37.1501 -"the Linux kernel source tree. Like Mercurial, its early design was somewhat " 37.1502 -"influenced by Monotone." 37.1503 -msgstr "" 37.1504 - 37.1505 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1506 -#: ../en/ch01-intro.xml:526 37.1507 -msgid "" 37.1508 -"Git has a very large command set, with version 1.5.0 providing 139 individual " 37.1509 -"commands. It has something of a reputation for being difficult to learn. " 37.1510 -"Compared to Git, Mercurial has a strong focus on simplicity." 37.1511 -msgstr "" 37.1512 - 37.1513 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1514 -#: ../en/ch01-intro.xml:531 37.1515 -msgid "" 37.1516 -"In terms of performance, Git is extremely fast. In several cases, it is " 37.1517 -"faster than Mercurial, at least on Linux, while Mercurial performs better on " 37.1518 -"other operations. However, on Windows, the performance and general level of " 37.1519 -"support that Git provides is, at the time of writing, far behind that of " 37.1520 -"Mercurial." 37.1521 -msgstr "" 37.1522 - 37.1523 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1524 -#: ../en/ch01-intro.xml:538 37.1525 -msgid "" 37.1526 -"While a Mercurial repository needs no maintenance, a Git repository requires " 37.1527 -"frequent manual <quote>repacks</quote> of its metadata. Without these, " 37.1528 -"performance degrades, while space usage grows rapidly. A server that " 37.1529 -"contains many Git repositories that are not rigorously and frequently " 37.1530 -"repacked will become heavily disk-bound during backups, and there have been " 37.1531 -"instances of daily backups taking far longer than 24 hours as a result. A " 37.1532 -"freshly packed Git repository is slightly smaller than a Mercurial " 37.1533 -"repository, but an unpacked repository is several orders of magnitude larger." 37.1534 -msgstr "" 37.1535 - 37.1536 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1537 -#: ../en/ch01-intro.xml:549 37.1538 -msgid "" 37.1539 -"The core of Git is written in C. Many Git commands are implemented as shell " 37.1540 -"or Perl scripts, and the quality of these scripts varies widely. I have " 37.1541 -"encountered several instances where scripts charged along blindly in the " 37.1542 -"presence of errors that should have been fatal." 37.1543 -msgstr "" 37.1544 - 37.1545 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1546 -#: ../en/ch01-intro.xml:555 37.1547 -msgid "Mercurial can import revision history from a Git repository." 37.1548 -msgstr "" 37.1549 - 37.1550 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1551 -#: ../en/ch01-intro.xml:561 ../en/ch01-intro.xml:657 37.1552 -msgid "CVS" 37.1553 -msgstr "" 37.1554 - 37.1555 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1556 -#: ../en/ch01-intro.xml:563 37.1557 -msgid "" 37.1558 -"CVS is probably the most widely used revision control tool in the world. Due " 37.1559 -"to its age and internal untidiness, it has been only lightly maintained for " 37.1560 -"many years." 37.1561 -msgstr "" 37.1562 - 37.1563 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1564 -#: ../en/ch01-intro.xml:567 37.1565 -msgid "" 37.1566 -"It has a centralised client/server architecture. It does not group related " 37.1567 -"file changes into atomic commits, making it easy for people to <quote>break " 37.1568 -"the build</quote>: one person can successfully commit part of a change and " 37.1569 -"then be blocked by the need for a merge, causing other people to see only a " 37.1570 -"portion of the work they intended to do. This also affects how you work with " 37.1571 -"project history. If you want to see all of the modifications someone made as " 37.1572 -"part of a task, you will need to manually inspect the descriptions and " 37.1573 -"timestamps of the changes made to each file involved (if you even know what " 37.1574 -"those files were)." 37.1575 -msgstr "" 37.1576 - 37.1577 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1578 -#: ../en/ch01-intro.xml:579 37.1579 -msgid "" 37.1580 -"CVS has a muddled notion of tags and branches that I will not attempt to even " 37.1581 -"describe. It does not support renaming of files or directories well, making " 37.1582 -"it easy to corrupt a repository. It has almost no internal consistency " 37.1583 -"checking capabilities, so it is usually not even possible to tell whether or " 37.1584 -"how a repository is corrupt. I would not recommend CVS for any project, " 37.1585 -"existing or new." 37.1586 -msgstr "" 37.1587 - 37.1588 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1589 -#: ../en/ch01-intro.xml:587 37.1590 -msgid "" 37.1591 -"Mercurial can import CVS revision history. However, there are a few caveats " 37.1592 -"that apply; these are true of every other revision control tool's CVS " 37.1593 -"importer, too. Due to CVS's lack of atomic changes and unversioned " 37.1594 -"filesystem hierarchy, it is not possible to reconstruct CVS history " 37.1595 -"completely accurately; some guesswork is involved, and renames will usually " 37.1596 -"not show up. Because a lot of advanced CVS administration has to be done by " 37.1597 -"hand and is hence error-prone, it's common for CVS importers to run into " 37.1598 -"multiple problems with corrupted repositories (completely bogus revision " 37.1599 -"timestamps and files that have remained locked for over a decade are just two " 37.1600 -"of the less interesting problems I can recall from personal experience)." 37.1601 -msgstr "" 37.1602 - 37.1603 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1604 -#: ../en/ch01-intro.xml:601 37.1605 -msgid "Mercurial can import revision history from a CVS repository." 37.1606 -msgstr "" 37.1607 - 37.1608 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.1609 -#: ../en/ch01-intro.xml:607 37.1610 -msgid "Commercial tools" 37.1611 -msgstr "商业工具" 37.1612 - 37.1613 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1614 -#: ../en/ch01-intro.xml:609 37.1615 -msgid "" 37.1616 -"Perforce has a centralised client/server architecture, with no client-side " 37.1617 -"caching of any data. Unlike modern revision control tools, Perforce requires " 37.1618 -"that a user run a command to inform the server about every file they intend " 37.1619 -"to edit." 37.1620 -msgstr "" 37.1621 - 37.1622 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1623 -#: ../en/ch01-intro.xml:615 37.1624 -msgid "" 37.1625 -"The performance of Perforce is quite good for small teams, but it falls off " 37.1626 -"rapidly as the number of users grows beyond a few dozen. Modestly large " 37.1627 -"Perforce installations require the deployment of proxies to cope with the " 37.1628 -"load their users generate." 37.1629 -msgstr "" 37.1630 - 37.1631 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.1632 -#: ../en/ch01-intro.xml:624 37.1633 -msgid "Choosing a revision control tool" 37.1634 -msgstr "选择版本控制工具" 37.1635 - 37.1636 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1637 -#: ../en/ch01-intro.xml:626 37.1638 -msgid "" 37.1639 -"With the exception of CVS, all of the tools listed above have unique " 37.1640 -"strengths that suit them to particular styles of work. There is no single " 37.1641 -"revision control tool that is best in all situations." 37.1642 -msgstr "" 37.1643 - 37.1644 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1645 -#: ../en/ch01-intro.xml:631 37.1646 -msgid "" 37.1647 -"As an example, Subversion is a good choice for working with frequently edited " 37.1648 -"binary files, due to its centralised nature and support for file locking." 37.1649 -msgstr "" 37.1650 - 37.1651 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.1652 -#: ../en/ch01-intro.xml:635 37.1653 -msgid "" 37.1654 -"I personally find Mercurial's properties of simplicity, performance, and good " 37.1655 -"merge support to be a compelling combination that has served me well for " 37.1656 -"several years." 37.1657 -msgstr "" 37.1658 - 37.1659 -#. type: Content of: <book><chapter><sect1><title> 37.1660 -#: ../en/ch01-intro.xml:643 37.1661 -msgid "Switching from another tool to Mercurial" 37.1662 -msgstr "从其它工具切换到 Mercurial" 37.1663 - 37.1664 -#. type: Content of: <book><chapter><sect1><para> 37.1665 -#: ../en/ch01-intro.xml:645 37.1666 -msgid "" 37.1667 -"Mercurial is bundled with an extension named <literal role=\"hg-ext" 37.1668 -"\">convert</literal>, which can incrementally import revision history from " 37.1669 -"several other revision control tools. By <quote>incremental</quote>, I mean " 37.1670 -"that you can convert all of a project's history to date in one go, then rerun " 37.1671 -"the conversion later to obtain new changes that happened after the initial " 37.1672 -"conversion." 37.1673 -msgstr "" 37.1674 - 37.1675 -#. type: Content of: <book><chapter><sect1><para> 37.1676 -#: ../en/ch01-intro.xml:653 37.1677 -msgid "" 37.1678 -"The revision control tools supported by <literal role=\"hg-ext\">convert</" 37.1679 -"literal> are as follows:" 37.1680 -msgstr "" 37.1681 - 37.1682 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.1683 -#: ../en/ch01-intro.xml:659 37.1684 -msgid "Darcs" 37.1685 -msgstr "" 37.1686 - 37.1687 -#. type: Content of: <book><chapter><sect1><para> 37.1688 -#: ../en/ch01-intro.xml:661 37.1689 -msgid "" 37.1690 -"In addition, <literal role=\"hg-ext\">convert</literal> can export changes " 37.1691 -"from Mercurial to Subversion. This makes it possible to try Subversion and " 37.1692 -"Mercurial in parallel before committing to a switchover, without risking the " 37.1693 -"loss of any work." 37.1694 -msgstr "" 37.1695 - 37.1696 -#. type: Content of: <book><chapter><sect1><para> 37.1697 -#: ../en/ch01-intro.xml:667 37.1698 -msgid "" 37.1699 -"The <command role=\"hg-ext-conver\">convert</command> command is easy to " 37.1700 -"use. Simply point it at the path or URL of the source repository, optionally " 37.1701 -"give it the name of the destination repository, and it will start working. " 37.1702 -"After the initial conversion, just run the same command again to import new " 37.1703 -"changes." 37.1704 -msgstr "" 37.1705 - 37.1706 -#. type: Content of: <book><chapter><title> 37.1707 -#: ../en/ch02-tour-basic.xml:5 37.1708 +#: ../en/ch01-tour-basic.xml:5 37.1709 msgid "A tour of Mercurial: the basics" 37.1710 msgstr "Mercurial 教程: 基础知识" 37.1711 37.1712 #. type: Content of: <book><chapter><sect1><title> 37.1713 -#: ../en/ch02-tour-basic.xml:8 37.1714 +#: ../en/ch01-tour-basic.xml:8 37.1715 msgid "Installing Mercurial on your system" 37.1716 msgstr "安装 Mercurial" 37.1717 37.1718 #. type: Content of: <book><chapter><sect1><para> 37.1719 -#: ../en/ch02-tour-basic.xml:10 37.1720 +#: ../en/ch01-tour-basic.xml:10 37.1721 msgid "" 37.1722 "Prebuilt binary packages of Mercurial are available for every popular " 37.1723 "operating system. These make it easy to start using Mercurial on your " 37.1724 @@ -2463,12 +1540,12 @@ 37.1725 "用 Mercurial 变得很容易。" 37.1726 37.1727 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1728 -#: ../en/ch02-tour-basic.xml:15 37.1729 +#: ../en/ch01-tour-basic.xml:15 37.1730 msgid "Linux" 37.1731 msgstr "Linux" 37.1732 37.1733 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1734 -#: ../en/ch02-tour-basic.xml:17 37.1735 +#: ../en/ch01-tour-basic.xml:17 37.1736 msgid "" 37.1737 "Because each Linux distribution has its own packaging tools, policies, and " 37.1738 "rate of development, it's difficult to give a comprehensive set of " 37.1739 @@ -2481,7 +1558,7 @@ 37.1740 "使用的发行版的 Mercurial 维护者的活跃程度。" 37.1741 37.1742 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1743 -#: ../en/ch02-tour-basic.xml:24 37.1744 +#: ../en/ch01-tour-basic.xml:24 37.1745 msgid "" 37.1746 "To keep things simple, I will focus on installing Mercurial from the command " 37.1747 "line under the most popular Linux distributions. Most of these distributions " 37.1748 @@ -2493,39 +1570,39 @@ 37.1749 "Mercurial;寻找的包名称是 <literal>mercurial</literal>。" 37.1750 37.1751 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.1752 -#: ../en/ch02-tour-basic.xml:32 37.1753 +#: ../en/ch01-tour-basic.xml:32 37.1754 msgid "Debian:" 37.1755 msgstr "Debian:" 37.1756 37.1757 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.1758 -#: ../en/ch02-tour-basic.xml:34 37.1759 +#: ../en/ch01-tour-basic.xml:34 37.1760 msgid "Fedora Core:" 37.1761 msgstr "Fedora Core:" 37.1762 37.1763 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.1764 -#: ../en/ch02-tour-basic.xml:36 37.1765 +#: ../en/ch01-tour-basic.xml:36 37.1766 msgid "Gentoo:" 37.1767 msgstr "Gentoo:" 37.1768 37.1769 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.1770 -#: ../en/ch02-tour-basic.xml:38 37.1771 +#: ../en/ch01-tour-basic.xml:38 37.1772 msgid "OpenSUSE:" 37.1773 msgstr "OpenSUSE:" 37.1774 37.1775 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.1776 -#: ../en/ch02-tour-basic.xml:40 37.1777 +#: ../en/ch01-tour-basic.xml:40 37.1778 msgid "" 37.1779 "Ubuntu: Ubuntu's Mercurial package is based on Debian's. To install it, run " 37.1780 "the following command." 37.1781 msgstr "Ubuntu: Ubuntu 的 Mercurial 包基于 Debian。安装时,使用如下命令:" 37.1782 37.1783 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1784 -#: ../en/ch02-tour-basic.xml:48 37.1785 +#: ../en/ch01-tour-basic.xml:48 37.1786 msgid "Solaris" 37.1787 msgstr "Solaris" 37.1788 37.1789 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1790 -#: ../en/ch02-tour-basic.xml:50 37.1791 +#: ../en/ch01-tour-basic.xml:50 37.1792 msgid "" 37.1793 "SunFreeWare, at <ulink url=\"http://www.sunfreeware.com\">http://www." 37.1794 "sunfreeware.com</ulink>, is a good source for a large number of pre-built " 37.1795 @@ -2537,12 +1614,12 @@ 37.1796 "和 64 位包,包含 Mercurial 的当前版本。" 37.1797 37.1798 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1799 -#: ../en/ch02-tour-basic.xml:58 37.1800 +#: ../en/ch01-tour-basic.xml:58 37.1801 msgid "Mac OS X" 37.1802 msgstr "Mac OS X" 37.1803 37.1804 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1805 -#: ../en/ch02-tour-basic.xml:60 37.1806 +#: ../en/ch01-tour-basic.xml:60 37.1807 msgid "" 37.1808 "Lee Cantey publishes an installer of Mercurial for Mac OS X at <ulink url=" 37.1809 "\"http://mercurial.berkwood.com\">http://mercurial.berkwood.com</ulink>. " 37.1810 @@ -2553,7 +1630,7 @@ 37.1811 msgstr "" 37.1812 37.1813 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1814 -#: ../en/ch02-tour-basic.xml:69 37.1815 +#: ../en/ch01-tour-basic.xml:69 37.1816 msgid "" 37.1817 "It's also possible to install Mercurial using Fink or MacPorts, two popular " 37.1818 "free package managers for Mac OS X. If you have Fink, use <command>sudo apt-" 37.1819 @@ -2562,12 +1639,12 @@ 37.1820 msgstr "" 37.1821 37.1822 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1823 -#: ../en/ch02-tour-basic.xml:77 37.1824 +#: ../en/ch01-tour-basic.xml:77 37.1825 msgid "Windows" 37.1826 msgstr "" 37.1827 37.1828 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1829 -#: ../en/ch02-tour-basic.xml:79 37.1830 +#: ../en/ch01-tour-basic.xml:79 37.1831 msgid "" 37.1832 "Lee Cantey publishes an installer of Mercurial for Windows at <ulink url=" 37.1833 "\"http://mercurial.berkwood.com\">http://mercurial.berkwood.com</ulink>. " 37.1834 @@ -2575,7 +1652,7 @@ 37.1835 msgstr "" 37.1836 37.1837 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.1838 -#: ../en/ch02-tour-basic.xml:86 37.1839 +#: ../en/ch01-tour-basic.xml:86 37.1840 msgid "" 37.1841 "The Windows version of Mercurial does not automatically convert line endings " 37.1842 "between Windows and Unix styles. If you want to share work with Unix users, " 37.1843 @@ -2583,12 +1660,12 @@ 37.1844 msgstr "" 37.1845 37.1846 #. type: Content of: <book><chapter><sect1><title> 37.1847 -#: ../en/ch02-tour-basic.xml:96 37.1848 +#: ../en/ch01-tour-basic.xml:96 37.1849 msgid "Getting started" 37.1850 msgstr "开始" 37.1851 37.1852 #. type: Content of: <book><chapter><sect1><para> 37.1853 -#: ../en/ch02-tour-basic.xml:98 37.1854 +#: ../en/ch01-tour-basic.xml:98 37.1855 msgid "" 37.1856 "To begin, we'll use the <command role=\"hg-cmd\">hg version</command> command " 37.1857 "to find out whether Mercurial is actually installed properly. The actual " 37.1858 @@ -2597,12 +1674,12 @@ 37.1859 msgstr "" 37.1860 37.1861 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1862 -#: ../en/ch02-tour-basic.xml:107 37.1863 +#: ../en/ch01-tour-basic.xml:107 37.1864 msgid "Built-in help" 37.1865 msgstr "内置帮助" 37.1866 37.1867 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1868 -#: ../en/ch02-tour-basic.xml:109 37.1869 +#: ../en/ch01-tour-basic.xml:109 37.1870 msgid "" 37.1871 "Mercurial provides a built-in help system. This is invaluable for those " 37.1872 "times when you find yourself stuck trying to remember how to run a command. " 37.1873 @@ -2613,7 +1690,7 @@ 37.1874 msgstr "" 37.1875 37.1876 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1877 -#: ../en/ch02-tour-basic.xml:120 37.1878 +#: ../en/ch01-tour-basic.xml:120 37.1879 msgid "" 37.1880 "For a more impressive level of detail (which you won't usually need) run " 37.1881 "<command role=\"hg-cmd\">hg help <option role=\"hg-opt-global\">-v</option></" 37.1882 @@ -2623,12 +1700,12 @@ 37.1883 msgstr "" 37.1884 37.1885 #. type: Content of: <book><chapter><sect1><title> 37.1886 -#: ../en/ch02-tour-basic.xml:131 37.1887 +#: ../en/ch01-tour-basic.xml:131 37.1888 msgid "Working with a repository" 37.1889 msgstr "使用版本库" 37.1890 37.1891 #. type: Content of: <book><chapter><sect1><para> 37.1892 -#: ../en/ch02-tour-basic.xml:133 37.1893 +#: ../en/ch01-tour-basic.xml:133 37.1894 msgid "" 37.1895 "In Mercurial, everything happens inside a <emphasis>repository</emphasis>. " 37.1896 "The repository for a project contains all of the files that <quote>belong to</" 37.1897 @@ -2636,7 +1713,7 @@ 37.1898 msgstr "" 37.1899 37.1900 #. type: Content of: <book><chapter><sect1><para> 37.1901 -#: ../en/ch02-tour-basic.xml:139 37.1902 +#: ../en/ch01-tour-basic.xml:139 37.1903 msgid "" 37.1904 "There's nothing particularly magical about a repository; it is simply a " 37.1905 "directory tree in your filesystem that Mercurial treats as special. You can " 37.1906 @@ -2645,12 +1722,12 @@ 37.1907 msgstr "" 37.1908 37.1909 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1910 -#: ../en/ch02-tour-basic.xml:146 37.1911 +#: ../en/ch01-tour-basic.xml:146 37.1912 msgid "Making a local copy of a repository" 37.1913 msgstr "创建版本库的工作副本" 37.1914 37.1915 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1916 -#: ../en/ch02-tour-basic.xml:148 37.1917 +#: ../en/ch01-tour-basic.xml:148 37.1918 msgid "" 37.1919 "<emphasis>Copying</emphasis> a repository is just a little bit special. " 37.1920 "While you could use a normal file copying command to make a copy of a " 37.1921 @@ -2660,21 +1737,21 @@ 37.1922 msgstr "" 37.1923 37.1924 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1925 -#: ../en/ch02-tour-basic.xml:157 37.1926 +#: ../en/ch01-tour-basic.xml:157 37.1927 msgid "" 37.1928 "If our clone succeeded, we should now have a local directory called <filename " 37.1929 "class=\"directory\">hello</filename>. This directory will contain some files." 37.1930 msgstr "" 37.1931 37.1932 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1933 -#: ../en/ch02-tour-basic.xml:163 37.1934 +#: ../en/ch01-tour-basic.xml:163 37.1935 msgid "" 37.1936 "These files have the same contents and history in our repository as they do " 37.1937 "in the repository we cloned." 37.1938 msgstr "" 37.1939 37.1940 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1941 -#: ../en/ch02-tour-basic.xml:166 37.1942 +#: ../en/ch01-tour-basic.xml:166 37.1943 msgid "" 37.1944 "Every Mercurial repository is complete, self-contained, and independent. It " 37.1945 "contains its own private copy of a project's files and history. A cloned " 37.1946 @@ -2684,7 +1761,7 @@ 37.1947 msgstr "" 37.1948 37.1949 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1950 -#: ../en/ch02-tour-basic.xml:173 37.1951 +#: ../en/ch01-tour-basic.xml:173 37.1952 msgid "" 37.1953 "What this means for now is that we're free to experiment with our repository, " 37.1954 "safe in the knowledge that it's a private <quote>sandbox</quote> that won't " 37.1955 @@ -2692,12 +1769,12 @@ 37.1956 msgstr "" 37.1957 37.1958 #. type: Content of: <book><chapter><sect1><sect2><title> 37.1959 -#: ../en/ch02-tour-basic.xml:179 37.1960 +#: ../en/ch01-tour-basic.xml:179 37.1961 msgid "What's in a repository?" 37.1962 msgstr "什么是版本库?" 37.1963 37.1964 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1965 -#: ../en/ch02-tour-basic.xml:181 37.1966 +#: ../en/ch01-tour-basic.xml:181 37.1967 msgid "" 37.1968 "When we take a more detailed look inside a repository, we can see that it " 37.1969 "contains a directory named <filename class=\"directory\">.hg</filename>. " 37.1970 @@ -2705,7 +1782,7 @@ 37.1971 msgstr "" 37.1972 37.1973 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1974 -#: ../en/ch02-tour-basic.xml:188 37.1975 +#: ../en/ch01-tour-basic.xml:188 37.1976 msgid "" 37.1977 "The contents of the <filename class=\"directory\">.hg</filename> directory " 37.1978 "and its subdirectories are private to Mercurial. Every other file and " 37.1979 @@ -2713,7 +1790,7 @@ 37.1980 msgstr "" 37.1981 37.1982 #. type: Content of: <book><chapter><sect1><sect2><para> 37.1983 -#: ../en/ch02-tour-basic.xml:194 37.1984 +#: ../en/ch01-tour-basic.xml:194 37.1985 msgid "" 37.1986 "To introduce a little terminology, the <filename class=\"directory\">.hg</" 37.1987 "filename> directory is the <quote>real</quote> repository, and all of the " 37.1988 @@ -2726,12 +1803,12 @@ 37.1989 msgstr "" 37.1990 37.1991 #. type: Content of: <book><chapter><sect1><title> 37.1992 -#: ../en/ch02-tour-basic.xml:209 37.1993 +#: ../en/ch01-tour-basic.xml:209 37.1994 msgid "A tour through history" 37.1995 msgstr "回溯历史" 37.1996 37.1997 #. type: Content of: <book><chapter><sect1><para> 37.1998 -#: ../en/ch02-tour-basic.xml:211 37.1999 +#: ../en/ch01-tour-basic.xml:211 37.2000 msgid "" 37.2001 "One of the first things we might want to do with a new, unfamiliar repository " 37.2002 "is understand its history. The <command role=\"hg-cmd\">hg log</command> " 37.2003 @@ -2739,7 +1816,7 @@ 37.2004 msgstr "" 37.2005 37.2006 #. type: Content of: <book><chapter><sect1><para> 37.2007 -#: ../en/ch02-tour-basic.xml:218 37.2008 +#: ../en/ch01-tour-basic.xml:218 37.2009 msgid "" 37.2010 "By default, this command prints a brief paragraph of output for each change " 37.2011 "to the project that was recorded. In Mercurial terminology, we call each of " 37.2012 @@ -2748,14 +1825,14 @@ 37.2013 msgstr "" 37.2014 37.2015 #. type: Content of: <book><chapter><sect1><para> 37.2016 -#: ../en/ch02-tour-basic.xml:224 37.2017 +#: ../en/ch01-tour-basic.xml:224 37.2018 msgid "" 37.2019 "The fields in a record of output from <command role=\"hg-cmd\">hg log</" 37.2020 "command> are as follows." 37.2021 msgstr "" 37.2022 37.2023 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2024 -#: ../en/ch02-tour-basic.xml:227 37.2025 +#: ../en/ch01-tour-basic.xml:227 37.2026 msgid "" 37.2027 "<literal>changeset</literal>: This field has the format of a number, followed " 37.2028 "by a colon, followed by a hexadecimal string. These are " 37.2029 @@ -2765,7 +1842,7 @@ 37.2030 msgstr "" 37.2031 37.2032 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2033 -#: ../en/ch02-tour-basic.xml:233 37.2034 +#: ../en/ch01-tour-basic.xml:233 37.2035 msgid "" 37.2036 "<literal>user</literal>: The identity of the person who created the " 37.2037 "changeset. This is a free-form field, but it most often contains a person's " 37.2038 @@ -2773,7 +1850,7 @@ 37.2039 msgstr "" 37.2040 37.2041 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2042 -#: ../en/ch02-tour-basic.xml:237 37.2043 +#: ../en/ch01-tour-basic.xml:237 37.2044 msgid "" 37.2045 "<literal>date</literal>: The date and time on which the changeset was " 37.2046 "created, and the timezone in which it was created. (The date and time are " 37.2047 @@ -2782,21 +1859,21 @@ 37.2048 msgstr "" 37.2049 37.2050 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2051 -#: ../en/ch02-tour-basic.xml:242 37.2052 +#: ../en/ch01-tour-basic.xml:242 37.2053 msgid "" 37.2054 "<literal>summary</literal>: The first line of the text message that the " 37.2055 "creator of the changeset entered to describe the changeset." 37.2056 msgstr "" 37.2057 37.2058 #. type: Content of: <book><chapter><sect1><para> 37.2059 -#: ../en/ch02-tour-basic.xml:245 37.2060 +#: ../en/ch01-tour-basic.xml:245 37.2061 msgid "" 37.2062 "The default output printed by <command role=\"hg-cmd\">hg log</command> is " 37.2063 "purely a summary; it is missing a lot of detail." 37.2064 msgstr "" 37.2065 37.2066 #. type: Content of: <book><chapter><sect1><para> 37.2067 -#: ../en/ch02-tour-basic.xml:249 37.2068 +#: ../en/ch01-tour-basic.xml:249 37.2069 msgid "" 37.2070 "Figure <xref endterm=\"fig.tour-basic.history.caption\" linkend=\"fig.tour-" 37.2071 "basic.history\"/> provides a graphical representation of the history of the " 37.2072 @@ -2807,39 +1884,39 @@ 37.2073 msgstr "" 37.2074 37.2075 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject> 37.2076 -#: ../en/ch02-tour-basic.xml:260 37.2077 +#: ../en/ch01-tour-basic.xml:260 37.2078 msgid "" 37.2079 "<imageobject><imagedata fileref=\"images/tour-history.png\"/></imageobject>" 37.2080 msgstr "" 37.2081 37.2082 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><textobject><phrase> 37.2083 -#: ../en/ch02-tour-basic.xml:261 ../en/ch03-tour-merge.xml:48 37.2084 -#: ../en/ch03-tour-merge.xml:78 ../en/ch03-tour-merge.xml:126 37.2085 -#: ../en/ch03-tour-merge.xml:182 ../en/ch03-tour-merge.xml:254 37.2086 -#: ../en/ch04-concepts.xml:56 ../en/ch04-concepts.xml:108 37.2087 -#: ../en/ch04-concepts.xml:194 ../en/ch04-concepts.xml:301 37.2088 -#: ../en/ch04-concepts.xml:353 ../en/ch04-concepts.xml:370 37.2089 -#: ../en/ch04-concepts.xml:414 ../en/ch04-concepts.xml:436 37.2090 -#: ../en/ch04-concepts.xml:480 ../en/ch06-collab.xml:277 37.2091 -#: ../en/ch09-undo.xml:366 ../en/ch09-undo.xml:417 ../en/ch09-undo.xml:485 37.2092 -#: ../en/ch09-undo.xml:527 ../en/ch12-mq.xml:409 37.2093 +#: ../en/ch01-tour-basic.xml:261 ../en/ch02-tour-merge.xml:48 37.2094 +#: ../en/ch02-tour-merge.xml:78 ../en/ch02-tour-merge.xml:126 37.2095 +#: ../en/ch02-tour-merge.xml:182 ../en/ch02-tour-merge.xml:254 37.2096 +#: ../en/ch03-concepts.xml:56 ../en/ch03-concepts.xml:108 37.2097 +#: ../en/ch03-concepts.xml:194 ../en/ch03-concepts.xml:301 37.2098 +#: ../en/ch03-concepts.xml:353 ../en/ch03-concepts.xml:370 37.2099 +#: ../en/ch03-concepts.xml:414 ../en/ch03-concepts.xml:436 37.2100 +#: ../en/ch03-concepts.xml:480 ../en/ch05-collab.xml:277 37.2101 +#: ../en/ch08-undo.xml:366 ../en/ch08-undo.xml:417 ../en/ch08-undo.xml:485 37.2102 +#: ../en/ch08-undo.xml:527 ../en/ch11-mq.xml:410 37.2103 msgid "XXX add text" 37.2104 msgstr "" 37.2105 37.2106 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject><caption><para> 37.2107 -#: ../en/ch02-tour-basic.xml:262 37.2108 +#: ../en/ch01-tour-basic.xml:262 37.2109 msgid "" 37.2110 "Graphical history of the <filename class=\"directory\">hello</filename> " 37.2111 "repository" 37.2112 msgstr "" 37.2113 37.2114 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2115 -#: ../en/ch02-tour-basic.xml:269 37.2116 +#: ../en/ch01-tour-basic.xml:269 37.2117 msgid "Changesets, revisions, and talking to other people" 37.2118 msgstr "改变集,版本,与其它用户交互" 37.2119 37.2120 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2121 -#: ../en/ch02-tour-basic.xml:272 37.2122 +#: ../en/ch01-tour-basic.xml:272 37.2123 msgid "" 37.2124 "As English is a notoriously sloppy language, and computer science has a " 37.2125 "hallowed history of terminological confusion (why use one term when four will " 37.2126 @@ -2851,7 +1928,7 @@ 37.2127 msgstr "" 37.2128 37.2129 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2130 -#: ../en/ch02-tour-basic.xml:282 37.2131 +#: ../en/ch01-tour-basic.xml:282 37.2132 msgid "" 37.2133 "While it doesn't matter what <emphasis>word</emphasis> you use to refer to " 37.2134 "the concept of <quote>a changeset</quote>, the <emphasis>identifier</" 37.2135 @@ -2862,13 +1939,13 @@ 37.2136 msgstr "" 37.2137 37.2138 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.2139 -#: ../en/ch02-tour-basic.xml:291 37.2140 +#: ../en/ch01-tour-basic.xml:291 37.2141 msgid "" 37.2142 "The revision number is <emphasis>only valid in that repository</emphasis>," 37.2143 msgstr "" 37.2144 37.2145 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.2146 -#: ../en/ch02-tour-basic.xml:293 37.2147 +#: ../en/ch01-tour-basic.xml:293 37.2148 msgid "" 37.2149 "while the hex string is the <emphasis>permanent, unchanging identifier</" 37.2150 "emphasis> that will always identify that exact changeset in <emphasis>every</" 37.2151 @@ -2876,7 +1953,7 @@ 37.2152 msgstr "" 37.2153 37.2154 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2155 -#: ../en/ch02-tour-basic.xml:298 37.2156 +#: ../en/ch01-tour-basic.xml:298 37.2157 msgid "" 37.2158 "This distinction is important. If you send someone an email talking about " 37.2159 "<quote>revision 33</quote>, there's a high likelihood that their revision 33 " 37.2160 @@ -2888,7 +1965,7 @@ 37.2161 msgstr "" 37.2162 37.2163 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2164 -#: ../en/ch02-tour-basic.xml:308 37.2165 +#: ../en/ch01-tour-basic.xml:308 37.2166 msgid "" 37.2167 "Mercurial uses revision numbers purely as a convenient shorthand. If you " 37.2168 "need to discuss a changeset with someone, or make a record of a changeset for " 37.2169 @@ -2897,12 +1974,12 @@ 37.2170 msgstr "" 37.2171 37.2172 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2173 -#: ../en/ch02-tour-basic.xml:316 37.2174 +#: ../en/ch01-tour-basic.xml:316 37.2175 msgid "Viewing specific revisions" 37.2176 msgstr "察看指定版本" 37.2177 37.2178 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2179 -#: ../en/ch02-tour-basic.xml:318 37.2180 +#: ../en/ch01-tour-basic.xml:318 37.2181 msgid "" 37.2182 "To narrow the output of <command role=\"hg-cmd\">hg log</command> down to a " 37.2183 "single revision, use the <option role=\"hg-opt-log\">-r</option> (or <option " 37.2184 @@ -2912,7 +1989,7 @@ 37.2185 msgstr "" 37.2186 37.2187 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2188 -#: ../en/ch02-tour-basic.xml:327 37.2189 +#: ../en/ch01-tour-basic.xml:327 37.2190 msgid "" 37.2191 "If you want to see the history of several revisions without having to list " 37.2192 "each one, you can use <emphasis>range notation</emphasis>; this lets you " 37.2193 @@ -2921,7 +1998,7 @@ 37.2194 msgstr "" 37.2195 37.2196 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2197 -#: ../en/ch02-tour-basic.xml:335 37.2198 +#: ../en/ch01-tour-basic.xml:335 37.2199 msgid "" 37.2200 "Mercurial also honours the order in which you specify revisions, so <command " 37.2201 "role=\"hg-cmd\">hg log -r 2:4</command> prints 2, 3, and 4. while <command " 37.2202 @@ -2929,12 +2006,12 @@ 37.2203 msgstr "" 37.2204 37.2205 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2206 -#: ../en/ch02-tour-basic.xml:342 37.2207 +#: ../en/ch01-tour-basic.xml:342 37.2208 msgid "More detailed information" 37.2209 msgstr "更详细的信息" 37.2210 37.2211 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2212 -#: ../en/ch02-tour-basic.xml:344 37.2213 +#: ../en/ch01-tour-basic.xml:344 37.2214 msgid "" 37.2215 "While the summary information printed by <command role=\"hg-cmd\">hg log</" 37.2216 "command> is useful if you already know what you're looking for, you may need " 37.2217 @@ -2946,7 +2023,7 @@ 37.2218 msgstr "" 37.2219 37.2220 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2221 -#: ../en/ch02-tour-basic.xml:356 37.2222 +#: ../en/ch01-tour-basic.xml:356 37.2223 msgid "" 37.2224 "If you want to see both the description and content of a change, add the " 37.2225 "<option role=\"hg-opt-log\">-p</option> (or <option role=\"hg-opt-log\">--" 37.2226 @@ -2956,12 +2033,12 @@ 37.2227 msgstr "" 37.2228 37.2229 #. type: Content of: <book><chapter><sect1><title> 37.2230 -#: ../en/ch02-tour-basic.xml:369 37.2231 +#: ../en/ch01-tour-basic.xml:369 37.2232 msgid "All about command options" 37.2233 msgstr "命令选项" 37.2234 37.2235 #. type: Content of: <book><chapter><sect1><para> 37.2236 -#: ../en/ch02-tour-basic.xml:371 37.2237 +#: ../en/ch01-tour-basic.xml:371 37.2238 msgid "" 37.2239 "Let's take a brief break from exploring Mercurial commands to discuss a " 37.2240 "pattern in the way that they work; you may find this useful to keep in mind " 37.2241 @@ -2969,7 +2046,7 @@ 37.2242 msgstr "" 37.2243 37.2244 #. type: Content of: <book><chapter><sect1><para> 37.2245 -#: ../en/ch02-tour-basic.xml:375 37.2246 +#: ../en/ch01-tour-basic.xml:375 37.2247 msgid "" 37.2248 "Mercurial has a consistent and straightforward approach to dealing with the " 37.2249 "options that you can pass to commands. It follows the conventions for " 37.2250 @@ -2977,7 +2054,7 @@ 37.2251 msgstr "" 37.2252 37.2253 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2254 -#: ../en/ch02-tour-basic.xml:380 37.2255 +#: ../en/ch01-tour-basic.xml:380 37.2256 msgid "" 37.2257 "Every option has a long name. For example, as we've already seen, the " 37.2258 "<command role=\"hg-cmd\">hg log</command> command accepts a <option role=\"hg-" 37.2259 @@ -2985,7 +2062,7 @@ 37.2260 msgstr "" 37.2261 37.2262 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2263 -#: ../en/ch02-tour-basic.xml:384 37.2264 +#: ../en/ch01-tour-basic.xml:384 37.2265 msgid "" 37.2266 "Most options have short names, too. Instead of <option role=\"hg-opt-log\">--" 37.2267 "rev</option>, we can use <option role=\"hg-opt-log\">-r</option>. (The " 37.2268 @@ -2994,7 +2071,7 @@ 37.2269 msgstr "" 37.2270 37.2271 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2272 -#: ../en/ch02-tour-basic.xml:389 37.2273 +#: ../en/ch01-tour-basic.xml:389 37.2274 msgid "" 37.2275 "Long options start with two dashes (e.g. <option role=\"hg-opt-log\">--rev</" 37.2276 "option>), while short options start with one (e.g. <option role=\"hg-opt-log" 37.2277 @@ -3002,7 +2079,7 @@ 37.2278 msgstr "" 37.2279 37.2280 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2281 -#: ../en/ch02-tour-basic.xml:393 37.2282 +#: ../en/ch01-tour-basic.xml:393 37.2283 msgid "" 37.2284 "Option naming and usage is consistent across commands. For example, every " 37.2285 "command that lets you specify a changeset ID or revision number accepts both " 37.2286 @@ -3011,7 +2088,7 @@ 37.2287 msgstr "" 37.2288 37.2289 #. type: Content of: <book><chapter><sect1><para> 37.2290 -#: ../en/ch02-tour-basic.xml:399 37.2291 +#: ../en/ch01-tour-basic.xml:399 37.2292 msgid "" 37.2293 "In the examples throughout this book, I use short options instead of long. " 37.2294 "This just reflects my own preference, so don't read anything significant into " 37.2295 @@ -3019,7 +2096,7 @@ 37.2296 msgstr "" 37.2297 37.2298 #. type: Content of: <book><chapter><sect1><para> 37.2299 -#: ../en/ch02-tour-basic.xml:403 37.2300 +#: ../en/ch01-tour-basic.xml:403 37.2301 msgid "" 37.2302 "Most commands that print output of some kind will print more output when " 37.2303 "passed a <option role=\"hg-opt-global\">-v</option> (or <option role=\"hg-opt-" 37.2304 @@ -3028,19 +2105,19 @@ 37.2305 msgstr "" 37.2306 37.2307 #. type: Content of: <book><chapter><sect1><title> 37.2308 -#: ../en/ch02-tour-basic.xml:411 37.2309 +#: ../en/ch01-tour-basic.xml:411 37.2310 msgid "Making and reviewing changes" 37.2311 msgstr "创建和复审修改" 37.2312 37.2313 #. type: Content of: <book><chapter><sect1><para> 37.2314 -#: ../en/ch02-tour-basic.xml:413 37.2315 +#: ../en/ch01-tour-basic.xml:413 37.2316 msgid "" 37.2317 "Now that we have a grasp of viewing history in Mercurial, let's take a look " 37.2318 "at making some changes and examining them." 37.2319 msgstr "" 37.2320 37.2321 #. type: Content of: <book><chapter><sect1><para> 37.2322 -#: ../en/ch02-tour-basic.xml:417 37.2323 +#: ../en/ch01-tour-basic.xml:417 37.2324 msgid "" 37.2325 "The first thing we'll do is isolate our experiment in a repository of its " 37.2326 "own. We use the <command role=\"hg-cmd\">hg clone</command> command, but we " 37.2327 @@ -3051,7 +2128,7 @@ 37.2328 msgstr "" 37.2329 37.2330 #. type: Content of: <book><chapter><sect1><para> 37.2331 -#: ../en/ch02-tour-basic.xml:427 37.2332 +#: ../en/ch01-tour-basic.xml:427 37.2333 msgid "" 37.2334 "As an aside, it's often good practice to keep a <quote>pristine</quote> copy " 37.2335 "of a remote repository around, which you can then make temporary clones of to " 37.2336 @@ -3063,7 +2140,7 @@ 37.2337 msgstr "" 37.2338 37.2339 #. type: Content of: <book><chapter><sect1><para> 37.2340 -#: ../en/ch02-tour-basic.xml:436 37.2341 +#: ../en/ch01-tour-basic.xml:436 37.2342 msgid "" 37.2343 "In our <filename class=\"directory\">my-hello</filename> repository, we have " 37.2344 "a file <filename>hello.c</filename> that contains the classic <quote>hello, " 37.2345 @@ -3076,14 +2153,14 @@ 37.2346 msgstr "" 37.2347 37.2348 #. type: Content of: <book><chapter><sect1><para> 37.2349 -#: ../en/ch02-tour-basic.xml:449 37.2350 +#: ../en/ch01-tour-basic.xml:449 37.2351 msgid "" 37.2352 "Mercurial's <command role=\"hg-cmd\">hg status</command> command will tell us " 37.2353 "what Mercurial knows about the files in the repository." 37.2354 msgstr "" 37.2355 37.2356 #. type: Content of: <book><chapter><sect1><para> 37.2357 -#: ../en/ch02-tour-basic.xml:455 37.2358 +#: ../en/ch01-tour-basic.xml:455 37.2359 msgid "" 37.2360 "The <command role=\"hg-cmd\">hg status</command> command prints no output for " 37.2361 "some files, but a line starting with <quote><literal>M</literal></quote> for " 37.2362 @@ -3093,7 +2170,7 @@ 37.2363 msgstr "" 37.2364 37.2365 #. type: Content of: <book><chapter><sect1><para> 37.2366 -#: ../en/ch02-tour-basic.xml:462 37.2367 +#: ../en/ch01-tour-basic.xml:462 37.2368 msgid "" 37.2369 "The <quote><literal>M</literal></quote> indicates that Mercurial has noticed " 37.2370 "that we modified <filename>hello.c</filename>. We didn't need to " 37.2371 @@ -3103,7 +2180,7 @@ 37.2372 msgstr "" 37.2373 37.2374 #. type: Content of: <book><chapter><sect1><para> 37.2375 -#: ../en/ch02-tour-basic.xml:470 37.2376 +#: ../en/ch01-tour-basic.xml:470 37.2377 msgid "" 37.2378 "It's a little bit helpful to know that we've modified <filename>hello.c</" 37.2379 "filename>, but we might prefer to know exactly <emphasis>what</emphasis> " 37.2380 @@ -3112,12 +2189,12 @@ 37.2381 msgstr "" 37.2382 37.2383 #. type: Content of: <book><chapter><sect1><title> 37.2384 -#: ../en/ch02-tour-basic.xml:480 37.2385 +#: ../en/ch01-tour-basic.xml:480 37.2386 msgid "Recording changes in a new changeset" 37.2387 msgstr "在新修改集中记录修改" 37.2388 37.2389 #. type: Content of: <book><chapter><sect1><para> 37.2390 -#: ../en/ch02-tour-basic.xml:482 37.2391 +#: ../en/ch01-tour-basic.xml:482 37.2392 msgid "" 37.2393 "We can modify files, build and test our changes, and use <command role=\"hg-" 37.2394 "cmd\">hg status</command> and <command role=\"hg-cmd\">hg diff</command> to " 37.2395 @@ -3126,7 +2203,7 @@ 37.2396 msgstr "" 37.2397 37.2398 #. type: Content of: <book><chapter><sect1><para> 37.2399 -#: ../en/ch02-tour-basic.xml:489 37.2400 +#: ../en/ch01-tour-basic.xml:489 37.2401 msgid "" 37.2402 "The <command role=\"hg-cmd\">hg commit</command> command lets us create a new " 37.2403 "changeset; we'll usually refer to this as <quote>making a commit</quote> or " 37.2404 @@ -3134,12 +2211,12 @@ 37.2405 msgstr "" 37.2406 37.2407 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2408 -#: ../en/ch02-tour-basic.xml:495 37.2409 +#: ../en/ch01-tour-basic.xml:495 37.2410 msgid "Setting up a username" 37.2411 msgstr "配置用户名称" 37.2412 37.2413 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2414 -#: ../en/ch02-tour-basic.xml:497 37.2415 +#: ../en/ch01-tour-basic.xml:497 37.2416 msgid "" 37.2417 "When you try to run <command role=\"hg-cmd\">hg commit</command> for the " 37.2418 "first time, it is not guaranteed to succeed. Mercurial records your name and " 37.2419 @@ -3150,7 +2227,7 @@ 37.2420 msgstr "" 37.2421 37.2422 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.2423 -#: ../en/ch02-tour-basic.xml:506 37.2424 +#: ../en/ch01-tour-basic.xml:506 37.2425 msgid "" 37.2426 "If you specify a <option role=\"hg-opt-commit\">-u</option> option to the " 37.2427 "<command role=\"hg-cmd\">hg commit</command> command on the command line, " 37.2428 @@ -3158,14 +2235,14 @@ 37.2429 msgstr "" 37.2430 37.2431 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.2432 -#: ../en/ch02-tour-basic.xml:511 37.2433 +#: ../en/ch01-tour-basic.xml:511 37.2434 msgid "" 37.2435 "If you have set the <envar>HGUSER</envar> environment variable, this is " 37.2436 "checked next." 37.2437 msgstr "" 37.2438 37.2439 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.2440 -#: ../en/ch02-tour-basic.xml:514 37.2441 +#: ../en/ch01-tour-basic.xml:514 37.2442 msgid "" 37.2443 "If you create a file in your home directory called <filename role=\"special" 37.2444 "\">.hgrc</filename>, with a <envar role=\"rc-item-ui\">username</envar> " 37.2445 @@ -3174,14 +2251,14 @@ 37.2446 msgstr "" 37.2447 37.2448 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.2449 -#: ../en/ch02-tour-basic.xml:521 37.2450 +#: ../en/ch01-tour-basic.xml:521 37.2451 msgid "" 37.2452 "If you have set the <envar>EMAIL</envar> environment variable, this will be " 37.2453 "used next." 37.2454 msgstr "" 37.2455 37.2456 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.2457 -#: ../en/ch02-tour-basic.xml:524 37.2458 +#: ../en/ch01-tour-basic.xml:524 37.2459 msgid "" 37.2460 "Mercurial will query your system to find out your local user name and host " 37.2461 "name, and construct a username from these components. Since this often " 37.2462 @@ -3190,7 +2267,7 @@ 37.2463 msgstr "" 37.2464 37.2465 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2466 -#: ../en/ch02-tour-basic.xml:531 37.2467 +#: ../en/ch01-tour-basic.xml:531 37.2468 msgid "" 37.2469 "If all of these mechanisms fail, Mercurial will fail, printing an error " 37.2470 "message. In this case, it will not let you commit until you set up a " 37.2471 @@ -3198,7 +2275,7 @@ 37.2472 msgstr "" 37.2473 37.2474 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2475 -#: ../en/ch02-tour-basic.xml:535 37.2476 +#: ../en/ch01-tour-basic.xml:535 37.2477 msgid "" 37.2478 "You should think of the <envar>HGUSER</envar> environment variable and the " 37.2479 "<option role=\"hg-opt-commit\">-u</option> option to the <command role=\"hg-" 37.2480 @@ -3209,12 +2286,12 @@ 37.2481 msgstr "" 37.2482 37.2483 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.2484 -#: ../en/ch02-tour-basic.xml:544 37.2485 +#: ../en/ch01-tour-basic.xml:544 37.2486 msgid "Creating a Mercurial configuration file" 37.2487 msgstr "创建 Mercurial 的配置文件" 37.2488 37.2489 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.2490 -#: ../en/ch02-tour-basic.xml:546 37.2491 +#: ../en/ch01-tour-basic.xml:546 37.2492 msgid "" 37.2493 "To set a user name, use your favourite editor to create a file called " 37.2494 "<filename role=\"special\">.hgrc</filename> in your home directory. " 37.2495 @@ -3224,7 +2301,7 @@ 37.2496 msgstr "" 37.2497 37.2498 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.2499 -#: ../en/ch02-tour-basic.xml:557 37.2500 +#: ../en/ch01-tour-basic.xml:558 37.2501 msgid "" 37.2502 "The <quote><literal>[ui]</literal></quote> line begins a <emphasis>section</" 37.2503 "emphasis> of the config file, so you can read the <quote><literal>username " 37.2504 @@ -3236,12 +2313,12 @@ 37.2505 msgstr "" 37.2506 37.2507 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.2508 -#: ../en/ch02-tour-basic.xml:570 37.2509 +#: ../en/ch01-tour-basic.xml:571 37.2510 msgid "Choosing a user name" 37.2511 msgstr "选择用户名称" 37.2512 37.2513 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.2514 -#: ../en/ch02-tour-basic.xml:572 37.2515 +#: ../en/ch01-tour-basic.xml:573 37.2516 msgid "" 37.2517 "You can use any text you like as the value of the <literal>username</literal> " 37.2518 "config item, since this information is for reading by other people, but for " 37.2519 @@ -3250,7 +2327,7 @@ 37.2520 msgstr "" 37.2521 37.2522 #. type: Content of: <book><chapter><sect1><sect2><sect3><note><para> 37.2523 -#: ../en/ch02-tour-basic.xml:579 37.2524 +#: ../en/ch01-tour-basic.xml:580 37.2525 msgid "" 37.2526 "Mercurial's built-in web server obfuscates email addresses, to make it more " 37.2527 "difficult for the email harvesting tools that spammers use. This reduces the " 37.2528 @@ -3259,12 +2336,12 @@ 37.2529 msgstr "" 37.2530 37.2531 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2532 -#: ../en/ch02-tour-basic.xml:589 37.2533 +#: ../en/ch01-tour-basic.xml:590 37.2534 msgid "Writing a commit message" 37.2535 msgstr "写提交日志" 37.2536 37.2537 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2538 -#: ../en/ch02-tour-basic.xml:591 37.2539 +#: ../en/ch01-tour-basic.xml:592 37.2540 msgid "" 37.2541 "When we commit a change, Mercurial drops us into a text editor, to enter a " 37.2542 "message that will describe the modifications we've made in this changeset. " 37.2543 @@ -3274,7 +2351,7 @@ 37.2544 msgstr "" 37.2545 37.2546 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2547 -#: ../en/ch02-tour-basic.xml:601 37.2548 +#: ../en/ch01-tour-basic.xml:602 37.2549 msgid "" 37.2550 "The editor that the <command role=\"hg-cmd\">hg commit</command> command " 37.2551 "drops us into will contain an empty line, followed by a number of lines " 37.2552 @@ -3282,7 +2359,7 @@ 37.2553 msgstr "" 37.2554 37.2555 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2556 -#: ../en/ch02-tour-basic.xml:608 37.2557 +#: ../en/ch01-tour-basic.xml:609 37.2558 msgid "" 37.2559 "Mercurial ignores the lines that start with <quote><literal>HG:</literal></" 37.2560 "quote>; it uses them only to tell us which files it's recording changes to. " 37.2561 @@ -3290,12 +2367,12 @@ 37.2562 msgstr "" 37.2563 37.2564 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2565 -#: ../en/ch02-tour-basic.xml:614 37.2566 +#: ../en/ch01-tour-basic.xml:615 37.2567 msgid "Writing a good commit message" 37.2568 msgstr "写好提交日志" 37.2569 37.2570 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2571 -#: ../en/ch02-tour-basic.xml:616 37.2572 +#: ../en/ch01-tour-basic.xml:617 37.2573 msgid "" 37.2574 "Since <command role=\"hg-cmd\">hg log</command> only prints the first line of " 37.2575 "a commit message by default, it's best to write a commit message whose first " 37.2576 @@ -3305,7 +2382,7 @@ 37.2577 msgstr "" 37.2578 37.2579 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2580 -#: ../en/ch02-tour-basic.xml:630 37.2581 +#: ../en/ch01-tour-basic.xml:631 37.2582 msgid "" 37.2583 "As far as the remainder of the contents of the commit message are concerned, " 37.2584 "there are no hard-and-fast rules. Mercurial itself doesn't interpret or care " 37.2585 @@ -3314,7 +2391,7 @@ 37.2586 msgstr "" 37.2587 37.2588 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2589 -#: ../en/ch02-tour-basic.xml:636 37.2590 +#: ../en/ch01-tour-basic.xml:637 37.2591 msgid "" 37.2592 "My personal preference is for short, but informative, commit messages that " 37.2593 "tell me something that I can't figure out with a quick glance at the output " 37.2594 @@ -3322,12 +2399,12 @@ 37.2595 msgstr "" 37.2596 37.2597 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2598 -#: ../en/ch02-tour-basic.xml:643 37.2599 +#: ../en/ch01-tour-basic.xml:644 37.2600 msgid "Aborting a commit" 37.2601 msgstr "终止提交" 37.2602 37.2603 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2604 -#: ../en/ch02-tour-basic.xml:645 37.2605 +#: ../en/ch01-tour-basic.xml:646 37.2606 msgid "" 37.2607 "If you decide that you don't want to commit while in the middle of editing a " 37.2608 "commit message, simply exit from your editor without saving the file that " 37.2609 @@ -3336,7 +2413,7 @@ 37.2610 msgstr "" 37.2611 37.2612 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2613 -#: ../en/ch02-tour-basic.xml:650 37.2614 +#: ../en/ch01-tour-basic.xml:651 37.2615 msgid "" 37.2616 "If we run the <command role=\"hg-cmd\">hg commit</command> command without " 37.2617 "any arguments, it records all of the changes we've made, as reported by " 37.2618 @@ -3345,12 +2422,12 @@ 37.2619 msgstr "" 37.2620 37.2621 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2622 -#: ../en/ch02-tour-basic.xml:657 37.2623 +#: ../en/ch01-tour-basic.xml:658 37.2624 msgid "Admiring our new handiwork" 37.2625 msgstr "欣赏我们的新手艺" 37.2626 37.2627 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2628 -#: ../en/ch02-tour-basic.xml:659 37.2629 +#: ../en/ch01-tour-basic.xml:660 37.2630 msgid "" 37.2631 "Once we've finished the commit, we can use the <command role=\"hg-cmd\">hg " 37.2632 "tip</command> command to display the changeset we just created. This command " 37.2633 @@ -3359,19 +2436,19 @@ 37.2634 msgstr "" 37.2635 37.2636 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2637 -#: ../en/ch02-tour-basic.xml:668 37.2638 +#: ../en/ch01-tour-basic.xml:669 37.2639 msgid "" 37.2640 "We refer to the newest revision in the repository as the tip revision, or " 37.2641 "simply the tip." 37.2642 msgstr "" 37.2643 37.2644 #. type: Content of: <book><chapter><sect1><title> 37.2645 -#: ../en/ch02-tour-basic.xml:675 37.2646 +#: ../en/ch01-tour-basic.xml:676 37.2647 msgid "Sharing changes" 37.2648 msgstr "共享修改" 37.2649 37.2650 #. type: Content of: <book><chapter><sect1><para> 37.2651 -#: ../en/ch02-tour-basic.xml:677 37.2652 +#: ../en/ch01-tour-basic.xml:678 37.2653 msgid "" 37.2654 "We mentioned earlier that repositories in Mercurial are self-contained. This " 37.2655 "means that the changeset we just created exists only in our <filename class=" 37.2656 @@ -3380,12 +2457,12 @@ 37.2657 msgstr "" 37.2658 37.2659 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2660 -#: ../en/ch02-tour-basic.xml:685 37.2661 +#: ../en/ch01-tour-basic.xml:686 37.2662 msgid "Pulling changes from another repository" 37.2663 msgstr "从其它版本库取得修改" 37.2664 37.2665 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2666 -#: ../en/ch02-tour-basic.xml:686 37.2667 +#: ../en/ch01-tour-basic.xml:687 37.2668 msgid "" 37.2669 "To get started, let's clone our original <filename class=\"directory\">hello</" 37.2670 "filename> repository, which does not contain the change we just committed. " 37.2671 @@ -3394,7 +2471,7 @@ 37.2672 msgstr "" 37.2673 37.2674 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2675 -#: ../en/ch02-tour-basic.xml:694 37.2676 +#: ../en/ch01-tour-basic.xml:695 37.2677 msgid "" 37.2678 "We'll use the <command role=\"hg-cmd\">hg pull</command> command to bring " 37.2679 "changes from <filename class=\"directory\">my-hello</filename> into <filename " 37.2680 @@ -3407,7 +2484,7 @@ 37.2681 msgstr "" 37.2682 37.2683 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2684 -#: ../en/ch02-tour-basic.xml:707 37.2685 +#: ../en/ch01-tour-basic.xml:708 37.2686 msgid "" 37.2687 "(Of course, someone could cause more changesets to appear in the repository " 37.2688 "that we ran <command role=\"hg-cmd\">hg incoming</command> in, before we get " 37.2689 @@ -3416,7 +2493,7 @@ 37.2690 msgstr "" 37.2691 37.2692 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2693 -#: ../en/ch02-tour-basic.xml:714 37.2694 +#: ../en/ch01-tour-basic.xml:715 37.2695 msgid "" 37.2696 "Bringing changes into a repository is a simple matter of running the <command " 37.2697 "role=\"hg-cmd\">hg pull</command> command, and telling it which repository to " 37.2698 @@ -3424,7 +2501,7 @@ 37.2699 msgstr "" 37.2700 37.2701 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2702 -#: ../en/ch02-tour-basic.xml:721 37.2703 +#: ../en/ch01-tour-basic.xml:722 37.2704 msgid "" 37.2705 "As you can see from the before-and-after output of <command role=\"hg-cmd" 37.2706 "\">hg tip</command>, we have successfully pulled changes into our " 37.2707 @@ -3433,12 +2510,12 @@ 37.2708 msgstr "" 37.2709 37.2710 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2711 -#: ../en/ch02-tour-basic.xml:729 37.2712 +#: ../en/ch01-tour-basic.xml:730 37.2713 msgid "Updating the working directory" 37.2714 msgstr "更新工作目录" 37.2715 37.2716 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2717 -#: ../en/ch02-tour-basic.xml:731 37.2718 +#: ../en/ch01-tour-basic.xml:732 37.2719 msgid "" 37.2720 "We have so far glossed over the relationship between a repository and its " 37.2721 "working directory. The <command role=\"hg-cmd\">hg pull</command> command " 37.2722 @@ -3450,7 +2527,7 @@ 37.2723 msgstr "" 37.2724 37.2725 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2726 -#: ../en/ch02-tour-basic.xml:743 37.2727 +#: ../en/ch01-tour-basic.xml:744 37.2728 msgid "" 37.2729 "It might seem a bit strange that <command role=\"hg-cmd\">hg pull</command> " 37.2730 "doesn't update the working directory automatically. There's actually a good " 37.2731 @@ -3464,7 +2541,7 @@ 37.2732 msgstr "" 37.2733 37.2734 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2735 -#: ../en/ch02-tour-basic.xml:754 37.2736 +#: ../en/ch01-tour-basic.xml:755 37.2737 msgid "" 37.2738 "However, since pull-then-update is such a common thing to do, Mercurial lets " 37.2739 "you combine the two by passing the <option role=\"hg-opt-pull\">-u</option> " 37.2740 @@ -3472,7 +2549,7 @@ 37.2741 msgstr "" 37.2742 37.2743 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2744 -#: ../en/ch02-tour-basic.xml:759 37.2745 +#: ../en/ch01-tour-basic.xml:760 37.2746 msgid "" 37.2747 "If you look back at the output of <command role=\"hg-cmd\">hg pull</command> " 37.2748 "in section <xref linkend=\"sec.tour.pull\"/> when we ran it without <option " 37.2749 @@ -3482,14 +2559,14 @@ 37.2750 msgstr "" 37.2751 37.2752 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2753 -#: ../en/ch02-tour-basic.xml:768 37.2754 +#: ../en/ch01-tour-basic.xml:769 37.2755 msgid "" 37.2756 "To find out what revision the working directory is at, use the <command role=" 37.2757 "\"hg-cmd\">hg parents</command> command." 37.2758 msgstr "" 37.2759 37.2760 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2761 -#: ../en/ch02-tour-basic.xml:774 37.2762 +#: ../en/ch01-tour-basic.xml:775 37.2763 msgid "" 37.2764 "If you look back at figure <xref endterm=\"fig.tour-basic.history.caption\" " 37.2765 "linkend=\"fig.tour-basic.history\"/>, you'll see arrows connecting each " 37.2766 @@ -3500,7 +2577,7 @@ 37.2767 msgstr "" 37.2768 37.2769 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2770 -#: ../en/ch02-tour-basic.xml:784 37.2771 +#: ../en/ch01-tour-basic.xml:785 37.2772 msgid "" 37.2773 "To update the working directory to a particular revision, give a revision " 37.2774 "number or changeset ID to the <command role=\"hg-cmd\">hg update</command> " 37.2775 @@ -3508,7 +2585,7 @@ 37.2776 msgstr "" 37.2777 37.2778 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2779 -#: ../en/ch02-tour-basic.xml:791 37.2780 +#: ../en/ch01-tour-basic.xml:792 37.2781 msgid "" 37.2782 "If you omit an explicit revision, <command role=\"hg-cmd\">hg update</" 37.2783 "command> will update to the tip revision, as shown by the second call to " 37.2784 @@ -3516,12 +2593,12 @@ 37.2785 msgstr "" 37.2786 37.2787 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2788 -#: ../en/ch02-tour-basic.xml:799 37.2789 +#: ../en/ch01-tour-basic.xml:800 37.2790 msgid "Pushing changes to another repository" 37.2791 msgstr "发布修改到其它版本库" 37.2792 37.2793 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2794 -#: ../en/ch02-tour-basic.xml:801 37.2795 +#: ../en/ch01-tour-basic.xml:802 37.2796 msgid "" 37.2797 "Mercurial lets us push changes to another repository, from the repository " 37.2798 "we're currently visiting. As with the example of <command role=\"hg-cmd\">hg " 37.2799 @@ -3530,21 +2607,21 @@ 37.2800 msgstr "" 37.2801 37.2802 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2803 -#: ../en/ch02-tour-basic.xml:809 37.2804 +#: ../en/ch01-tour-basic.xml:810 37.2805 msgid "" 37.2806 "The <command role=\"hg-cmd\">hg outgoing</command> command tells us what " 37.2807 "changes would be pushed into another repository." 37.2808 msgstr "" 37.2809 37.2810 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2811 -#: ../en/ch02-tour-basic.xml:815 37.2812 +#: ../en/ch01-tour-basic.xml:816 37.2813 msgid "" 37.2814 "And the <command role=\"hg-cmd\">hg push</command> command does the actual " 37.2815 "push." 37.2816 msgstr "" 37.2817 37.2818 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2819 -#: ../en/ch02-tour-basic.xml:821 37.2820 +#: ../en/ch01-tour-basic.xml:822 37.2821 msgid "" 37.2822 "As with <command role=\"hg-cmd\">hg pull</command>, the <command role=\"hg-cmd" 37.2823 "\">hg push</command> command does not update the working directory in the " 37.2824 @@ -3555,19 +2632,19 @@ 37.2825 msgstr "" 37.2826 37.2827 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2828 -#: ../en/ch02-tour-basic.xml:830 37.2829 +#: ../en/ch01-tour-basic.xml:831 37.2830 msgid "" 37.2831 "What happens if we try to pull or push changes and the receiving repository " 37.2832 "already has those changes? Nothing too exciting." 37.2833 msgstr "" 37.2834 37.2835 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2836 -#: ../en/ch02-tour-basic.xml:837 37.2837 +#: ../en/ch01-tour-basic.xml:838 37.2838 msgid "Sharing changes over a network" 37.2839 msgstr "通过网络共享修改" 37.2840 37.2841 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2842 -#: ../en/ch02-tour-basic.xml:839 37.2843 +#: ../en/ch01-tour-basic.xml:840 37.2844 msgid "" 37.2845 "The commands we have covered in the previous few sections are not limited to " 37.2846 "working with local repositories. Each works in exactly the same fashion over " 37.2847 @@ -3575,7 +2652,7 @@ 37.2848 msgstr "" 37.2849 37.2850 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2851 -#: ../en/ch02-tour-basic.xml:847 37.2852 +#: ../en/ch01-tour-basic.xml:848 37.2853 msgid "" 37.2854 "In this example, we can see what changes we could push to the remote " 37.2855 "repository, but the repository is understandably not set up to let anonymous " 37.2856 @@ -3583,12 +2660,12 @@ 37.2857 msgstr "" 37.2858 37.2859 #. type: Content of: <book><chapter><title> 37.2860 -#: ../en/ch03-tour-merge.xml:5 37.2861 +#: ../en/ch02-tour-merge.xml:5 37.2862 msgid "A tour of Mercurial: merging work" 37.2863 msgstr "Mercurial 教程: 合并工作" 37.2864 37.2865 #. type: Content of: <book><chapter><para> 37.2866 -#: ../en/ch03-tour-merge.xml:7 37.2867 +#: ../en/ch02-tour-merge.xml:7 37.2868 msgid "" 37.2869 "We've now covered cloning a repository, making changes in a repository, and " 37.2870 "pulling or pushing changes from one repository into another. Our next step " 37.2871 @@ -3596,19 +2673,19 @@ 37.2872 msgstr "" 37.2873 37.2874 #. type: Content of: <book><chapter><sect1><title> 37.2875 -#: ../en/ch03-tour-merge.xml:13 37.2876 +#: ../en/ch02-tour-merge.xml:13 37.2877 msgid "Merging streams of work" 37.2878 msgstr "合并的流程" 37.2879 37.2880 #. type: Content of: <book><chapter><sect1><para> 37.2881 -#: ../en/ch03-tour-merge.xml:15 37.2882 +#: ../en/ch02-tour-merge.xml:15 37.2883 msgid "" 37.2884 "Merging is a fundamental part of working with a distributed revision control " 37.2885 "tool." 37.2886 msgstr "" 37.2887 37.2888 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2889 -#: ../en/ch03-tour-merge.xml:18 37.2890 +#: ../en/ch02-tour-merge.xml:18 37.2891 msgid "" 37.2892 "Alice and Bob each have a personal copy of a repository for a project they're " 37.2893 "collaborating on. Alice fixes a bug in her repository; Bob adds a new " 37.2894 @@ -3617,7 +2694,7 @@ 37.2895 msgstr "" 37.2896 37.2897 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.2898 -#: ../en/ch03-tour-merge.xml:24 37.2899 +#: ../en/ch02-tour-merge.xml:24 37.2900 msgid "" 37.2901 "I frequently work on several different tasks for a single project at once, " 37.2902 "each safely isolated in its own repository. Working this way means that I " 37.2903 @@ -3625,7 +2702,7 @@ 37.2904 msgstr "" 37.2905 37.2906 #. type: Content of: <book><chapter><sect1><para> 37.2907 -#: ../en/ch03-tour-merge.xml:30 37.2908 +#: ../en/ch02-tour-merge.xml:30 37.2909 msgid "" 37.2910 "Because merging is such a common thing to need to do, Mercurial makes it " 37.2911 "easy. Let's walk through the process. We'll begin by cloning yet another " 37.2912 @@ -3633,7 +2710,7 @@ 37.2913 msgstr "" 37.2914 37.2915 #. type: Content of: <book><chapter><sect1><para> 37.2916 -#: ../en/ch03-tour-merge.xml:37 37.2917 +#: ../en/ch02-tour-merge.xml:37 37.2918 msgid "" 37.2919 "We should now have two copies of <filename>hello.c</filename> with different " 37.2920 "contents. The histories of the two repositories have also diverged, as " 37.2921 @@ -3642,14 +2719,14 @@ 37.2922 msgstr "" 37.2923 37.2924 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject> 37.2925 -#: ../en/ch03-tour-merge.xml:47 37.2926 +#: ../en/ch02-tour-merge.xml:47 37.2927 msgid "" 37.2928 "<imageobject><imagedata fileref=\"images/tour-merge-sep-repos.png\"/></" 37.2929 "imageobject>" 37.2930 msgstr "" 37.2931 37.2932 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject><caption><para> 37.2933 -#: ../en/ch03-tour-merge.xml:49 37.2934 +#: ../en/ch02-tour-merge.xml:49 37.2935 msgid "" 37.2936 "Divergent recent histories of the <filename class=\"directory\">my-hello</" 37.2937 "filename> and <filename class=\"directory\">my-new-hello</filename> " 37.2938 @@ -3657,7 +2734,7 @@ 37.2939 msgstr "" 37.2940 37.2941 #. type: Content of: <book><chapter><sect1><para> 37.2942 -#: ../en/ch03-tour-merge.xml:57 37.2943 +#: ../en/ch02-tour-merge.xml:57 37.2944 msgid "" 37.2945 "We already know that pulling changes from our <filename class=\"directory" 37.2946 "\">my-hello</filename> repository will have no effect on the working " 37.2947 @@ -3665,19 +2742,19 @@ 37.2948 msgstr "" 37.2949 37.2950 #. type: Content of: <book><chapter><sect1><para> 37.2951 -#: ../en/ch03-tour-merge.xml:63 37.2952 +#: ../en/ch02-tour-merge.xml:63 37.2953 msgid "" 37.2954 "However, the <command role=\"hg-cmd\">hg pull</command> command says " 37.2955 "something about <quote>heads</quote>." 37.2956 msgstr "" 37.2957 37.2958 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2959 -#: ../en/ch03-tour-merge.xml:67 37.2960 +#: ../en/ch02-tour-merge.xml:67 37.2961 msgid "Head changesets" 37.2962 msgstr "顶点改变集" 37.2963 37.2964 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2965 -#: ../en/ch03-tour-merge.xml:69 37.2966 +#: ../en/ch02-tour-merge.xml:69 37.2967 msgid "" 37.2968 "A head is a change that has no descendants, or children, as they're also " 37.2969 "known. The tip revision is thus a head, because the newest revision in a " 37.2970 @@ -3686,20 +2763,20 @@ 37.2971 msgstr "" 37.2972 37.2973 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.2974 -#: ../en/ch03-tour-merge.xml:77 37.2975 +#: ../en/ch02-tour-merge.xml:77 37.2976 msgid "" 37.2977 "<imageobject><imagedata fileref=\"images/tour-merge-pull.png\"/></imageobject>" 37.2978 msgstr "" 37.2979 37.2980 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.2981 -#: ../en/ch03-tour-merge.xml:79 37.2982 +#: ../en/ch02-tour-merge.xml:79 37.2983 msgid "" 37.2984 "Repository contents after pulling from <filename class=\"directory\">my-" 37.2985 "hello</filename> into <filename class=\"directory\">my-new-hello</filename>" 37.2986 msgstr "" 37.2987 37.2988 #. type: Content of: <book><chapter><sect1><sect2><para> 37.2989 -#: ../en/ch03-tour-merge.xml:85 37.2990 +#: ../en/ch02-tour-merge.xml:85 37.2991 msgid "" 37.2992 "In figure <xref endterm=\"fig.tour-merge.pull.caption\" linkend=\"fig.tour-" 37.2993 "merge.pull\"/>, you can see the effect of the pull from <filename class=" 37.2994 @@ -3716,19 +2793,19 @@ 37.2995 msgstr "" 37.2996 37.2997 #. type: Content of: <book><chapter><sect1><sect2><title> 37.2998 -#: ../en/ch03-tour-merge.xml:106 37.2999 +#: ../en/ch02-tour-merge.xml:106 37.3000 msgid "Performing the merge" 37.3001 msgstr "执行合并" 37.3002 37.3003 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3004 -#: ../en/ch03-tour-merge.xml:108 37.3005 +#: ../en/ch02-tour-merge.xml:108 37.3006 msgid "" 37.3007 "What happens if we try to use the normal <command role=\"hg-cmd\">hg update</" 37.3008 "command> command to update to the new tip?" 37.3009 msgstr "" 37.3010 37.3011 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3012 -#: ../en/ch03-tour-merge.xml:114 37.3013 +#: ../en/ch02-tour-merge.xml:114 37.3014 msgid "" 37.3015 "Mercurial is telling us that the <command role=\"hg-cmd\">hg update</command> " 37.3016 "command won't do a merge; it won't update the working directory when it " 37.3017 @@ -3738,19 +2815,19 @@ 37.3018 msgstr "" 37.3019 37.3020 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3021 -#: ../en/ch03-tour-merge.xml:125 37.3022 +#: ../en/ch02-tour-merge.xml:125 37.3023 msgid "" 37.3024 "<imageobject><imagedata fileref=\"images/tour-merge-merge.png\"/></" 37.3025 "imageobject>" 37.3026 msgstr "" 37.3027 37.3028 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3029 -#: ../en/ch03-tour-merge.xml:127 37.3030 +#: ../en/ch02-tour-merge.xml:127 37.3031 msgid "Working directory and repository during merge, and following commit" 37.3032 msgstr "" 37.3033 37.3034 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3035 -#: ../en/ch03-tour-merge.xml:132 37.3036 +#: ../en/ch02-tour-merge.xml:132 37.3037 msgid "" 37.3038 "This updates the working directory so that it contains changes from " 37.3039 "<emphasis>both</emphasis> heads, which is reflected in both the output of " 37.3040 @@ -3759,12 +2836,12 @@ 37.3041 msgstr "" 37.3042 37.3043 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3044 -#: ../en/ch03-tour-merge.xml:142 37.3045 +#: ../en/ch02-tour-merge.xml:142 37.3046 msgid "Committing the results of the merge" 37.3047 msgstr "提交合并结果" 37.3048 37.3049 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3050 -#: ../en/ch03-tour-merge.xml:144 37.3051 +#: ../en/ch02-tour-merge.xml:144 37.3052 msgid "" 37.3053 "Whenever we've done a merge, <command role=\"hg-cmd\">hg parents</command> " 37.3054 "will display two parents until we <command role=\"hg-cmd\">hg commit</" 37.3055 @@ -3772,7 +2849,7 @@ 37.3056 msgstr "" 37.3057 37.3058 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3059 -#: ../en/ch03-tour-merge.xml:151 37.3060 +#: ../en/ch02-tour-merge.xml:151 37.3061 msgid "" 37.3062 "We now have a new tip revision; notice that it has <emphasis>both</emphasis> " 37.3063 "of our former heads as its parents. These are the same revisions that were " 37.3064 @@ -3780,7 +2857,7 @@ 37.3065 msgstr "" 37.3066 37.3067 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3068 -#: ../en/ch03-tour-merge.xml:158 37.3069 +#: ../en/ch02-tour-merge.xml:158 37.3070 msgid "" 37.3071 "In figure <xref endterm=\"fig.tour-merge.merge.caption\" linkend=\"fig.tour-" 37.3072 "merge.merge\"/>, you can see a representation of what happens to the working " 37.3073 @@ -3790,12 +2867,12 @@ 37.3074 msgstr "" 37.3075 37.3076 #. type: Content of: <book><chapter><sect1><title> 37.3077 -#: ../en/ch03-tour-merge.xml:169 37.3078 +#: ../en/ch02-tour-merge.xml:169 37.3079 msgid "Merging conflicting changes" 37.3080 msgstr "合并有冲突的改变" 37.3081 37.3082 #. type: Content of: <book><chapter><sect1><para> 37.3083 -#: ../en/ch03-tour-merge.xml:171 37.3084 +#: ../en/ch02-tour-merge.xml:171 37.3085 msgid "" 37.3086 "Most merges are simple affairs, but sometimes you'll find yourself merging " 37.3087 "changes where each modifies the same portions of the same files. Unless both " 37.3088 @@ -3805,19 +2882,19 @@ 37.3089 msgstr "" 37.3090 37.3091 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject> 37.3092 -#: ../en/ch03-tour-merge.xml:180 37.3093 +#: ../en/ch02-tour-merge.xml:180 37.3094 msgid "" 37.3095 "<imageobject><imagedata fileref=\"images/tour-merge-conflict.png\"/> </" 37.3096 "imageobject>" 37.3097 msgstr "" 37.3098 37.3099 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject><caption><para> 37.3100 -#: ../en/ch03-tour-merge.xml:183 37.3101 +#: ../en/ch02-tour-merge.xml:183 37.3102 msgid "Conflicting changes to a document" 37.3103 msgstr "" 37.3104 37.3105 #. type: Content of: <book><chapter><sect1><para> 37.3106 -#: ../en/ch03-tour-merge.xml:188 37.3107 +#: ../en/ch02-tour-merge.xml:188 37.3108 msgid "" 37.3109 "Figure <xref endterm=\"fig.tour-merge.conflict.caption\" linkend=\"fig.tour-" 37.3110 "merge.conflict\"/> illustrates an instance of two conflicting changes to a " 37.3111 @@ -3828,7 +2905,7 @@ 37.3112 msgstr "" 37.3113 37.3114 #. type: Content of: <book><chapter><sect1><para> 37.3115 -#: ../en/ch03-tour-merge.xml:196 37.3116 +#: ../en/ch02-tour-merge.xml:196 37.3117 msgid "" 37.3118 "Mercurial doesn't have a built-in facility for handling conflicts. Instead, " 37.3119 "it runs an external program called <command>hgmerge</command>. This is a " 37.3120 @@ -3841,7 +2918,7 @@ 37.3121 msgstr "" 37.3122 37.3123 #. type: Content of: <book><chapter><sect1><para> 37.3124 -#: ../en/ch03-tour-merge.xml:207 37.3125 +#: ../en/ch02-tour-merge.xml:207 37.3126 msgid "" 37.3127 "It's also possible to get Mercurial to run another program or script instead " 37.3128 "of <command>hgmerge</command>, by setting the <envar>HGMERGE</envar> " 37.3129 @@ -3849,12 +2926,12 @@ 37.3130 msgstr "" 37.3131 37.3132 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3133 -#: ../en/ch03-tour-merge.xml:213 37.3134 +#: ../en/ch02-tour-merge.xml:213 37.3135 msgid "Using a graphical merge tool" 37.3136 msgstr "使用图形合并工具" 37.3137 37.3138 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3139 -#: ../en/ch03-tour-merge.xml:215 37.3140 +#: ../en/ch02-tour-merge.xml:215 37.3141 msgid "" 37.3142 "My preferred graphical merge tool is <command>kdiff3</command>, which I'll " 37.3143 "use to describe the features that are common to graphical file merging " 37.3144 @@ -3867,7 +2944,7 @@ 37.3145 msgstr "" 37.3146 37.3147 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3148 -#: ../en/ch03-tour-merge.xml:226 37.3149 +#: ../en/ch02-tour-merge.xml:226 37.3150 msgid "" 37.3151 "At the left is the <emphasis>base</emphasis> version of the file, i.e. the " 37.3152 "most recent version from which the two versions we're trying to merge are " 37.3153 @@ -3875,21 +2952,21 @@ 37.3154 msgstr "" 37.3155 37.3156 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3157 -#: ../en/ch03-tour-merge.xml:231 37.3158 +#: ../en/ch02-tour-merge.xml:231 37.3159 msgid "" 37.3160 "In the middle is <quote>our</quote> version of the file, with the contents " 37.3161 "that we modified." 37.3162 msgstr "" 37.3163 37.3164 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3165 -#: ../en/ch03-tour-merge.xml:234 37.3166 +#: ../en/ch02-tour-merge.xml:234 37.3167 msgid "" 37.3168 "On the right is <quote>their</quote> version of the file, the one that from " 37.3169 "the changeset that we're trying to merge with." 37.3170 msgstr "" 37.3171 37.3172 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3173 -#: ../en/ch03-tour-merge.xml:238 37.3174 +#: ../en/ch02-tour-merge.xml:238 37.3175 msgid "" 37.3176 "In the pane below these is the current <emphasis>result</emphasis> of the " 37.3177 "merge. Our task is to replace all of the red text, which indicates unresolved " 37.3178 @@ -3898,7 +2975,7 @@ 37.3179 msgstr "" 37.3180 37.3181 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3182 -#: ../en/ch03-tour-merge.xml:245 37.3183 +#: ../en/ch02-tour-merge.xml:245 37.3184 msgid "" 37.3185 "All four of these panes are <emphasis>locked together</emphasis>; if we " 37.3186 "scroll vertically or horizontally in any of them, the others are updated to " 37.3187 @@ -3906,19 +2983,19 @@ 37.3188 msgstr "" 37.3189 37.3190 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3191 -#: ../en/ch03-tour-merge.xml:252 37.3192 +#: ../en/ch02-tour-merge.xml:252 37.3193 msgid "" 37.3194 "<imageobject><imagedata width=\"100%\" fileref=\"images/kdiff3.png\"/> </" 37.3195 "imageobject>" 37.3196 msgstr "" 37.3197 37.3198 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3199 -#: ../en/ch03-tour-merge.xml:255 37.3200 +#: ../en/ch02-tour-merge.xml:255 37.3201 msgid "Using <command>kdiff3</command> to merge versions of a file" 37.3202 msgstr "" 37.3203 37.3204 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3205 -#: ../en/ch03-tour-merge.xml:261 37.3206 +#: ../en/ch02-tour-merge.xml:261 37.3207 msgid "" 37.3208 "For each conflicting portion of the file, we can choose to resolve the " 37.3209 "conflict using some combination of text from the base version, ours, or " 37.3210 @@ -3927,7 +3004,7 @@ 37.3211 msgstr "" 37.3212 37.3213 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3214 -#: ../en/ch03-tour-merge.xml:267 37.3215 +#: ../en/ch02-tour-merge.xml:267 37.3216 msgid "" 37.3217 "There are <emphasis>many</emphasis> file merging tools available, too many to " 37.3218 "cover here. They vary in which platforms they are available for, and in " 37.3219 @@ -3937,12 +3014,12 @@ 37.3220 msgstr "" 37.3221 37.3222 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3223 -#: ../en/ch03-tour-merge.xml:276 37.3224 +#: ../en/ch02-tour-merge.xml:276 37.3225 msgid "A worked example" 37.3226 msgstr "合并实例" 37.3227 37.3228 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3229 -#: ../en/ch03-tour-merge.xml:278 37.3230 +#: ../en/ch02-tour-merge.xml:278 37.3231 msgid "" 37.3232 "In this example, we will reproduce the file modification history of figure " 37.3233 "<xref endterm=\"fig.tour-merge.conflict.caption\" linkend=\"fig.tour-merge." 37.3234 @@ -3951,12 +3028,12 @@ 37.3235 msgstr "" 37.3236 37.3237 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3238 -#: ../en/ch03-tour-merge.xml:286 37.3239 +#: ../en/ch02-tour-merge.xml:286 37.3240 msgid "We'll clone the repository and make a change to the file." 37.3241 msgstr "" 37.3242 37.3243 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3244 -#: ../en/ch03-tour-merge.xml:291 37.3245 +#: ../en/ch02-tour-merge.xml:291 37.3246 msgid "" 37.3247 "And another clone, to simulate someone else making a change to the file. " 37.3248 "(This hints at the idea that it's not all that unusual to merge with yourself " 37.3249 @@ -3965,14 +3042,14 @@ 37.3250 msgstr "" 37.3251 37.3252 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3253 -#: ../en/ch03-tour-merge.xml:299 37.3254 +#: ../en/ch02-tour-merge.xml:299 37.3255 msgid "" 37.3256 "Having created two different versions of the file, we'll set up an " 37.3257 "environment suitable for running our merge." 37.3258 msgstr "" 37.3259 37.3260 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3261 -#: ../en/ch03-tour-merge.xml:305 37.3262 +#: ../en/ch02-tour-merge.xml:305 37.3263 msgid "" 37.3264 "In this example, I won't use Mercurial's normal <command>hgmerge</command> " 37.3265 "program to do the merge, because it would drop my nice automated example-" 37.3266 @@ -3984,12 +3061,12 @@ 37.3267 msgstr "" 37.3268 37.3269 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3270 -#: ../en/ch03-tour-merge.xml:315 37.3271 +#: ../en/ch02-tour-merge.xml:315 37.3272 msgid "<emphasis role=\"bold\">XXX FIX THIS EXAMPLE.</emphasis>" 37.3273 msgstr "" 37.3274 37.3275 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3276 -#: ../en/ch03-tour-merge.xml:320 37.3277 +#: ../en/ch02-tour-merge.xml:320 37.3278 msgid "" 37.3279 "Because <command>merge</command> can't resolve the conflicting changes, it " 37.3280 "leaves <emphasis>merge markers</emphasis> inside the file that has conflicts, " 37.3281 @@ -3998,7 +3075,7 @@ 37.3282 msgstr "" 37.3283 37.3284 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3285 -#: ../en/ch03-tour-merge.xml:326 37.3286 +#: ../en/ch02-tour-merge.xml:326 37.3287 msgid "" 37.3288 "Mercurial can tell from the way <command>merge</command> exits that it wasn't " 37.3289 "able to merge successfully, so it tells us what commands we'll need to run if " 37.3290 @@ -4008,7 +3085,7 @@ 37.3291 msgstr "" 37.3292 37.3293 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3294 -#: ../en/ch03-tour-merge.xml:333 37.3295 +#: ../en/ch02-tour-merge.xml:333 37.3296 msgid "" 37.3297 "If automatic or manual merges fail, there's nothing to prevent us from " 37.3298 "<quote>fixing up</quote> the affected files ourselves, and committing the " 37.3299 @@ -4016,19 +3093,19 @@ 37.3300 msgstr "" 37.3301 37.3302 #. type: Content of: <book><chapter><sect1><title> 37.3303 -#: ../en/ch03-tour-merge.xml:342 37.3304 +#: ../en/ch02-tour-merge.xml:342 37.3305 msgid "Simplifying the pull-merge-commit sequence" 37.3306 msgstr "简化拉-合并-提交程序" 37.3307 37.3308 #. type: Content of: <book><chapter><sect1><para> 37.3309 -#: ../en/ch03-tour-merge.xml:344 37.3310 +#: ../en/ch02-tour-merge.xml:344 37.3311 msgid "" 37.3312 "The process of merging changes as outlined above is straightforward, but " 37.3313 "requires running three commands in sequence." 37.3314 msgstr "" 37.3315 37.3316 #. type: Content of: <book><chapter><sect1><para> 37.3317 -#: ../en/ch03-tour-merge.xml:350 37.3318 +#: ../en/ch02-tour-merge.xml:350 37.3319 msgid "" 37.3320 "In the case of the final commit, you also need to enter a commit message, " 37.3321 "which is almost always going to be a piece of uninteresting " 37.3322 @@ -4036,7 +3113,7 @@ 37.3323 msgstr "" 37.3324 37.3325 #. type: Content of: <book><chapter><sect1><para> 37.3326 -#: ../en/ch03-tour-merge.xml:354 37.3327 +#: ../en/ch02-tour-merge.xml:354 37.3328 msgid "" 37.3329 "It would be nice to reduce the number of steps needed, if this were " 37.3330 "possible. Indeed, Mercurial is distributed with an extension called <literal " 37.3331 @@ -4044,7 +3121,7 @@ 37.3332 msgstr "" 37.3333 37.3334 #. type: Content of: <book><chapter><sect1><para> 37.3335 -#: ../en/ch03-tour-merge.xml:359 37.3336 +#: ../en/ch02-tour-merge.xml:359 37.3337 msgid "" 37.3338 "Mercurial provides a flexible extension mechanism that lets people extend its " 37.3339 "functionality, while keeping the core of Mercurial small and easy to deal " 37.3340 @@ -4054,7 +3131,7 @@ 37.3341 msgstr "" 37.3342 37.3343 #. type: Content of: <book><chapter><sect1><para> 37.3344 -#: ../en/ch03-tour-merge.xml:366 37.3345 +#: ../en/ch02-tour-merge.xml:366 37.3346 msgid "" 37.3347 "The <literal role=\"hg-ext\">fetch</literal> extension adds a new command " 37.3348 "called, not surprisingly, <command role=\"hg-cmd\">hg fetch</command>. This " 37.3349 @@ -4068,7 +3145,7 @@ 37.3350 msgstr "" 37.3351 37.3352 #. type: Content of: <book><chapter><sect1><para> 37.3353 -#: ../en/ch03-tour-merge.xml:379 37.3354 +#: ../en/ch02-tour-merge.xml:379 37.3355 msgid "" 37.3356 "Enabling the <literal role=\"hg-ext\">fetch</literal> extension is easy. " 37.3357 "Edit your <filename role=\"special\">.hgrc</filename>, and either go to the " 37.3358 @@ -4078,7 +3155,7 @@ 37.3359 msgstr "" 37.3360 37.3361 #. type: Content of: <book><chapter><sect1><para> 37.3362 -#: ../en/ch03-tour-merge.xml:389 37.3363 +#: ../en/ch02-tour-merge.xml:388 37.3364 msgid "" 37.3365 "(Normally, on the right-hand side of the <quote><literal>=</literal></quote> " 37.3366 "would appear the location of the extension, but since the <literal role=\"hg-" 37.3367 @@ -4087,12 +3164,12 @@ 37.3368 msgstr "" 37.3369 37.3370 #. type: Content of: <book><chapter><title> 37.3371 -#: ../en/ch04-concepts.xml:5 37.3372 +#: ../en/ch03-concepts.xml:5 37.3373 msgid "Behind the scenes" 37.3374 msgstr "Mercurial 内幕" 37.3375 37.3376 #. type: Content of: <book><chapter><para> 37.3377 -#: ../en/ch04-concepts.xml:7 37.3378 +#: ../en/ch03-concepts.xml:7 37.3379 msgid "" 37.3380 "Unlike many revision control systems, the concepts upon which Mercurial is " 37.3381 "built are simple enough that it's easy to understand how the software really " 37.3382 @@ -4101,7 +3178,7 @@ 37.3383 msgstr "" 37.3384 37.3385 #. type: Content of: <book><chapter><para> 37.3386 -#: ../en/ch04-concepts.xml:13 37.3387 +#: ../en/ch03-concepts.xml:13 37.3388 msgid "" 37.3389 "This understanding gives me confidence that Mercurial has been carefully " 37.3390 "designed to be both <emphasis>safe</emphasis> and <emphasis>efficient</" 37.3391 @@ -4111,7 +3188,7 @@ 37.3392 msgstr "" 37.3393 37.3394 #. type: Content of: <book><chapter><para> 37.3395 -#: ../en/ch04-concepts.xml:20 37.3396 +#: ../en/ch03-concepts.xml:20 37.3397 msgid "" 37.3398 "In this chapter, we'll initially cover the core concepts behind Mercurial's " 37.3399 "design, then continue to discuss some of the interesting details of its " 37.3400 @@ -4119,17 +3196,17 @@ 37.3401 msgstr "" 37.3402 37.3403 #. type: Content of: <book><chapter><sect1><title> 37.3404 -#: ../en/ch04-concepts.xml:25 37.3405 +#: ../en/ch03-concepts.xml:25 37.3406 msgid "Mercurial's historical record" 37.3407 msgstr "Mercurial 的历史记录" 37.3408 37.3409 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3410 -#: ../en/ch04-concepts.xml:28 37.3411 +#: ../en/ch03-concepts.xml:28 37.3412 msgid "Tracking the history of a single file" 37.3413 msgstr "跟踪单一文件的历史" 37.3414 37.3415 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3416 -#: ../en/ch04-concepts.xml:30 37.3417 +#: ../en/ch03-concepts.xml:30 37.3418 msgid "" 37.3419 "When Mercurial tracks modifications to a file, it stores the history of that " 37.3420 "file in a metadata object called a <emphasis>filelog</emphasis>. Each entry " 37.3421 @@ -4141,7 +3218,7 @@ 37.3422 msgstr "" 37.3423 37.3424 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3425 -#: ../en/ch04-concepts.xml:41 37.3426 +#: ../en/ch03-concepts.xml:41 37.3427 msgid "" 37.3428 "A file that is large, or has a lot of history, has its filelog stored in " 37.3429 "separate data (<quote><literal>.d</literal></quote> suffix) and index " 37.3430 @@ -4154,23 +3231,23 @@ 37.3431 msgstr "" 37.3432 37.3433 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3434 -#: ../en/ch04-concepts.xml:55 37.3435 +#: ../en/ch03-concepts.xml:55 37.3436 msgid "<imageobject><imagedata fileref=\"images/filelog.png\"/></imageobject>" 37.3437 msgstr "" 37.3438 37.3439 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3440 -#: ../en/ch04-concepts.xml:57 37.3441 +#: ../en/ch03-concepts.xml:57 37.3442 msgid "" 37.3443 "Relationships between files in working directory and filelogs in repository" 37.3444 msgstr "" 37.3445 37.3446 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3447 -#: ../en/ch04-concepts.xml:65 37.3448 +#: ../en/ch03-concepts.xml:65 37.3449 msgid "Managing tracked files" 37.3450 msgstr "管理跟踪的文件" 37.3451 37.3452 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3453 -#: ../en/ch04-concepts.xml:67 37.3454 +#: ../en/ch03-concepts.xml:67 37.3455 msgid "" 37.3456 "Mercurial uses a structure called a <emphasis>manifest</emphasis> to collect " 37.3457 "together information about the files that it tracks. Each entry in the " 37.3458 @@ -4180,12 +3257,12 @@ 37.3459 msgstr "" 37.3460 37.3461 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3462 -#: ../en/ch04-concepts.xml:77 37.3463 +#: ../en/ch03-concepts.xml:77 37.3464 msgid "Recording changeset information" 37.3465 msgstr "记录修改集信息" 37.3466 37.3467 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3468 -#: ../en/ch04-concepts.xml:79 37.3469 +#: ../en/ch03-concepts.xml:79 37.3470 msgid "" 37.3471 "The <emphasis>changelog</emphasis> contains information about each " 37.3472 "changeset. Each revision records who committed a change, the changeset " 37.3473 @@ -4194,12 +3271,12 @@ 37.3474 msgstr "" 37.3475 37.3476 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3477 -#: ../en/ch04-concepts.xml:87 37.3478 +#: ../en/ch03-concepts.xml:87 37.3479 msgid "Relationships between revisions" 37.3480 msgstr "版本之间的关系" 37.3481 37.3482 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3483 -#: ../en/ch04-concepts.xml:89 37.3484 +#: ../en/ch03-concepts.xml:89 37.3485 msgid "" 37.3486 "Within a changelog, a manifest, or a filelog, each revision stores a pointer " 37.3487 "to its immediate parent (or to its two parents, if it's a merge revision). " 37.3488 @@ -4209,7 +3286,7 @@ 37.3489 msgstr "" 37.3490 37.3491 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3492 -#: ../en/ch04-concepts.xml:96 37.3493 +#: ../en/ch03-concepts.xml:96 37.3494 msgid "" 37.3495 "For every changeset in a repository, there is exactly one revision stored in " 37.3496 "the changelog. Each revision of the changelog contains a pointer to a single " 37.3497 @@ -4220,17 +3297,17 @@ 37.3498 msgstr "" 37.3499 37.3500 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3501 -#: ../en/ch04-concepts.xml:107 37.3502 +#: ../en/ch03-concepts.xml:107 37.3503 msgid "<imageobject><imagedata fileref=\"images/metadata.png\"/></imageobject>" 37.3504 msgstr "" 37.3505 37.3506 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3507 -#: ../en/ch04-concepts.xml:109 37.3508 +#: ../en/ch03-concepts.xml:109 37.3509 msgid "Metadata relationships" 37.3510 msgstr "" 37.3511 37.3512 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3513 -#: ../en/ch04-concepts.xml:114 37.3514 +#: ../en/ch03-concepts.xml:114 37.3515 msgid "" 37.3516 "As the illustration shows, there is <emphasis>not</emphasis> a <quote>one to " 37.3517 "one</quote> relationship between revisions in the changelog, manifest, or " 37.3518 @@ -4242,24 +3319,24 @@ 37.3519 msgstr "" 37.3520 37.3521 #. type: Content of: <book><chapter><sect1><title> 37.3522 -#: ../en/ch04-concepts.xml:127 37.3523 +#: ../en/ch03-concepts.xml:127 37.3524 msgid "Safe, efficient storage" 37.3525 msgstr "安全,高效的存储" 37.3526 37.3527 #. type: Content of: <book><chapter><sect1><para> 37.3528 -#: ../en/ch04-concepts.xml:129 37.3529 +#: ../en/ch03-concepts.xml:129 37.3530 msgid "" 37.3531 "The underpinnings of changelogs, manifests, and filelogs are provided by a " 37.3532 "single structure called the <emphasis>revlog</emphasis>." 37.3533 msgstr "" 37.3534 37.3535 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3536 -#: ../en/ch04-concepts.xml:134 37.3537 +#: ../en/ch03-concepts.xml:134 37.3538 msgid "Efficient storage" 37.3539 msgstr "高效存储" 37.3540 37.3541 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3542 -#: ../en/ch04-concepts.xml:136 37.3543 +#: ../en/ch03-concepts.xml:136 37.3544 msgid "" 37.3545 "The revlog provides efficient storage of revisions using a <emphasis>delta</" 37.3546 "emphasis> mechanism. Instead of storing a complete copy of a file for each " 37.3547 @@ -4269,7 +3346,7 @@ 37.3548 msgstr "" 37.3549 37.3550 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3551 -#: ../en/ch04-concepts.xml:144 37.3552 +#: ../en/ch03-concepts.xml:144 37.3553 msgid "" 37.3554 "Some obsolete revision control systems can only work with deltas of text " 37.3555 "files. They must either store binary files as complete snapshots or encoded " 37.3556 @@ -4279,12 +3356,12 @@ 37.3557 msgstr "" 37.3558 37.3559 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3560 -#: ../en/ch04-concepts.xml:153 37.3561 +#: ../en/ch03-concepts.xml:153 37.3562 msgid "Safe operation" 37.3563 msgstr "安全操作" 37.3564 37.3565 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3566 -#: ../en/ch04-concepts.xml:155 37.3567 +#: ../en/ch03-concepts.xml:155 37.3568 msgid "" 37.3569 "Mercurial only ever <emphasis>appends</emphasis> data to the end of a revlog " 37.3570 "file. It never modifies a section of a file after it has written it. This is " 37.3571 @@ -4293,7 +3370,7 @@ 37.3572 msgstr "" 37.3573 37.3574 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3575 -#: ../en/ch04-concepts.xml:161 37.3576 +#: ../en/ch03-concepts.xml:161 37.3577 msgid "" 37.3578 "In addition, Mercurial treats every write as part of a <emphasis>transaction</" 37.3579 "emphasis> that can span a number of files. A transaction is " 37.3580 @@ -4305,7 +3382,7 @@ 37.3581 msgstr "" 37.3582 37.3583 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3584 -#: ../en/ch04-concepts.xml:171 37.3585 +#: ../en/ch03-concepts.xml:171 37.3586 msgid "" 37.3587 "The fact that Mercurial only appends to files makes it easier to provide this " 37.3588 "transactional guarantee. The easier it is to do stuff like this, the more " 37.3589 @@ -4313,12 +3390,12 @@ 37.3590 msgstr "" 37.3591 37.3592 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3593 -#: ../en/ch04-concepts.xml:178 37.3594 +#: ../en/ch03-concepts.xml:178 37.3595 msgid "Fast retrieval" 37.3596 msgstr "快速检索" 37.3597 37.3598 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3599 -#: ../en/ch04-concepts.xml:180 37.3600 +#: ../en/ch03-concepts.xml:180 37.3601 msgid "" 37.3602 "Mercurial cleverly avoids a pitfall common to all earlier revision control " 37.3603 "systems: the problem of <emphasis>inefficient retrieval</emphasis>. Most " 37.3604 @@ -4331,17 +3408,17 @@ 37.3605 msgstr "" 37.3606 37.3607 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3608 -#: ../en/ch04-concepts.xml:193 37.3609 +#: ../en/ch03-concepts.xml:193 37.3610 msgid "<imageobject><imagedata fileref=\"images/snapshot.png\"/></imageobject>" 37.3611 msgstr "" 37.3612 37.3613 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3614 -#: ../en/ch04-concepts.xml:195 37.3615 +#: ../en/ch03-concepts.xml:195 37.3616 msgid "Snapshot of a revlog, with incremental deltas" 37.3617 msgstr "" 37.3618 37.3619 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3620 -#: ../en/ch04-concepts.xml:200 37.3621 +#: ../en/ch03-concepts.xml:200 37.3622 msgid "" 37.3623 "The innovation that Mercurial applies to this problem is simple but " 37.3624 "effective. Once the cumulative amount of delta information stored since the " 37.3625 @@ -4353,7 +3430,7 @@ 37.3626 msgstr "" 37.3627 37.3628 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3629 -#: ../en/ch04-concepts.xml:209 37.3630 +#: ../en/ch03-concepts.xml:209 37.3631 msgid "" 37.3632 "Figure <xref endterm=\"fig.concepts.snapshot.caption\" linkend=\"fig.concepts." 37.3633 "snapshot\"/> illustrates the idea. In an entry in a revlog's index file, " 37.3634 @@ -4362,12 +3439,12 @@ 37.3635 msgstr "" 37.3636 37.3637 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.3638 -#: ../en/ch04-concepts.xml:216 37.3639 +#: ../en/ch03-concepts.xml:216 37.3640 msgid "Aside: the influence of video compression" 37.3641 msgstr "" 37.3642 37.3643 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.3644 -#: ../en/ch04-concepts.xml:218 37.3645 +#: ../en/ch03-concepts.xml:218 37.3646 msgid "" 37.3647 "If you're familiar with video compression or have ever watched a TV feed " 37.3648 "through a digital cable or satellite service, you may know that most video " 37.3649 @@ -4378,7 +3455,7 @@ 37.3650 msgstr "" 37.3651 37.3652 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.3653 -#: ../en/ch04-concepts.xml:227 37.3654 +#: ../en/ch03-concepts.xml:227 37.3655 msgid "" 37.3656 "Because it's possible for a video stream to <quote>drop out</quote> " 37.3657 "occasionally due to signal glitches, and to limit the accumulation of " 37.3658 @@ -4391,12 +3468,12 @@ 37.3659 msgstr "" 37.3660 37.3661 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3662 -#: ../en/ch04-concepts.xml:241 37.3663 +#: ../en/ch03-concepts.xml:241 37.3664 msgid "Identification and strong integrity" 37.3665 msgstr "鉴别和强完整性" 37.3666 37.3667 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3668 -#: ../en/ch04-concepts.xml:243 37.3669 +#: ../en/ch03-concepts.xml:243 37.3670 msgid "" 37.3671 "Along with delta or snapshot information, a revlog entry contains a " 37.3672 "cryptographic hash of the data that it represents. This makes it difficult " 37.3673 @@ -4404,7 +3481,7 @@ 37.3674 msgstr "" 37.3675 37.3676 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3677 -#: ../en/ch04-concepts.xml:248 37.3678 +#: ../en/ch03-concepts.xml:248 37.3679 msgid "" 37.3680 "Hashes provide more than a mere check against corruption; they are used as " 37.3681 "the identifiers for revisions. The changeset identification hashes that you " 37.3682 @@ -4413,7 +3490,7 @@ 37.3683 msgstr "" 37.3684 37.3685 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3686 -#: ../en/ch04-concepts.xml:255 37.3687 +#: ../en/ch03-concepts.xml:255 37.3688 msgid "" 37.3689 "Mercurial verifies that hashes are correct when it retrieves file revisions " 37.3690 "and when it pulls changes from another repository. If it encounters an " 37.3691 @@ -4421,7 +3498,7 @@ 37.3692 msgstr "" 37.3693 37.3694 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3695 -#: ../en/ch04-concepts.xml:260 37.3696 +#: ../en/ch03-concepts.xml:260 37.3697 msgid "" 37.3698 "In addition to the effect it has on retrieval efficiency, Mercurial's use of " 37.3699 "periodic snapshots makes it more robust against partial data corruption. If " 37.3700 @@ -4432,12 +3509,12 @@ 37.3701 msgstr "" 37.3702 37.3703 #. type: Content of: <book><chapter><sect1><title> 37.3704 -#: ../en/ch04-concepts.xml:272 37.3705 +#: ../en/ch03-concepts.xml:272 37.3706 msgid "Revision history, branching, and merging" 37.3707 msgstr "修订历史,分支与合并" 37.3708 37.3709 #. type: Content of: <book><chapter><sect1><para> 37.3710 -#: ../en/ch04-concepts.xml:274 37.3711 +#: ../en/ch03-concepts.xml:274 37.3712 msgid "" 37.3713 "Every entry in a Mercurial revlog knows the identity of its immediate " 37.3714 "ancestor revision, usually referred to as its <emphasis>parent</emphasis>. " 37.3715 @@ -4448,7 +3525,7 @@ 37.3716 msgstr "" 37.3717 37.3718 #. type: Content of: <book><chapter><sect1><para> 37.3719 -#: ../en/ch04-concepts.xml:282 37.3720 +#: ../en/ch03-concepts.xml:282 37.3721 msgid "" 37.3722 "In figure <xref endterm=\"fig.concepts.revlog.caption\" linkend=\"fig." 37.3723 "concepts.revlog\"/>, you can see an example of the conceptual structure of a " 37.3724 @@ -4457,7 +3534,7 @@ 37.3725 msgstr "" 37.3726 37.3727 #. type: Content of: <book><chapter><sect1><para> 37.3728 -#: ../en/ch04-concepts.xml:289 37.3729 +#: ../en/ch03-concepts.xml:289 37.3730 msgid "" 37.3731 "The first revision in a revlog (at the bottom of the image) has the null ID " 37.3732 "in both of its parent slots. For a <quote>normal</quote> revision, its first " 37.3733 @@ -4469,29 +3546,29 @@ 37.3734 msgstr "" 37.3735 37.3736 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject> 37.3737 -#: ../en/ch04-concepts.xml:300 37.3738 +#: ../en/ch03-concepts.xml:300 37.3739 msgid "<imageobject><imagedata fileref=\"images/revlog.png\"/></imageobject>" 37.3740 msgstr "" 37.3741 37.3742 #. type: Content of: <book><chapter><sect1><informalfigure><mediaobject><caption><para> 37.3743 -#: ../en/ch04-concepts.xml:302 37.3744 +#: ../en/ch03-concepts.xml:302 37.3745 msgid "Revision in revlog" 37.3746 msgstr "" 37.3747 37.3748 #. type: Content of: <book><chapter><sect1><title> 37.3749 -#: ../en/ch04-concepts.xml:309 37.3750 +#: ../en/ch03-concepts.xml:309 37.3751 msgid "The working directory" 37.3752 msgstr "工作目录" 37.3753 37.3754 #. type: Content of: <book><chapter><sect1><para> 37.3755 -#: ../en/ch04-concepts.xml:311 37.3756 +#: ../en/ch03-concepts.xml:311 37.3757 msgid "" 37.3758 "In the working directory, Mercurial stores a snapshot of the files from the " 37.3759 "repository as of a particular changeset." 37.3760 msgstr "" 37.3761 37.3762 #. type: Content of: <book><chapter><sect1><para> 37.3763 -#: ../en/ch04-concepts.xml:314 37.3764 +#: ../en/ch03-concepts.xml:314 37.3765 msgid "" 37.3766 "The working directory <quote>knows</quote> which changeset it contains. When " 37.3767 "you update the working directory to contain a particular changeset, Mercurial " 37.3768 @@ -4502,7 +3579,7 @@ 37.3769 msgstr "" 37.3770 37.3771 #. type: Content of: <book><chapter><sect1><para> 37.3772 -#: ../en/ch04-concepts.xml:323 37.3773 +#: ../en/ch03-concepts.xml:323 37.3774 msgid "" 37.3775 "The <emphasis>dirstate</emphasis> contains Mercurial's knowledge of the " 37.3776 "working directory. This details which changeset the working directory is " 37.3777 @@ -4511,7 +3588,7 @@ 37.3778 msgstr "" 37.3779 37.3780 #. type: Content of: <book><chapter><sect1><para> 37.3781 -#: ../en/ch04-concepts.xml:329 37.3782 +#: ../en/ch03-concepts.xml:329 37.3783 msgid "" 37.3784 "Just as a revision of a revlog has room for two parents, so that it can " 37.3785 "represent either a normal revision (with one parent) or a merge of two " 37.3786 @@ -4526,12 +3603,12 @@ 37.3787 msgstr "" 37.3788 37.3789 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3790 -#: ../en/ch04-concepts.xml:343 37.3791 +#: ../en/ch03-concepts.xml:343 37.3792 msgid "What happens when you commit" 37.3793 msgstr "当你提交时发生的事情" 37.3794 37.3795 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3796 -#: ../en/ch04-concepts.xml:345 37.3797 +#: ../en/ch03-concepts.xml:345 37.3798 msgid "" 37.3799 "The dirstate stores parent information for more than just book-keeping " 37.3800 "purposes. Mercurial uses the parents of the dirstate as <emphasis>the " 37.3801 @@ -4539,17 +3616,17 @@ 37.3802 msgstr "" 37.3803 37.3804 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3805 -#: ../en/ch04-concepts.xml:352 37.3806 +#: ../en/ch03-concepts.xml:352 37.3807 msgid "<imageobject><imagedata fileref=\"images/wdir.png\"/></imageobject>" 37.3808 msgstr "" 37.3809 37.3810 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3811 -#: ../en/ch04-concepts.xml:354 37.3812 +#: ../en/ch03-concepts.xml:354 37.3813 msgid "The working directory can have two parents" 37.3814 msgstr "" 37.3815 37.3816 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3817 -#: ../en/ch04-concepts.xml:359 37.3818 +#: ../en/ch03-concepts.xml:359 37.3819 msgid "" 37.3820 "Figure <xref endterm=\"fig.concepts.wdir.caption\" linkend=\"fig.concepts.wdir" 37.3821 "\"/> shows the normal state of the working directory, where it has a single " 37.3822 @@ -4558,19 +3635,19 @@ 37.3823 msgstr "" 37.3824 37.3825 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3826 -#: ../en/ch04-concepts.xml:368 37.3827 +#: ../en/ch03-concepts.xml:368 37.3828 msgid "" 37.3829 "<imageobject><imagedata fileref=\"images/wdir-after-commit.png\"/> </" 37.3830 "imageobject>" 37.3831 msgstr "" 37.3832 37.3833 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3834 -#: ../en/ch04-concepts.xml:371 37.3835 +#: ../en/ch03-concepts.xml:371 37.3836 msgid "The working directory gains new parents after a commit" 37.3837 msgstr "" 37.3838 37.3839 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3840 -#: ../en/ch04-concepts.xml:376 37.3841 +#: ../en/ch03-concepts.xml:376 37.3842 msgid "" 37.3843 "It's useful to think of the working directory as <quote>the changeset I'm " 37.3844 "about to commit</quote>. Any files that you tell Mercurial that you've " 37.3845 @@ -4580,7 +3657,7 @@ 37.3846 msgstr "" 37.3847 37.3848 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3849 -#: ../en/ch04-concepts.xml:384 37.3850 +#: ../en/ch03-concepts.xml:384 37.3851 msgid "" 37.3852 "After a commit, Mercurial will update the parents of the working directory, " 37.3853 "so that the first parent is the ID of the new changeset, and the second is " 37.3854 @@ -4591,12 +3668,12 @@ 37.3855 msgstr "" 37.3856 37.3857 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3858 -#: ../en/ch04-concepts.xml:396 37.3859 +#: ../en/ch03-concepts.xml:396 37.3860 msgid "Creating a new head" 37.3861 msgstr "创建新顶点" 37.3862 37.3863 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3864 -#: ../en/ch04-concepts.xml:398 37.3865 +#: ../en/ch03-concepts.xml:398 37.3866 msgid "" 37.3867 "It's perfectly normal to update the working directory to a changeset other " 37.3868 "than the current tip. For example, you might want to know what your project " 37.3869 @@ -4610,19 +3687,19 @@ 37.3870 msgstr "" 37.3871 37.3872 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3873 -#: ../en/ch04-concepts.xml:412 37.3874 +#: ../en/ch03-concepts.xml:412 37.3875 msgid "" 37.3876 "<imageobject><imagedata fileref=\"images/wdir-pre-branch.png\"/> </" 37.3877 "imageobject>" 37.3878 msgstr "" 37.3879 37.3880 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3881 -#: ../en/ch04-concepts.xml:415 37.3882 +#: ../en/ch03-concepts.xml:415 37.3883 msgid "The working directory, updated to an older changeset" 37.3884 msgstr "" 37.3885 37.3886 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3887 -#: ../en/ch04-concepts.xml:420 37.3888 +#: ../en/ch03-concepts.xml:420 37.3889 msgid "" 37.3890 "Having updated the working directory to an older changeset, what happens if " 37.3891 "you make some changes, and then commit? Mercurial behaves in the same way as " 37.3892 @@ -4635,18 +3712,18 @@ 37.3893 msgstr "" 37.3894 37.3895 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3896 -#: ../en/ch04-concepts.xml:434 37.3897 +#: ../en/ch03-concepts.xml:434 37.3898 msgid "" 37.3899 "<imageobject><imagedata fileref=\"images/wdir-branch.png\"/> </imageobject>" 37.3900 msgstr "" 37.3901 37.3902 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3903 -#: ../en/ch04-concepts.xml:437 37.3904 +#: ../en/ch03-concepts.xml:437 37.3905 msgid "After a commit made while synced to an older changeset" 37.3906 msgstr "" 37.3907 37.3908 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.3909 -#: ../en/ch04-concepts.xml:443 37.3910 +#: ../en/ch03-concepts.xml:443 37.3911 msgid "" 37.3912 "If you're new to Mercurial, you should keep in mind a common <quote>error</" 37.3913 "quote>, which is to use the <command role=\"hg-cmd\">hg pull</command> " 37.3914 @@ -4660,7 +3737,7 @@ 37.3915 msgstr "" 37.3916 37.3917 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.3918 -#: ../en/ch04-concepts.xml:455 37.3919 +#: ../en/ch03-concepts.xml:455 37.3920 msgid "" 37.3921 "I put the word <quote>error</quote> in quotes because all that you need to do " 37.3922 "to rectify this situation is <command role=\"hg-cmd\">hg merge</command>, " 37.3923 @@ -4671,12 +3748,12 @@ 37.3924 msgstr "" 37.3925 37.3926 #. type: Content of: <book><chapter><sect1><sect2><title> 37.3927 -#: ../en/ch04-concepts.xml:467 37.3928 +#: ../en/ch03-concepts.xml:467 37.3929 msgid "Merging heads" 37.3930 msgstr "合并顶点" 37.3931 37.3932 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3933 -#: ../en/ch04-concepts.xml:469 37.3934 +#: ../en/ch03-concepts.xml:469 37.3935 msgid "" 37.3936 "When you run the <command role=\"hg-cmd\">hg merge</command> command, " 37.3937 "Mercurial leaves the first parent of the working directory unchanged, and " 37.3938 @@ -4686,18 +3763,18 @@ 37.3939 msgstr "" 37.3940 37.3941 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.3942 -#: ../en/ch04-concepts.xml:478 37.3943 +#: ../en/ch03-concepts.xml:478 37.3944 msgid "" 37.3945 "<imageobject><imagedata fileref=\"images/wdir-merge.png\"/> </imageobject>" 37.3946 msgstr "" 37.3947 37.3948 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.3949 -#: ../en/ch04-concepts.xml:481 37.3950 +#: ../en/ch03-concepts.xml:481 37.3951 msgid "Merging two heads" 37.3952 msgstr "" 37.3953 37.3954 #. type: Content of: <book><chapter><sect1><sect2><para> 37.3955 -#: ../en/ch04-concepts.xml:486 37.3956 +#: ../en/ch03-concepts.xml:486 37.3957 msgid "" 37.3958 "Mercurial also has to modify the working directory, to merge the files " 37.3959 "managed in the two changesets. Simplified a little, the merging process goes " 37.3960 @@ -4705,33 +3782,33 @@ 37.3961 msgstr "" 37.3962 37.3963 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3964 -#: ../en/ch04-concepts.xml:491 37.3965 +#: ../en/ch03-concepts.xml:491 37.3966 msgid "If neither changeset has modified a file, do nothing with that file." 37.3967 msgstr "" 37.3968 37.3969 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3970 -#: ../en/ch04-concepts.xml:494 37.3971 +#: ../en/ch03-concepts.xml:494 37.3972 msgid "" 37.3973 "If one changeset has modified a file, and the other hasn't, create the " 37.3974 "modified copy of the file in the working directory." 37.3975 msgstr "" 37.3976 37.3977 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3978 -#: ../en/ch04-concepts.xml:498 37.3979 +#: ../en/ch03-concepts.xml:498 37.3980 msgid "" 37.3981 "If one changeset has removed a file, and the other hasn't (or has also " 37.3982 "deleted it), delete the file from the working directory." 37.3983 msgstr "" 37.3984 37.3985 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3986 -#: ../en/ch04-concepts.xml:502 37.3987 +#: ../en/ch03-concepts.xml:502 37.3988 msgid "" 37.3989 "If one changeset has removed a file, but the other has modified the file, ask " 37.3990 "the user what to do: keep the modified file, or remove it?" 37.3991 msgstr "" 37.3992 37.3993 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.3994 -#: ../en/ch04-concepts.xml:506 37.3995 +#: ../en/ch03-concepts.xml:506 37.3996 msgid "" 37.3997 "If both changesets have modified a file, invoke an external merge program to " 37.3998 "choose the new contents for the merged file. This may require input from the " 37.3999 @@ -4739,14 +3816,14 @@ 37.4000 msgstr "" 37.4001 37.4002 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.4003 -#: ../en/ch04-concepts.xml:511 37.4004 +#: ../en/ch03-concepts.xml:511 37.4005 msgid "" 37.4006 "If one changeset has modified a file, and the other has renamed or copied the " 37.4007 "file, make sure that the changes follow the new name of the file." 37.4008 msgstr "" 37.4009 37.4010 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4011 -#: ../en/ch04-concepts.xml:515 37.4012 +#: ../en/ch03-concepts.xml:515 37.4013 msgid "" 37.4014 "There are more details&emdash;merging has plenty of corner cases&emdash;but " 37.4015 "these are the most common choices that are involved in a merge. As you can " 37.4016 @@ -4755,7 +3832,7 @@ 37.4017 msgstr "" 37.4018 37.4019 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4020 -#: ../en/ch04-concepts.xml:522 37.4021 +#: ../en/ch03-concepts.xml:522 37.4022 msgid "" 37.4023 "When you're thinking about what happens when you commit after a merge, once " 37.4024 "again the working directory is <quote>the changeset I'm about to commit</" 37.4025 @@ -4765,7 +3842,7 @@ 37.4026 msgstr "" 37.4027 37.4028 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4029 -#: ../en/ch04-concepts.xml:529 37.4030 +#: ../en/ch03-concepts.xml:529 37.4031 msgid "" 37.4032 "Mercurial lets you perform multiple merges, but you must commit the results " 37.4033 "of each individual merge as you go. This is necessary because Mercurial only " 37.4034 @@ -4776,12 +3853,12 @@ 37.4035 msgstr "" 37.4036 37.4037 #. type: Content of: <book><chapter><sect1><title> 37.4038 -#: ../en/ch04-concepts.xml:540 37.4039 +#: ../en/ch03-concepts.xml:540 37.4040 msgid "Other interesting design features" 37.4041 msgstr "其它有趣的设计特性" 37.4042 37.4043 #. type: Content of: <book><chapter><sect1><para> 37.4044 -#: ../en/ch04-concepts.xml:542 37.4045 +#: ../en/ch03-concepts.xml:542 37.4046 msgid "" 37.4047 "In the sections above, I've tried to highlight some of the most important " 37.4048 "aspects of Mercurial's design, to illustrate that it pays careful attention " 37.4049 @@ -4794,12 +3871,12 @@ 37.4050 msgstr "" 37.4051 37.4052 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4053 -#: ../en/ch04-concepts.xml:553 37.4054 +#: ../en/ch03-concepts.xml:553 37.4055 msgid "Clever compression" 37.4056 msgstr "智能压缩" 37.4057 37.4058 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4059 -#: ../en/ch04-concepts.xml:555 37.4060 +#: ../en/ch03-concepts.xml:555 37.4061 msgid "" 37.4062 "When appropriate, Mercurial will store both snapshots and deltas in " 37.4063 "compressed form. It does this by always <emphasis>trying to</emphasis> " 37.4064 @@ -4808,7 +3885,7 @@ 37.4065 msgstr "" 37.4066 37.4067 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4068 -#: ../en/ch04-concepts.xml:561 37.4069 +#: ../en/ch03-concepts.xml:561 37.4070 msgid "" 37.4071 "This means that Mercurial does <quote>the right thing</quote> when storing a " 37.4072 "file whose native form is compressed, such as a <literal>zip</literal> " 37.4073 @@ -4818,7 +3895,7 @@ 37.4074 msgstr "" 37.4075 37.4076 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4077 -#: ../en/ch04-concepts.xml:569 37.4078 +#: ../en/ch03-concepts.xml:569 37.4079 msgid "" 37.4080 "Deltas between revisions of a compressed file are usually larger than " 37.4081 "snapshots of the file, and Mercurial again does <quote>the right thing</" 37.4082 @@ -4828,12 +3905,12 @@ 37.4083 msgstr "" 37.4084 37.4085 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.4086 -#: ../en/ch04-concepts.xml:578 37.4087 +#: ../en/ch03-concepts.xml:578 37.4088 msgid "Network recompression" 37.4089 msgstr "网络重新压缩" 37.4090 37.4091 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.4092 -#: ../en/ch04-concepts.xml:580 37.4093 +#: ../en/ch03-concepts.xml:580 37.4094 msgid "" 37.4095 "When storing revisions on disk, Mercurial uses the <quote>deflate</quote> " 37.4096 "compression algorithm (the same one used by the popular <literal>zip</" 37.4097 @@ -4843,7 +3920,7 @@ 37.4098 msgstr "" 37.4099 37.4100 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.4101 -#: ../en/ch04-concepts.xml:588 37.4102 +#: ../en/ch03-concepts.xml:588 37.4103 msgid "" 37.4104 "If the connection is over HTTP, Mercurial recompresses the entire stream of " 37.4105 "data using a compression algorithm that gives a better compression ratio (the " 37.4106 @@ -4855,7 +3932,7 @@ 37.4107 msgstr "" 37.4108 37.4109 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.4110 -#: ../en/ch04-concepts.xml:598 37.4111 +#: ../en/ch03-concepts.xml:598 37.4112 msgid "" 37.4113 "(If the connection is over <command>ssh</command>, Mercurial " 37.4114 "<emphasis>doesn't</emphasis> recompress the stream, because <command>ssh</" 37.4115 @@ -4863,12 +3940,12 @@ 37.4116 msgstr "" 37.4117 37.4118 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4119 -#: ../en/ch04-concepts.xml:606 37.4120 +#: ../en/ch03-concepts.xml:606 37.4121 msgid "Read/write ordering and atomicity" 37.4122 msgstr "读写顺序与原子性" 37.4123 37.4124 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4125 -#: ../en/ch04-concepts.xml:608 37.4126 +#: ../en/ch03-concepts.xml:608 37.4127 msgid "" 37.4128 "Appending to files isn't the whole story when it comes to guaranteeing that a " 37.4129 "reader won't see a partial write. If you recall figure <xref endterm=\"fig." 37.4130 @@ -4878,7 +3955,7 @@ 37.4131 msgstr "" 37.4132 37.4133 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4134 -#: ../en/ch04-concepts.xml:616 37.4135 +#: ../en/ch03-concepts.xml:616 37.4136 msgid "" 37.4137 "A writer starts a transaction by writing filelog and manifest data, and " 37.4138 "doesn't write any changelog data until those are finished. A reader starts " 37.4139 @@ -4886,7 +3963,7 @@ 37.4140 msgstr "" 37.4141 37.4142 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4143 -#: ../en/ch04-concepts.xml:621 37.4144 +#: ../en/ch03-concepts.xml:621 37.4145 msgid "" 37.4146 "Since the writer has always finished writing filelog and manifest data before " 37.4147 "it writes to the changelog, a reader will never read a pointer to a partially " 37.4148 @@ -4895,12 +3972,12 @@ 37.4149 msgstr "" 37.4150 37.4151 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4152 -#: ../en/ch04-concepts.xml:629 37.4153 +#: ../en/ch03-concepts.xml:629 37.4154 msgid "Concurrent access" 37.4155 msgstr "并发访问" 37.4156 37.4157 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4158 -#: ../en/ch04-concepts.xml:631 37.4159 +#: ../en/ch03-concepts.xml:631 37.4160 msgid "" 37.4161 "The read/write ordering and atomicity guarantees mean that Mercurial never " 37.4162 "needs to <emphasis>lock</emphasis> a repository when it's reading data, even " 37.4163 @@ -4911,7 +3988,7 @@ 37.4164 msgstr "" 37.4165 37.4166 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4167 -#: ../en/ch04-concepts.xml:640 37.4168 +#: ../en/ch03-concepts.xml:640 37.4169 msgid "" 37.4170 "The lockless nature of reading means that if you're sharing a repository on a " 37.4171 "multi-user system, you don't need to grant other local users permission to " 37.4172 @@ -4925,7 +4002,7 @@ 37.4173 msgstr "" 37.4174 37.4175 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4176 -#: ../en/ch04-concepts.xml:653 37.4177 +#: ../en/ch03-concepts.xml:653 37.4178 msgid "" 37.4179 "Mercurial uses locks to ensure that only one process can write to a " 37.4180 "repository at a time (the locking mechanism is safe even over filesystems " 37.4181 @@ -4939,12 +4016,12 @@ 37.4182 msgstr "" 37.4183 37.4184 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.4185 -#: ../en/ch04-concepts.xml:665 37.4186 +#: ../en/ch03-concepts.xml:665 37.4187 msgid "Safe dirstate access" 37.4188 msgstr "安全的目录状态访问" 37.4189 37.4190 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.4191 -#: ../en/ch04-concepts.xml:667 37.4192 +#: ../en/ch03-concepts.xml:667 37.4193 msgid "" 37.4194 "As with revision data, Mercurial doesn't take a lock to read the dirstate " 37.4195 "file; it does acquire a lock to write it. To avoid the possibility of " 37.4196 @@ -4956,12 +4033,12 @@ 37.4197 msgstr "" 37.4198 37.4199 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4200 -#: ../en/ch04-concepts.xml:680 37.4201 +#: ../en/ch03-concepts.xml:680 37.4202 msgid "Avoiding seeks" 37.4203 msgstr "避免查找" 37.4204 37.4205 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4206 -#: ../en/ch04-concepts.xml:682 37.4207 +#: ../en/ch03-concepts.xml:682 37.4208 msgid "" 37.4209 "Critical to Mercurial's performance is the avoidance of seeks of the disk " 37.4210 "head, since any seek is far more expensive than even a comparatively large " 37.4211 @@ -4969,7 +4046,7 @@ 37.4212 msgstr "" 37.4213 37.4214 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4215 -#: ../en/ch04-concepts.xml:686 37.4216 +#: ../en/ch03-concepts.xml:686 37.4217 msgid "" 37.4218 "This is why, for example, the dirstate is stored in a single file. If there " 37.4219 "were a dirstate file per directory that Mercurial tracked, the disk would " 37.4220 @@ -4978,7 +4055,7 @@ 37.4221 msgstr "" 37.4222 37.4223 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4224 -#: ../en/ch04-concepts.xml:692 37.4225 +#: ../en/ch03-concepts.xml:692 37.4226 msgid "" 37.4227 "Mercurial also uses a <quote>copy on write</quote> scheme when cloning a " 37.4228 "repository on local storage. Instead of copying every revlog file from the " 37.4229 @@ -4991,7 +4068,7 @@ 37.4230 msgstr "" 37.4231 37.4232 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4233 -#: ../en/ch04-concepts.xml:703 37.4234 +#: ../en/ch03-concepts.xml:703 37.4235 msgid "" 37.4236 "A few revision control developers have pointed out that this idea of making a " 37.4237 "complete private copy of a file is not very efficient in its use of storage. " 37.4238 @@ -5003,12 +4080,12 @@ 37.4239 msgstr "" 37.4240 37.4241 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4242 -#: ../en/ch04-concepts.xml:715 37.4243 +#: ../en/ch03-concepts.xml:715 37.4244 msgid "Other contents of the dirstate" 37.4245 msgstr "目录状态的其它内容" 37.4246 37.4247 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4248 -#: ../en/ch04-concepts.xml:717 37.4249 +#: ../en/ch03-concepts.xml:717 37.4250 msgid "" 37.4251 "Because Mercurial doesn't force you to tell it when you're modifying a file, " 37.4252 "it uses the dirstate to store some extra information so it can determine " 37.4253 @@ -5018,7 +4095,7 @@ 37.4254 msgstr "" 37.4255 37.4256 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4257 -#: ../en/ch04-concepts.xml:724 37.4258 +#: ../en/ch03-concepts.xml:724 37.4259 msgid "" 37.4260 "When you explicitly <command role=\"hg-cmd\">hg add</command>, <command role=" 37.4261 "\"hg-cmd\">hg remove</command>, <command role=\"hg-cmd\">hg rename</command> " 37.4262 @@ -5027,7 +4104,7 @@ 37.4263 msgstr "" 37.4264 37.4265 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4266 -#: ../en/ch04-concepts.xml:731 37.4267 +#: ../en/ch03-concepts.xml:731 37.4268 msgid "" 37.4269 "When Mercurial is checking the states of files in the working directory, it " 37.4270 "first checks a file's modification time. If that has not changed, the file " 37.4271 @@ -5041,17 +4118,17 @@ 37.4272 msgstr "" 37.4273 37.4274 #. type: Content of: <book><chapter><title> 37.4275 -#: ../en/ch05-daily.xml:5 37.4276 +#: ../en/ch04-daily.xml:5 37.4277 msgid "Mercurial in daily use" 37.4278 msgstr "Mercurial 的日常使用" 37.4279 37.4280 #. type: Content of: <book><chapter><sect1><title> 37.4281 -#: ../en/ch05-daily.xml:8 37.4282 +#: ../en/ch04-daily.xml:8 37.4283 msgid "Telling Mercurial which files to track" 37.4284 msgstr "告诉 Mercurial 要跟踪哪些文件" 37.4285 37.4286 #. type: Content of: <book><chapter><sect1><para> 37.4287 -#: ../en/ch05-daily.xml:10 37.4288 +#: ../en/ch04-daily.xml:10 37.4289 msgid "" 37.4290 "Mercurial does not work with files in your repository unless you tell it to " 37.4291 "manage them. The <command role=\"hg-cmd\">hg status</command> command will " 37.4292 @@ -5061,7 +4138,7 @@ 37.4293 37.4294 # 37.4295 #. type: Content of: <book><chapter><sect1><para> 37.4296 -#: ../en/ch05-daily.xml:17 37.4297 +#: ../en/ch04-daily.xml:17 37.4298 msgid "" 37.4299 "To tell Mercurial to track a file, use the <command role=\"hg-cmd\">hg add</" 37.4300 "command> command. Once you have added a file, the entry in the output of " 37.4301 @@ -5070,7 +4147,7 @@ 37.4302 msgstr "" 37.4303 37.4304 #. type: Content of: <book><chapter><sect1><para> 37.4305 -#: ../en/ch05-daily.xml:26 37.4306 +#: ../en/ch04-daily.xml:26 37.4307 msgid "" 37.4308 "After you run a <command role=\"hg-cmd\">hg commit</command>, the files that " 37.4309 "you added before the commit will no longer be listed in the output of " 37.4310 @@ -5084,7 +4161,7 @@ 37.4311 msgstr "" 37.4312 37.4313 #. type: Content of: <book><chapter><sect1><para> 37.4314 -#: ../en/ch05-daily.xml:38 37.4315 +#: ../en/ch04-daily.xml:38 37.4316 msgid "" 37.4317 "Once you add a file, Mercurial doesn't do anything with it immediately. " 37.4318 "Instead, it will take a snapshot of the file's state the next time you " 37.4319 @@ -5093,12 +4170,12 @@ 37.4320 msgstr "" 37.4321 37.4322 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4323 -#: ../en/ch05-daily.xml:45 37.4324 +#: ../en/ch04-daily.xml:45 37.4325 msgid "Explicit versus implicit file naming" 37.4326 msgstr "明确与隐含文件命名" 37.4327 37.4328 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4329 -#: ../en/ch05-daily.xml:47 37.4330 +#: ../en/ch04-daily.xml:47 37.4331 msgid "" 37.4332 "A useful behaviour that Mercurial has is that if you pass the name of a " 37.4333 "directory to a command, every Mercurial command will treat this as <quote>I " 37.4334 @@ -5107,7 +4184,7 @@ 37.4335 msgstr "" 37.4336 37.4337 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4338 -#: ../en/ch05-daily.xml:54 37.4339 +#: ../en/ch04-daily.xml:54 37.4340 msgid "" 37.4341 "Notice in this example that Mercurial printed the names of the files it " 37.4342 "added, whereas it didn't do so when we added the file named <filename>a</" 37.4343 @@ -5115,7 +4192,7 @@ 37.4344 msgstr "" 37.4345 37.4346 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4347 -#: ../en/ch05-daily.xml:59 37.4348 +#: ../en/ch04-daily.xml:59 37.4349 msgid "" 37.4350 "What's going on is that in the former case, we explicitly named the file to " 37.4351 "add on the command line, so the assumption that Mercurial makes in such cases " 37.4352 @@ -5123,7 +4200,7 @@ 37.4353 msgstr "" 37.4354 37.4355 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4356 -#: ../en/ch05-daily.xml:64 37.4357 +#: ../en/ch04-daily.xml:64 37.4358 msgid "" 37.4359 "However, when we <emphasis>imply</emphasis> the names of files by giving the " 37.4360 "name of a directory, Mercurial takes the extra step of printing the name of " 37.4361 @@ -5133,12 +4210,12 @@ 37.4362 msgstr "" 37.4363 37.4364 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4365 -#: ../en/ch05-daily.xml:73 37.4366 +#: ../en/ch04-daily.xml:73 37.4367 msgid "Aside: Mercurial tracks files, not directories" 37.4368 msgstr "旁白: Mercurial 只跟踪文件,不跟踪目录" 37.4369 37.4370 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4371 -#: ../en/ch05-daily.xml:75 37.4372 +#: ../en/ch04-daily.xml:75 37.4373 msgid "" 37.4374 "Mercurial does not track directory information. Instead, it tracks the path " 37.4375 "to a file. Before creating a file, it first creates any missing directory " 37.4376 @@ -5149,7 +4226,7 @@ 37.4377 msgstr "" 37.4378 37.4379 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4380 -#: ../en/ch05-daily.xml:84 37.4381 +#: ../en/ch04-daily.xml:84 37.4382 msgid "" 37.4383 "Empty directories are rarely useful, and there are unintrusive workarounds " 37.4384 "that you can use to achieve an appropriate effect. The developers of " 37.4385 @@ -5158,7 +4235,7 @@ 37.4386 msgstr "" 37.4387 37.4388 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4389 -#: ../en/ch05-daily.xml:91 37.4390 +#: ../en/ch04-daily.xml:91 37.4391 msgid "" 37.4392 "If you need an empty directory in your repository, there are a few ways to " 37.4393 "achieve this. One is to create a directory, then <command role=\"hg-cmd\">hg " 37.4394 @@ -5169,20 +4246,20 @@ 37.4395 msgstr "" 37.4396 37.4397 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4398 -#: ../en/ch05-daily.xml:102 37.4399 +#: ../en/ch04-daily.xml:102 37.4400 msgid "" 37.4401 "Another way to tackle a need for an empty directory is to simply create one " 37.4402 "in your automated build scripts before they will need it." 37.4403 msgstr "" 37.4404 37.4405 #. type: Content of: <book><chapter><sect1><title> 37.4406 -#: ../en/ch05-daily.xml:109 37.4407 +#: ../en/ch04-daily.xml:109 37.4408 msgid "How to stop tracking a file" 37.4409 msgstr "如何停止跟踪文件" 37.4410 37.4411 # 37.4412 #. type: Content of: <book><chapter><sect1><para> 37.4413 -#: ../en/ch05-daily.xml:111 37.4414 +#: ../en/ch04-daily.xml:111 37.4415 msgid "" 37.4416 "Once you decide that a file no longer belongs in your repository, use the " 37.4417 "<command role=\"hg-cmd\">hg remove</command> command; this deletes the file, " 37.4418 @@ -5192,7 +4269,7 @@ 37.4419 msgstr "" 37.4420 37.4421 #. type: Content of: <book><chapter><sect1><para> 37.4422 -#: ../en/ch05-daily.xml:120 37.4423 +#: ../en/ch04-daily.xml:120 37.4424 msgid "" 37.4425 "After you <command role=\"hg-cmd\">hg remove</command> a file, Mercurial will " 37.4426 "no longer track changes to that file, even if you recreate a file with the " 37.4427 @@ -5203,36 +4280,36 @@ 37.4428 msgstr "" 37.4429 37.4430 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4431 -#: ../en/ch05-daily.xml:129 37.4432 +#: ../en/ch04-daily.xml:129 37.4433 msgid "Removing a file does not affect its history" 37.4434 msgstr "删除文件不影响历史" 37.4435 37.4436 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4437 -#: ../en/ch05-daily.xml:131 37.4438 +#: ../en/ch04-daily.xml:131 37.4439 msgid "It is important to understand that removing a file has only two effects." 37.4440 msgstr "" 37.4441 37.4442 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.4443 -#: ../en/ch05-daily.xml:134 37.4444 +#: ../en/ch04-daily.xml:134 37.4445 msgid "It removes the current version of the file from the working directory." 37.4446 msgstr "" 37.4447 37.4448 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.4449 -#: ../en/ch05-daily.xml:137 37.4450 +#: ../en/ch04-daily.xml:137 37.4451 msgid "" 37.4452 "It stops Mercurial from tracking changes to the file, from the time of the " 37.4453 "next commit." 37.4454 msgstr "" 37.4455 37.4456 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4457 -#: ../en/ch05-daily.xml:140 37.4458 +#: ../en/ch04-daily.xml:140 37.4459 msgid "" 37.4460 "Removing a file <emphasis>does not</emphasis> in any way alter the " 37.4461 "<emphasis>history</emphasis> of the file." 37.4462 msgstr "" 37.4463 37.4464 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4465 -#: ../en/ch05-daily.xml:143 37.4466 +#: ../en/ch04-daily.xml:143 37.4467 msgid "" 37.4468 "If you update the working directory to a changeset in which a file that you " 37.4469 "have removed was still tracked, it will reappear in the working directory, " 37.4470 @@ -5242,12 +4319,12 @@ 37.4471 msgstr "" 37.4472 37.4473 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4474 -#: ../en/ch05-daily.xml:153 37.4475 +#: ../en/ch04-daily.xml:153 37.4476 msgid "Missing files" 37.4477 msgstr "丢失的文件" 37.4478 37.4479 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4480 -#: ../en/ch05-daily.xml:155 37.4481 +#: ../en/ch04-daily.xml:155 37.4482 msgid "" 37.4483 "Mercurial considers a file that you have deleted, but not used <command role=" 37.4484 "\"hg-cmd\">hg remove</command> to delete, to be <emphasis>missing</" 37.4485 @@ -5257,7 +4334,7 @@ 37.4486 msgstr "" 37.4487 37.4488 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4489 -#: ../en/ch05-daily.xml:165 37.4490 +#: ../en/ch04-daily.xml:165 37.4491 msgid "" 37.4492 "If your repository contains a file that <command role=\"hg-cmd\">hg status</" 37.4493 "command> reports as missing, and you want the file to stay gone, you can run " 37.4494 @@ -5267,7 +4344,7 @@ 37.4495 msgstr "" 37.4496 37.4497 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4498 -#: ../en/ch05-daily.xml:175 37.4499 +#: ../en/ch04-daily.xml:175 37.4500 msgid "" 37.4501 "On the other hand, if you deleted the missing file by accident, give <command " 37.4502 "role=\"hg-cmd\">hg revert</command> the name of the file to recover. It will " 37.4503 @@ -5275,12 +4352,12 @@ 37.4504 msgstr "" 37.4505 37.4506 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4507 -#: ../en/ch05-daily.xml:184 37.4508 +#: ../en/ch04-daily.xml:184 37.4509 msgid "Aside: why tell Mercurial explicitly to remove a file?" 37.4510 msgstr "旁白: 为什么要明确告诉 Mercurial 删除文件?" 37.4511 37.4512 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4513 -#: ../en/ch05-daily.xml:187 37.4514 +#: ../en/ch04-daily.xml:187 37.4515 msgid "" 37.4516 "You might wonder why Mercurial requires you to explicitly tell it that you " 37.4517 "are deleting a file. Early during the development of Mercurial, it let you " 37.4518 @@ -5291,12 +4368,12 @@ 37.4519 msgstr "" 37.4520 37.4521 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4522 -#: ../en/ch05-daily.xml:198 37.4523 +#: ../en/ch04-daily.xml:198 37.4524 msgid "Useful shorthand&emdash;adding and removing files in one step" 37.4525 msgstr "有用的速记&emdash;一个步骤添加和删除文件" 37.4526 37.4527 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4528 -#: ../en/ch05-daily.xml:201 37.4529 +#: ../en/ch04-daily.xml:201 37.4530 msgid "" 37.4531 "Mercurial offers a combination command, <command role=\"hg-cmd\">hg " 37.4532 "addremove</command>, that adds untracked files and marks missing files as " 37.4533 @@ -5304,7 +4381,7 @@ 37.4534 msgstr "" 37.4535 37.4536 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4537 -#: ../en/ch05-daily.xml:207 37.4538 +#: ../en/ch04-daily.xml:207 37.4539 msgid "" 37.4540 "The <command role=\"hg-cmd\">hg commit</command> command also provides a " 37.4541 "<option role=\"hg-opt-commit\">-A</option> option that performs this same add-" 37.4542 @@ -5312,12 +4389,12 @@ 37.4543 msgstr "" 37.4544 37.4545 #. type: Content of: <book><chapter><sect1><title> 37.4546 -#: ../en/ch05-daily.xml:217 37.4547 +#: ../en/ch04-daily.xml:217 37.4548 msgid "Copying files" 37.4549 msgstr "复制文件" 37.4550 37.4551 #. type: Content of: <book><chapter><sect1><para> 37.4552 -#: ../en/ch05-daily.xml:219 37.4553 +#: ../en/ch04-daily.xml:219 37.4554 msgid "" 37.4555 "Mercurial provides a <command role=\"hg-cmd\">hg copy</command> command that " 37.4556 "lets you make a new copy of a file. When you copy a file using this command, " 37.4557 @@ -5327,12 +4404,12 @@ 37.4558 msgstr "" 37.4559 37.4560 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4561 -#: ../en/ch05-daily.xml:227 37.4562 +#: ../en/ch04-daily.xml:227 37.4563 msgid "The results of copying during a merge" 37.4564 msgstr "合并期间的复制结果" 37.4565 37.4566 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4567 -#: ../en/ch05-daily.xml:229 37.4568 +#: ../en/ch04-daily.xml:229 37.4569 msgid "" 37.4570 "What happens during a merge is that changes <quote>follow</quote> a copy. To " 37.4571 "best illustrate what this means, let's create an example. We'll start with " 37.4572 @@ -5340,28 +4417,28 @@ 37.4573 msgstr "" 37.4574 37.4575 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4576 -#: ../en/ch05-daily.xml:236 37.4577 +#: ../en/ch04-daily.xml:236 37.4578 msgid "" 37.4579 "We need to do some work in parallel, so that we'll have something to merge. " 37.4580 "So let's clone our repository." 37.4581 msgstr "" 37.4582 37.4583 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4584 -#: ../en/ch05-daily.xml:242 37.4585 +#: ../en/ch04-daily.xml:242 37.4586 msgid "" 37.4587 "Back in our initial repository, let's use the <command role=\"hg-cmd\">hg " 37.4588 "copy</command> command to make a copy of the first file we created." 37.4589 msgstr "" 37.4590 37.4591 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4592 -#: ../en/ch05-daily.xml:248 37.4593 +#: ../en/ch04-daily.xml:248 37.4594 msgid "" 37.4595 "If we look at the output of the <command role=\"hg-cmd\">hg status</command> " 37.4596 "command afterwards, the copied file looks just like a normal added file." 37.4597 msgstr "" 37.4598 37.4599 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4600 -#: ../en/ch05-daily.xml:254 37.4601 +#: ../en/ch04-daily.xml:254 37.4602 msgid "" 37.4603 "But if we pass the <option role=\"hg-opt-status\">-C</option> option to " 37.4604 "<command role=\"hg-cmd\">hg status</command>, it prints another line of " 37.4605 @@ -5370,14 +4447,14 @@ 37.4606 msgstr "" 37.4607 37.4608 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4609 -#: ../en/ch05-daily.xml:262 37.4610 +#: ../en/ch04-daily.xml:262 37.4611 msgid "" 37.4612 "Now, back in the repository we cloned, let's make a change in parallel. " 37.4613 "We'll add a line of content to the original file that we created." 37.4614 msgstr "" 37.4615 37.4616 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4617 -#: ../en/ch05-daily.xml:268 37.4618 +#: ../en/ch04-daily.xml:268 37.4619 msgid "" 37.4620 "Now we have a modified <filename>file</filename> in this repository. When we " 37.4621 "pull the changes from the first repository, and merge the two heads, " 37.4622 @@ -5386,19 +4463,19 @@ 37.4623 msgstr "" 37.4624 37.4625 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4626 -#: ../en/ch05-daily.xml:278 37.4627 +#: ../en/ch04-daily.xml:278 37.4628 msgid "Why should changes follow copies?" 37.4629 msgstr "为什么复制后需要后续修改?" 37.4630 37.4631 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4632 -#: ../en/ch05-daily.xml:280 37.4633 +#: ../en/ch04-daily.xml:280 37.4634 msgid "" 37.4635 "This behaviour, of changes to a file propagating out to copies of the file, " 37.4636 "might seem esoteric, but in most cases it's highly desirable." 37.4637 msgstr "" 37.4638 37.4639 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4640 -#: ../en/ch05-daily.xml:284 37.4641 +#: ../en/ch04-daily.xml:284 37.4642 msgid "" 37.4643 "First of all, remember that this propagation <emphasis>only</emphasis> " 37.4644 "happens when you merge. So if you <command role=\"hg-cmd\">hg copy</command> " 37.4645 @@ -5407,7 +4484,7 @@ 37.4646 msgstr "" 37.4647 37.4648 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4649 -#: ../en/ch05-daily.xml:290 37.4650 +#: ../en/ch04-daily.xml:290 37.4651 msgid "" 37.4652 "The second thing to know is that modifications will only propagate across a " 37.4653 "copy as long as the repository that you're pulling changes from " 37.4654 @@ -5415,7 +4492,7 @@ 37.4655 msgstr "" 37.4656 37.4657 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4658 -#: ../en/ch05-daily.xml:295 37.4659 +#: ../en/ch04-daily.xml:295 37.4660 msgid "" 37.4661 "The reason that Mercurial does this is as follows. Let's say I make an " 37.4662 "important bug fix in a source file, and commit my changes. Meanwhile, you've " 37.4663 @@ -5425,7 +4502,7 @@ 37.4664 msgstr "" 37.4665 37.4666 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4667 -#: ../en/ch05-daily.xml:302 37.4668 +#: ../en/ch04-daily.xml:302 37.4669 msgid "" 37.4670 "If you pulled and merged my changes, and Mercurial <emphasis>didn't</" 37.4671 "emphasis> propagate changes across copies, your source file would now contain " 37.4672 @@ -5434,7 +4511,7 @@ 37.4673 msgstr "" 37.4674 37.4675 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4676 -#: ../en/ch05-daily.xml:308 37.4677 +#: ../en/ch04-daily.xml:308 37.4678 msgid "" 37.4679 "By automatically propagating the change that fixed the bug from the original " 37.4680 "file to the copy, Mercurial prevents this class of problem. To my knowledge, " 37.4681 @@ -5443,7 +4520,7 @@ 37.4682 msgstr "" 37.4683 37.4684 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4685 -#: ../en/ch05-daily.xml:314 37.4686 +#: ../en/ch04-daily.xml:314 37.4687 msgid "" 37.4688 "Once your change history has a record that the copy and subsequent merge " 37.4689 "occurred, there's usually no further need to propagate changes from the " 37.4690 @@ -5452,12 +4529,12 @@ 37.4691 msgstr "" 37.4692 37.4693 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4694 -#: ../en/ch05-daily.xml:322 37.4695 +#: ../en/ch04-daily.xml:322 37.4696 msgid "How to make changes <emphasis>not</emphasis> follow a copy" 37.4697 msgstr "如何让复制后<emphasis>不</emphasis>修改?" 37.4698 37.4699 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4700 -#: ../en/ch05-daily.xml:325 37.4701 +#: ../en/ch04-daily.xml:325 37.4702 msgid "" 37.4703 "If, for some reason, you decide that this business of automatically " 37.4704 "propagating changes across copies is not for you, simply use your system's " 37.4705 @@ -5469,12 +4546,12 @@ 37.4706 msgstr "" 37.4707 37.4708 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4709 -#: ../en/ch05-daily.xml:338 37.4710 +#: ../en/ch04-daily.xml:338 37.4711 msgid "Behaviour of the <command role=\"hg-cmd\">hg copy</command> command" 37.4712 msgstr "命令 <command role=\"hg-cmd\">hg copy</command> 的特性" 37.4713 37.4714 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4715 -#: ../en/ch05-daily.xml:341 37.4716 +#: ../en/ch04-daily.xml:341 37.4717 msgid "" 37.4718 "When you use the <command role=\"hg-cmd\">hg copy</command> command, " 37.4719 "Mercurial makes a copy of each source file as it currently stands in the " 37.4720 @@ -5486,7 +4563,7 @@ 37.4721 msgstr "" 37.4722 37.4723 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4724 -#: ../en/ch05-daily.xml:351 37.4725 +#: ../en/ch04-daily.xml:351 37.4726 msgid "" 37.4727 "The <command role=\"hg-cmd\">hg copy</command> command acts similarly to the " 37.4728 "Unix <command>cp</command> command (you can use the <command role=\"hg-cmd" 37.4729 @@ -5497,21 +4574,21 @@ 37.4730 msgstr "" 37.4731 37.4732 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4733 -#: ../en/ch05-daily.xml:362 37.4734 +#: ../en/ch04-daily.xml:362 37.4735 msgid "" 37.4736 "If the destination is a directory, Mercurial copies its sources into that " 37.4737 "directory." 37.4738 msgstr "" 37.4739 37.4740 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4741 -#: ../en/ch05-daily.xml:367 37.4742 +#: ../en/ch04-daily.xml:367 37.4743 msgid "" 37.4744 "Copying a directory is recursive, and preserves the directory structure of " 37.4745 "the source." 37.4746 msgstr "" 37.4747 37.4748 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4749 -#: ../en/ch05-daily.xml:373 37.4750 +#: ../en/ch04-daily.xml:373 37.4751 msgid "" 37.4752 "If the source and destination are both directories, the source tree is " 37.4753 "recreated in the destination directory." 37.4754 @@ -5519,7 +4596,7 @@ 37.4755 37.4756 # 37.4757 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4758 -#: ../en/ch05-daily.xml:378 37.4759 +#: ../en/ch04-daily.xml:378 37.4760 msgid "" 37.4761 "As with the <command role=\"hg-cmd\">hg rename</command> command, if you copy " 37.4762 "a file manually and then want Mercurial to know that you've copied the file, " 37.4763 @@ -5528,12 +4605,12 @@ 37.4764 msgstr "" 37.4765 37.4766 #. type: Content of: <book><chapter><sect1><title> 37.4767 -#: ../en/ch05-daily.xml:389 37.4768 +#: ../en/ch04-daily.xml:389 37.4769 msgid "Renaming files" 37.4770 msgstr "改名文件" 37.4771 37.4772 #. type: Content of: <book><chapter><sect1><para> 37.4773 -#: ../en/ch05-daily.xml:391 37.4774 +#: ../en/ch04-daily.xml:391 37.4775 msgid "" 37.4776 "It's rather more common to need to rename a file than to make a copy of it. " 37.4777 "The reason I discussed the <command role=\"hg-cmd\">hg copy</command> command " 37.4778 @@ -5543,7 +4620,7 @@ 37.4779 msgstr "" 37.4780 37.4781 #. type: Content of: <book><chapter><sect1><para> 37.4782 -#: ../en/ch05-daily.xml:399 37.4783 +#: ../en/ch04-daily.xml:399 37.4784 msgid "" 37.4785 "When you use the <command role=\"hg-cmd\">hg rename</command> command, " 37.4786 "Mercurial makes a copy of each source file, then deletes it and marks the " 37.4787 @@ -5551,14 +4628,14 @@ 37.4788 msgstr "" 37.4789 37.4790 #. type: Content of: <book><chapter><sect1><para> 37.4791 -#: ../en/ch05-daily.xml:405 37.4792 +#: ../en/ch04-daily.xml:405 37.4793 msgid "" 37.4794 "The <command role=\"hg-cmd\">hg status</command> command shows the newly " 37.4795 "copied file as added, and the copied-from file as removed." 37.4796 msgstr "" 37.4797 37.4798 #. type: Content of: <book><chapter><sect1><para> 37.4799 -#: ../en/ch05-daily.xml:411 37.4800 +#: ../en/ch04-daily.xml:411 37.4801 msgid "" 37.4802 "As with the results of a <command role=\"hg-cmd\">hg copy</command>, we must " 37.4803 "use the <option role=\"hg-opt-status\">-C</option> option to <command role=" 37.4804 @@ -5567,7 +4644,7 @@ 37.4805 msgstr "" 37.4806 37.4807 #. type: Content of: <book><chapter><sect1><para> 37.4808 -#: ../en/ch05-daily.xml:420 37.4809 +#: ../en/ch04-daily.xml:420 37.4810 msgid "" 37.4811 "As with <command role=\"hg-cmd\">hg remove</command> and <command role=\"hg-" 37.4812 "cmd\">hg copy</command>, you can tell Mercurial about a rename after the fact " 37.4813 @@ -5578,19 +4655,19 @@ 37.4814 msgstr "" 37.4815 37.4816 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4817 -#: ../en/ch05-daily.xml:430 37.4818 +#: ../en/ch04-daily.xml:430 37.4819 msgid "Renaming files and merging changes" 37.4820 msgstr "改名文件与合并修改" 37.4821 37.4822 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4823 -#: ../en/ch05-daily.xml:432 37.4824 +#: ../en/ch04-daily.xml:432 37.4825 msgid "" 37.4826 "Since Mercurial's rename is implemented as copy-and-remove, the same " 37.4827 "propagation of changes happens when you merge after a rename as after a copy." 37.4828 msgstr "" 37.4829 37.4830 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4831 -#: ../en/ch05-daily.xml:436 37.4832 +#: ../en/ch04-daily.xml:436 37.4833 msgid "" 37.4834 "If I modify a file, and you rename it to a new name, and then we merge our " 37.4835 "respective changes, my modifications to the file under its original name will " 37.4836 @@ -5600,7 +4677,7 @@ 37.4837 msgstr "" 37.4838 37.4839 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4840 -#: ../en/ch05-daily.xml:443 37.4841 +#: ../en/ch04-daily.xml:443 37.4842 msgid "" 37.4843 "Whereas having changes follow a copy is a feature where you can perhaps nod " 37.4844 "and say <quote>yes, that might be useful,</quote> it should be clear that " 37.4845 @@ -5610,12 +4687,12 @@ 37.4846 msgstr "" 37.4847 37.4848 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4849 -#: ../en/ch05-daily.xml:452 37.4850 +#: ../en/ch04-daily.xml:452 37.4851 msgid "Divergent renames and merging" 37.4852 msgstr "改名与合并的分歧" 37.4853 37.4854 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4855 -#: ../en/ch05-daily.xml:454 37.4856 +#: ../en/ch04-daily.xml:454 37.4857 msgid "" 37.4858 "The case of diverging names occurs when two developers start with a " 37.4859 "file&emdash;let's call it <filename>foo</filename>&emdash;in their respective " 37.4860 @@ -5623,17 +4700,17 @@ 37.4861 msgstr "" 37.4862 37.4863 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4864 -#: ../en/ch05-daily.xml:461 37.4865 +#: ../en/ch04-daily.xml:461 37.4866 msgid "Anne renames the file to <filename>bar</filename>." 37.4867 msgstr "" 37.4868 37.4869 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4870 -#: ../en/ch05-daily.xml:465 37.4871 +#: ../en/ch04-daily.xml:465 37.4872 msgid "Meanwhile, Bob renames it to <filename>quux</filename>." 37.4873 msgstr "" 37.4874 37.4875 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4876 -#: ../en/ch05-daily.xml:470 37.4877 +#: ../en/ch04-daily.xml:470 37.4878 msgid "" 37.4879 "I like to think of this as a conflict because each developer has expressed " 37.4880 "different intentions about what the file ought to be named." 37.4881 @@ -5641,7 +4718,7 @@ 37.4882 37.4883 # 37.4884 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4885 -#: ../en/ch05-daily.xml:474 37.4886 +#: ../en/ch04-daily.xml:474 37.4887 msgid "" 37.4888 "What do you think should happen when they merge their work? Mercurial's " 37.4889 "actual behaviour is that it always preserves <emphasis>both</emphasis> names " 37.4890 @@ -5649,19 +4726,19 @@ 37.4891 msgstr "" 37.4892 37.4893 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4894 -#: ../en/ch05-daily.xml:481 37.4895 +#: ../en/ch04-daily.xml:481 37.4896 msgid "" 37.4897 "Notice that Mercurial does warn about the divergent renames, but it leaves it " 37.4898 "up to you to do something about the divergence after the merge." 37.4899 msgstr "" 37.4900 37.4901 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4902 -#: ../en/ch05-daily.xml:487 37.4903 +#: ../en/ch04-daily.xml:487 37.4904 msgid "Convergent renames and merging" 37.4905 msgstr "收敛改名与合并" 37.4906 37.4907 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4908 -#: ../en/ch05-daily.xml:489 37.4909 +#: ../en/ch04-daily.xml:489 37.4910 msgid "" 37.4911 "Another kind of rename conflict occurs when two people choose to rename " 37.4912 "different <emphasis>source</emphasis> files to the same " 37.4913 @@ -5670,12 +4747,12 @@ 37.4914 msgstr "" 37.4915 37.4916 #. type: Content of: <book><chapter><sect1><sect2><title> 37.4917 -#: ../en/ch05-daily.xml:497 37.4918 +#: ../en/ch04-daily.xml:497 37.4919 msgid "Other name-related corner cases" 37.4920 msgstr "其它名称相关的角落" 37.4921 37.4922 #. type: Content of: <book><chapter><sect1><sect2><para> 37.4923 -#: ../en/ch05-daily.xml:499 37.4924 +#: ../en/ch04-daily.xml:499 37.4925 msgid "" 37.4926 "Mercurial has a longstanding bug in which it fails to handle a merge where " 37.4927 "one side has a file with a given name, while another has a directory with the " 37.4928 @@ -5684,19 +4761,19 @@ 37.4929 msgstr "" 37.4930 37.4931 #. type: Content of: <book><chapter><sect1><title> 37.4932 -#: ../en/ch05-daily.xml:511 37.4933 +#: ../en/ch04-daily.xml:511 37.4934 msgid "Recovering from mistakes" 37.4935 msgstr "从错误恢复" 37.4936 37.4937 #. type: Content of: <book><chapter><sect1><para> 37.4938 -#: ../en/ch05-daily.xml:513 37.4939 +#: ../en/ch04-daily.xml:513 37.4940 msgid "" 37.4941 "Mercurial has some useful commands that will help you to recover from some " 37.4942 "common mistakes." 37.4943 msgstr "" 37.4944 37.4945 #. type: Content of: <book><chapter><sect1><para> 37.4946 -#: ../en/ch05-daily.xml:516 37.4947 +#: ../en/ch04-daily.xml:516 37.4948 msgid "" 37.4949 "The <command role=\"hg-cmd\">hg revert</command> command lets you undo " 37.4950 "changes that you have made to your working directory. For example, if you " 37.4951 @@ -5708,7 +4785,7 @@ 37.4952 msgstr "" 37.4953 37.4954 #. type: Content of: <book><chapter><sect1><para> 37.4955 -#: ../en/ch05-daily.xml:526 37.4956 +#: ../en/ch04-daily.xml:526 37.4957 msgid "" 37.4958 "It's useful to remember that the <command role=\"hg-cmd\">hg revert</command> " 37.4959 "command is useful for changes that you have not yet committed. Once you've " 37.4960 @@ -5717,7 +4794,7 @@ 37.4961 msgstr "" 37.4962 37.4963 #. type: Content of: <book><chapter><sect1><para> 37.4964 -#: ../en/ch05-daily.xml:532 37.4965 +#: ../en/ch04-daily.xml:532 37.4966 msgid "" 37.4967 "For more information about the <command role=\"hg-cmd\">hg revert</command> " 37.4968 "command, and details about how to deal with changes you have already " 37.4969 @@ -5725,12 +4802,12 @@ 37.4970 msgstr "" 37.4971 37.4972 #. type: Content of: <book><chapter><title> 37.4973 -#: ../en/ch06-collab.xml:5 37.4974 +#: ../en/ch05-collab.xml:5 37.4975 msgid "Collaborating with other people" 37.4976 msgstr "团体协作" 37.4977 37.4978 #. type: Content of: <book><chapter><para> 37.4979 -#: ../en/ch06-collab.xml:7 37.4980 +#: ../en/ch05-collab.xml:7 37.4981 msgid "" 37.4982 "As a completely decentralised tool, Mercurial doesn't impose any policy on " 37.4983 "how people ought to work with each other. However, if you're new to " 37.4984 @@ -5739,19 +4816,19 @@ 37.4985 msgstr "" 37.4986 37.4987 #. type: Content of: <book><chapter><sect1><title> 37.4988 -#: ../en/ch06-collab.xml:14 37.4989 +#: ../en/ch05-collab.xml:14 37.4990 msgid "Mercurial's web interface" 37.4991 msgstr "Mercurial 的 web 接口" 37.4992 37.4993 #. type: Content of: <book><chapter><sect1><para> 37.4994 -#: ../en/ch06-collab.xml:16 37.4995 +#: ../en/ch05-collab.xml:16 37.4996 msgid "" 37.4997 "Mercurial has a powerful web interface that provides several useful " 37.4998 "capabilities." 37.4999 msgstr "" 37.5000 37.5001 #. type: Content of: <book><chapter><sect1><para> 37.5002 -#: ../en/ch06-collab.xml:19 37.5003 +#: ../en/ch05-collab.xml:19 37.5004 msgid "" 37.5005 "For interactive use, the web interface lets you browse a single repository or " 37.5006 "a collection of repositories. You can view the history of a repository, " 37.5007 @@ -5760,7 +4837,7 @@ 37.5008 msgstr "" 37.5009 37.5010 #. type: Content of: <book><chapter><sect1><para> 37.5011 -#: ../en/ch06-collab.xml:24 37.5012 +#: ../en/ch05-collab.xml:24 37.5013 msgid "" 37.5014 "Also for human consumption, the web interface provides an RSS feed of the " 37.5015 "changes in a repository. This lets you <quote>subscribe</quote> to a " 37.5016 @@ -5772,7 +4849,7 @@ 37.5017 msgstr "" 37.5018 37.5019 #. type: Content of: <book><chapter><sect1><para> 37.5020 -#: ../en/ch06-collab.xml:34 37.5021 +#: ../en/ch05-collab.xml:34 37.5022 msgid "" 37.5023 "The web interface also lets remote users clone a repository, pull changes " 37.5024 "from it, and (when the server is configured to permit it) push changes back " 37.5025 @@ -5781,7 +4858,7 @@ 37.5026 msgstr "" 37.5027 37.5028 #. type: Content of: <book><chapter><sect1><para> 37.5029 -#: ../en/ch06-collab.xml:40 37.5030 +#: ../en/ch05-collab.xml:40 37.5031 msgid "" 37.5032 "The easiest way to get started with the web interface is to use your web " 37.5033 "browser to visit an existing repository, such as the master Mercurial " 37.5034 @@ -5790,7 +4867,7 @@ 37.5035 msgstr "" 37.5036 37.5037 #. type: Content of: <book><chapter><sect1><para> 37.5038 -#: ../en/ch06-collab.xml:45 37.5039 +#: ../en/ch05-collab.xml:45 37.5040 msgid "" 37.5041 "If you're interested in providing a web interface to your own repositories, " 37.5042 "Mercurial provides two ways to do this. The first is using the <command role=" 37.5043 @@ -5804,12 +4881,12 @@ 37.5044 msgstr "" 37.5045 37.5046 #. type: Content of: <book><chapter><sect1><title> 37.5047 -#: ../en/ch06-collab.xml:60 37.5048 +#: ../en/ch05-collab.xml:60 37.5049 msgid "Collaboration models" 37.5050 msgstr "协作模型" 37.5051 37.5052 #. type: Content of: <book><chapter><sect1><para> 37.5053 -#: ../en/ch06-collab.xml:62 37.5054 +#: ../en/ch05-collab.xml:62 37.5055 msgid "" 37.5056 "With a suitably flexible tool, making decisions about workflow is much more " 37.5057 "of a social engineering challenge than a technical one. Mercurial imposes few " 37.5058 @@ -5819,12 +4896,12 @@ 37.5059 msgstr "" 37.5060 37.5061 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5062 -#: ../en/ch06-collab.xml:70 37.5063 +#: ../en/ch05-collab.xml:70 37.5064 msgid "Factors to keep in mind" 37.5065 msgstr "要牢记的因素" 37.5066 37.5067 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5068 -#: ../en/ch06-collab.xml:72 37.5069 +#: ../en/ch05-collab.xml:72 37.5070 msgid "" 37.5071 "The most important aspect of any model that you must keep in mind is how well " 37.5072 "it matches the needs and capabilities of the people who will be using it. " 37.5073 @@ -5833,7 +4910,7 @@ 37.5074 msgstr "" 37.5075 37.5076 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5077 -#: ../en/ch06-collab.xml:78 37.5078 +#: ../en/ch05-collab.xml:78 37.5079 msgid "" 37.5080 "I once put together a workflow model that seemed to make perfect sense to me, " 37.5081 "but that caused a considerable amount of consternation and strife within my " 37.5082 @@ -5846,7 +4923,7 @@ 37.5083 msgstr "" 37.5084 37.5085 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5086 -#: ../en/ch06-collab.xml:88 37.5087 +#: ../en/ch05-collab.xml:88 37.5088 msgid "" 37.5089 "Don't sweep foreseeable social or technical problems under the rug. Whatever " 37.5090 "scheme you put into effect, you should plan for mistakes and problem " 37.5091 @@ -5860,12 +4937,12 @@ 37.5092 msgstr "" 37.5093 37.5094 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5095 -#: ../en/ch06-collab.xml:102 37.5096 +#: ../en/ch05-collab.xml:102 37.5097 msgid "Informal anarchy" 37.5098 msgstr "无政府状态" 37.5099 37.5100 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5101 -#: ../en/ch06-collab.xml:104 37.5102 +#: ../en/ch05-collab.xml:104 37.5103 msgid "" 37.5104 "I wouldn't suggest an <quote>anything goes</quote> approach as something " 37.5105 "sustainable, but it's a model that's easy to grasp, and it works perfectly " 37.5106 @@ -5873,7 +4950,7 @@ 37.5107 msgstr "" 37.5108 37.5109 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5110 -#: ../en/ch06-collab.xml:109 37.5111 +#: ../en/ch05-collab.xml:109 37.5112 msgid "" 37.5113 "As one example, many projects have a loose-knit group of collaborators who " 37.5114 "rarely physically meet each other. Some groups like to overcome the " 37.5115 @@ -5885,7 +4962,7 @@ 37.5116 msgstr "" 37.5117 37.5118 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5119 -#: ../en/ch06-collab.xml:118 37.5120 +#: ../en/ch05-collab.xml:118 37.5121 msgid "" 37.5122 "A sprint is the perfect place to use the <command role=\"hg-cmd\">hg serve</" 37.5123 "command> command, since <command role=\"hg-cmd\">hg serve</command> does not " 37.5124 @@ -5900,7 +4977,7 @@ 37.5125 msgstr "" 37.5126 37.5127 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5128 -#: ../en/ch06-collab.xml:132 37.5129 +#: ../en/ch05-collab.xml:132 37.5130 msgid "" 37.5131 "The charm, and the problem, with doing things in an ad hoc fashion like this " 37.5132 "is that only people who know about your changes, and where they are, can see " 37.5133 @@ -5910,12 +4987,12 @@ 37.5134 msgstr "" 37.5135 37.5136 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5137 -#: ../en/ch06-collab.xml:141 37.5138 +#: ../en/ch05-collab.xml:141 37.5139 msgid "A single central repository" 37.5140 msgstr "单一中央版本库" 37.5141 37.5142 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5143 -#: ../en/ch06-collab.xml:143 37.5144 +#: ../en/ch05-collab.xml:143 37.5145 msgid "" 37.5146 "For smaller projects migrating from a centralised revision control tool, " 37.5147 "perhaps the easiest way to get started is to have changes flow through a " 37.5148 @@ -5924,7 +5001,7 @@ 37.5149 msgstr "" 37.5150 37.5151 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5152 -#: ../en/ch06-collab.xml:149 37.5153 +#: ../en/ch05-collab.xml:149 37.5154 msgid "" 37.5155 "Contributors start by cloning a copy of this repository. They can pull " 37.5156 "changes from it whenever they need to, and some (perhaps all) developers have " 37.5157 @@ -5933,7 +5010,7 @@ 37.5158 msgstr "" 37.5159 37.5160 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5161 -#: ../en/ch06-collab.xml:154 37.5162 +#: ../en/ch05-collab.xml:154 37.5163 msgid "" 37.5164 "Under this model, it can still often make sense for people to pull changes " 37.5165 "directly from each other, without going through the central repository. " 37.5166 @@ -5946,7 +5023,7 @@ 37.5167 msgstr "" 37.5168 37.5169 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5170 -#: ../en/ch06-collab.xml:165 37.5171 +#: ../en/ch05-collab.xml:165 37.5172 msgid "" 37.5173 "In this kind of scenario, people usually use the <command>ssh</command> " 37.5174 "protocol to securely push changes to the central repository, as documented in " 37.5175 @@ -5958,12 +5035,12 @@ 37.5176 msgstr "" 37.5177 37.5178 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5179 -#: ../en/ch06-collab.xml:178 37.5180 +#: ../en/ch05-collab.xml:178 37.5181 msgid "Working with multiple branches" 37.5182 msgstr "使用多个分支工作" 37.5183 37.5184 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5185 -#: ../en/ch06-collab.xml:180 37.5186 +#: ../en/ch05-collab.xml:180 37.5187 msgid "" 37.5188 "Projects of any significant size naturally tend to make progress on several " 37.5189 "fronts simultaneously. In the case of software, it's common for a project to " 37.5190 @@ -5977,7 +5054,7 @@ 37.5191 msgstr "" 37.5192 37.5193 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5194 -#: ../en/ch06-collab.xml:193 37.5195 +#: ../en/ch05-collab.xml:193 37.5196 msgid "" 37.5197 "Mercurial is particularly well suited to managing a number of simultaneous, " 37.5198 "but not identical, branches. Each <quote>development direction</quote> can " 37.5199 @@ -5988,19 +5065,19 @@ 37.5200 msgstr "" 37.5201 37.5202 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5203 -#: ../en/ch06-collab.xml:202 37.5204 +#: ../en/ch05-collab.xml:202 37.5205 msgid "" 37.5206 "Here's an example of how this can work in practice. Let's say you have one " 37.5207 "<quote>main branch</quote> on a central server." 37.5208 msgstr "" 37.5209 37.5210 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5211 -#: ../en/ch06-collab.xml:208 37.5212 +#: ../en/ch05-collab.xml:208 37.5213 msgid "People clone it, make changes locally, test them, and push them back." 37.5214 msgstr "" 37.5215 37.5216 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5217 -#: ../en/ch06-collab.xml:211 37.5218 +#: ../en/ch05-collab.xml:211 37.5219 msgid "" 37.5220 "Once the main branch reaches a release milestone, you can use the <command " 37.5221 "role=\"hg-cmd\">hg tag</command> command to give a permanent name to the " 37.5222 @@ -6008,12 +5085,12 @@ 37.5223 msgstr "" 37.5224 37.5225 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5226 -#: ../en/ch06-collab.xml:217 37.5227 +#: ../en/ch05-collab.xml:217 37.5228 msgid "Let's say some ongoing development occurs on the main branch." 37.5229 msgstr "" 37.5230 37.5231 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5232 -#: ../en/ch06-collab.xml:222 37.5233 +#: ../en/ch05-collab.xml:222 37.5234 msgid "" 37.5235 "Using the tag that was recorded at the milestone, people who clone that " 37.5236 "repository at any time in the future can use <command role=\"hg-cmd\">hg " 37.5237 @@ -6023,7 +5100,7 @@ 37.5238 37.5239 # 37.5240 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5241 -#: ../en/ch06-collab.xml:230 37.5242 +#: ../en/ch05-collab.xml:230 37.5243 msgid "" 37.5244 "In addition, immediately after the main branch is tagged, someone can then " 37.5245 "clone the main branch on the server to a new <quote>stable</quote> branch, " 37.5246 @@ -6031,7 +5108,7 @@ 37.5247 msgstr "" 37.5248 37.5249 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5250 -#: ../en/ch06-collab.xml:236 37.5251 +#: ../en/ch05-collab.xml:236 37.5252 msgid "" 37.5253 "Someone who needs to make a change to the stable branch can then clone " 37.5254 "<emphasis>that</emphasis> repository, make their changes, commit, and push " 37.5255 @@ -6039,7 +5116,7 @@ 37.5256 msgstr "" 37.5257 37.5258 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5259 -#: ../en/ch06-collab.xml:242 37.5260 +#: ../en/ch05-collab.xml:242 37.5261 msgid "" 37.5262 "Because Mercurial repositories are independent, and Mercurial doesn't move " 37.5263 "changes around automatically, the stable and main branches are " 37.5264 @@ -6049,7 +5126,7 @@ 37.5265 msgstr "" 37.5266 37.5267 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5268 -#: ../en/ch06-collab.xml:249 37.5269 +#: ../en/ch05-collab.xml:249 37.5270 msgid "" 37.5271 "You'll often want all of your bugfixes on the stable branch to show up on the " 37.5272 "main branch, too. Rather than rewrite a bugfix on the main branch, you can " 37.5273 @@ -6058,7 +5135,7 @@ 37.5274 msgstr "" 37.5275 37.5276 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5277 -#: ../en/ch06-collab.xml:257 37.5278 +#: ../en/ch05-collab.xml:257 37.5279 msgid "" 37.5280 "The main branch will still contain changes that are not on the stable branch, " 37.5281 "but it will also contain all of the bugfixes from the stable branch. The " 37.5282 @@ -6066,12 +5143,12 @@ 37.5283 msgstr "" 37.5284 37.5285 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.5286 -#: ../en/ch06-collab.xml:264 ../en/ch06-collab.xml:278 37.5287 +#: ../en/ch05-collab.xml:264 ../en/ch05-collab.xml:278 37.5288 msgid "Feature branches" 37.5289 msgstr "特性分支" 37.5290 37.5291 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5292 -#: ../en/ch06-collab.xml:266 37.5293 +#: ../en/ch05-collab.xml:266 37.5294 msgid "" 37.5295 "For larger projects, an effective way to manage change is to break up a team " 37.5296 "into smaller groups. Each group has a shared branch of its own, cloned from " 37.5297 @@ -6081,14 +5158,14 @@ 37.5298 msgstr "" 37.5299 37.5300 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.5301 -#: ../en/ch06-collab.xml:275 37.5302 +#: ../en/ch05-collab.xml:275 37.5303 msgid "" 37.5304 "<imageobject><imagedata fileref=\"images/feature-branches.png\"/> </" 37.5305 "imageobject>" 37.5306 msgstr "" 37.5307 37.5308 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5309 -#: ../en/ch06-collab.xml:283 37.5310 +#: ../en/ch05-collab.xml:283 37.5311 msgid "" 37.5312 "When a particular feature is deemed to be in suitable shape, someone on that " 37.5313 "feature team pulls and merges from the master branch into the feature branch, " 37.5314 @@ -6096,12 +5173,12 @@ 37.5315 msgstr "" 37.5316 37.5317 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5318 -#: ../en/ch06-collab.xml:290 37.5319 +#: ../en/ch05-collab.xml:290 37.5320 msgid "The release train" 37.5321 msgstr "发布列车" 37.5322 37.5323 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5324 -#: ../en/ch06-collab.xml:292 37.5325 +#: ../en/ch05-collab.xml:292 37.5326 msgid "" 37.5327 "Some projects are organised on a <quote>train</quote> basis: a release is " 37.5328 "scheduled to happen every few months, and whatever features are ready when " 37.5329 @@ -6109,7 +5186,7 @@ 37.5330 msgstr "" 37.5331 37.5332 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5333 -#: ../en/ch06-collab.xml:297 37.5334 +#: ../en/ch05-collab.xml:297 37.5335 msgid "" 37.5336 "This model resembles working with feature branches. The difference is that " 37.5337 "when a feature branch misses a train, someone on the feature team pulls and " 37.5338 @@ -6119,12 +5196,12 @@ 37.5339 msgstr "" 37.5340 37.5341 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5342 -#: ../en/ch06-collab.xml:306 37.5343 +#: ../en/ch05-collab.xml:306 37.5344 msgid "The Linux kernel model" 37.5345 msgstr "Linux 内核模型" 37.5346 37.5347 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5348 -#: ../en/ch06-collab.xml:308 37.5349 +#: ../en/ch05-collab.xml:308 37.5350 msgid "" 37.5351 "The development of the Linux kernel has a shallow hierarchical structure, " 37.5352 "surrounded by a cloud of apparent chaos. Because most Linux developers use " 37.5353 @@ -6134,7 +5211,7 @@ 37.5354 msgstr "" 37.5355 37.5356 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5357 -#: ../en/ch06-collab.xml:316 37.5358 +#: ../en/ch05-collab.xml:316 37.5359 msgid "" 37.5360 "At the center of the community sits Linus Torvalds, the creator of Linux. He " 37.5361 "publishes a single source repository that is considered the " 37.5362 @@ -6144,7 +5221,7 @@ 37.5363 msgstr "" 37.5364 37.5365 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5366 -#: ../en/ch06-collab.xml:323 37.5367 +#: ../en/ch05-collab.xml:323 37.5368 msgid "" 37.5369 "Linus has a number of <quote>trusted lieutenants</quote>. As a general rule, " 37.5370 "he pulls whatever changes they publish, in most cases without even reviewing " 37.5371 @@ -6158,7 +5235,7 @@ 37.5372 msgstr "" 37.5373 37.5374 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5375 -#: ../en/ch06-collab.xml:335 37.5376 +#: ../en/ch05-collab.xml:335 37.5377 msgid "" 37.5378 "Individual lieutenants have their own approaches to reviewing, accepting, and " 37.5379 "publishing changes; and for deciding when to feed them to Linus. In " 37.5380 @@ -6171,7 +5248,7 @@ 37.5381 msgstr "" 37.5382 37.5383 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5384 -#: ../en/ch06-collab.xml:346 37.5385 +#: ../en/ch05-collab.xml:346 37.5386 msgid "" 37.5387 "This model has two notable features. The first is that it's <quote>pull " 37.5388 "only</quote>. You have to ask, convince, or beg another developer to take a " 37.5389 @@ -6181,7 +5258,7 @@ 37.5390 msgstr "" 37.5391 37.5392 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5393 -#: ../en/ch06-collab.xml:353 37.5394 +#: ../en/ch05-collab.xml:353 37.5395 msgid "" 37.5396 "The second is that it's based on reputation and acclaim. If you're an " 37.5397 "unknown, Linus will probably ignore changes from you without even " 37.5398 @@ -6195,7 +5272,7 @@ 37.5399 msgstr "" 37.5400 37.5401 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5402 -#: ../en/ch06-collab.xml:364 37.5403 +#: ../en/ch05-collab.xml:364 37.5404 msgid "" 37.5405 "Reputation and acclaim don't necessarily cross subsystem or <quote>people</" 37.5406 "quote> boundaries. If you're a respected but specialised storage hacker, and " 37.5407 @@ -6204,7 +5281,7 @@ 37.5408 msgstr "" 37.5409 37.5410 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5411 -#: ../en/ch06-collab.xml:371 37.5412 +#: ../en/ch05-collab.xml:371 37.5413 msgid "" 37.5414 "To people who come from more orderly project backgrounds, the comparatively " 37.5415 "chaotic Linux kernel development process often seems completely insane. It's " 37.5416 @@ -6214,12 +5291,12 @@ 37.5417 msgstr "" 37.5418 37.5419 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5420 -#: ../en/ch06-collab.xml:381 37.5421 +#: ../en/ch05-collab.xml:381 37.5422 msgid "Pull-only versus shared-push collaboration" 37.5423 msgstr "只读与共享写协作" 37.5424 37.5425 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5426 -#: ../en/ch06-collab.xml:383 37.5427 +#: ../en/ch05-collab.xml:383 37.5428 msgid "" 37.5429 "A perpetual source of heat in the open source community is whether a " 37.5430 "development model in which people only ever pull changes from others is " 37.5431 @@ -6228,7 +5305,7 @@ 37.5432 msgstr "" 37.5433 37.5434 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5435 -#: ../en/ch06-collab.xml:389 37.5436 +#: ../en/ch05-collab.xml:389 37.5437 msgid "" 37.5438 "Typically, the backers of the shared-push model use tools that actively " 37.5439 "enforce this approach. If you're using a centralised revision control tool " 37.5440 @@ -6239,7 +5316,7 @@ 37.5441 msgstr "" 37.5442 37.5443 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5444 -#: ../en/ch06-collab.xml:397 37.5445 +#: ../en/ch05-collab.xml:397 37.5446 msgid "" 37.5447 "A good distributed revision control tool, such as Mercurial, will support " 37.5448 "both models. You and your collaborators can then structure how you work " 37.5449 @@ -6248,12 +5325,12 @@ 37.5450 msgstr "" 37.5451 37.5452 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5453 -#: ../en/ch06-collab.xml:405 37.5454 +#: ../en/ch05-collab.xml:405 37.5455 msgid "Where collaboration meets branch management" 37.5456 msgstr "协作与分支管理" 37.5457 37.5458 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5459 -#: ../en/ch06-collab.xml:407 37.5460 +#: ../en/ch05-collab.xml:407 37.5461 msgid "" 37.5462 "Once you and your team set up some shared repositories and start propagating " 37.5463 "changes back and forth between local and shared repos, you begin to face a " 37.5464 @@ -6265,24 +5342,24 @@ 37.5465 msgstr "" 37.5466 37.5467 #. type: Content of: <book><chapter><sect1><title> 37.5468 -#: ../en/ch06-collab.xml:419 37.5469 +#: ../en/ch05-collab.xml:419 37.5470 msgid "The technical side of sharing" 37.5471 msgstr "共享的技术因素" 37.5472 37.5473 #. type: Content of: <book><chapter><sect1><para> 37.5474 -#: ../en/ch06-collab.xml:421 37.5475 +#: ../en/ch05-collab.xml:421 37.5476 msgid "" 37.5477 "The remainder of this chapter is devoted to the question of serving data to " 37.5478 "your collaborators." 37.5479 msgstr "" 37.5480 37.5481 #. type: Content of: <book><chapter><sect1><title> 37.5482 -#: ../en/ch06-collab.xml:426 37.5483 +#: ../en/ch05-collab.xml:426 37.5484 msgid "Informal sharing with <command role=\"hg-cmd\">hg serve</command>" 37.5485 msgstr "使用 <command role=\"hg-cmd\">hg serve</command> 进行非正式共享" 37.5486 37.5487 #. type: Content of: <book><chapter><sect1><para> 37.5488 -#: ../en/ch06-collab.xml:429 37.5489 +#: ../en/ch05-collab.xml:429 37.5490 msgid "" 37.5491 "Mercurial's <command role=\"hg-cmd\">hg serve</command> command is " 37.5492 "wonderfully suited to small, tight-knit, and fast-paced group environments. " 37.5493 @@ -6291,7 +5368,7 @@ 37.5494 msgstr "" 37.5495 37.5496 #. type: Content of: <book><chapter><sect1><para> 37.5497 -#: ../en/ch06-collab.xml:434 37.5498 +#: ../en/ch05-collab.xml:434 37.5499 msgid "" 37.5500 "Run <command role=\"hg-cmd\">hg serve</command> inside a repository, and in " 37.5501 "under a second it will bring up a specialised HTTP server; this will accept " 37.5502 @@ -6304,21 +5381,21 @@ 37.5503 msgstr "" 37.5504 37.5505 #. type: Content of: <book><chapter><sect1><para> 37.5506 -#: ../en/ch06-collab.xml:445 37.5507 +#: ../en/ch05-collab.xml:445 37.5508 msgid "" 37.5509 "The <command role=\"hg-cmd\">hg serve</command> command is <emphasis>not</" 37.5510 "emphasis> a general-purpose web server. It can do only two things:" 37.5511 msgstr "" 37.5512 37.5513 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.5514 -#: ../en/ch06-collab.xml:449 37.5515 +#: ../en/ch05-collab.xml:449 37.5516 msgid "" 37.5517 "Allow people to browse the history of the repository it's serving, from their " 37.5518 "normal web browsers." 37.5519 msgstr "" 37.5520 37.5521 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.5522 -#: ../en/ch06-collab.xml:453 37.5523 +#: ../en/ch05-collab.xml:453 37.5524 msgid "" 37.5525 "Speak Mercurial's wire protocol, so that people can <command role=\"hg-cmd" 37.5526 "\">hg clone</command> or <command role=\"hg-cmd\">hg pull</command> changes " 37.5527 @@ -6326,7 +5403,7 @@ 37.5528 msgstr "" 37.5529 37.5530 #. type: Content of: <book><chapter><sect1><para> 37.5531 -#: ../en/ch06-collab.xml:458 37.5532 +#: ../en/ch05-collab.xml:458 37.5533 msgid "" 37.5534 "In particular, <command role=\"hg-cmd\">hg serve</command> won't allow remote " 37.5535 "users to <emphasis>modify</emphasis> your repository. It's intended for read-" 37.5536 @@ -6334,7 +5411,7 @@ 37.5537 msgstr "" 37.5538 37.5539 #. type: Content of: <book><chapter><sect1><para> 37.5540 -#: ../en/ch06-collab.xml:462 37.5541 +#: ../en/ch05-collab.xml:462 37.5542 msgid "" 37.5543 "If you're getting started with Mercurial, there's nothing to prevent you from " 37.5544 "using <command role=\"hg-cmd\">hg serve</command> to serve up a repository on " 37.5545 @@ -6345,12 +5422,12 @@ 37.5546 msgstr "" 37.5547 37.5548 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5549 -#: ../en/ch06-collab.xml:472 37.5550 +#: ../en/ch05-collab.xml:472 37.5551 msgid "A few things to keep in mind" 37.5552 msgstr "要牢记的几件事" 37.5553 37.5554 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5555 -#: ../en/ch06-collab.xml:474 37.5556 +#: ../en/ch05-collab.xml:474 37.5557 msgid "" 37.5558 "Because it provides unauthenticated read access to all clients, you should " 37.5559 "only use <command role=\"hg-cmd\">hg serve</command> in an environment where " 37.5560 @@ -6359,7 +5436,7 @@ 37.5561 msgstr "" 37.5562 37.5563 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5564 -#: ../en/ch06-collab.xml:480 37.5565 +#: ../en/ch05-collab.xml:480 37.5566 msgid "" 37.5567 "The <command role=\"hg-cmd\">hg serve</command> command knows nothing about " 37.5568 "any firewall software you might have installed on your system or network. It " 37.5569 @@ -6370,7 +5447,7 @@ 37.5570 msgstr "" 37.5571 37.5572 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5573 -#: ../en/ch06-collab.xml:489 37.5574 +#: ../en/ch05-collab.xml:489 37.5575 msgid "" 37.5576 "By default, <command role=\"hg-cmd\">hg serve</command> listens for incoming " 37.5577 "connections on port 8000. If another process is already listening on the " 37.5578 @@ -6379,7 +5456,7 @@ 37.5579 msgstr "" 37.5580 37.5581 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5582 -#: ../en/ch06-collab.xml:495 37.5583 +#: ../en/ch05-collab.xml:495 37.5584 msgid "" 37.5585 "Normally, when <command role=\"hg-cmd\">hg serve</command> starts, it prints " 37.5586 "no output, which can be a bit unnerving. If you'd like to confirm that it is " 37.5587 @@ -6389,12 +5466,12 @@ 37.5588 msgstr "" 37.5589 37.5590 #. type: Content of: <book><chapter><sect1><title> 37.5591 -#: ../en/ch06-collab.xml:505 37.5592 +#: ../en/ch05-collab.xml:505 37.5593 msgid "Using the Secure Shell (ssh) protocol" 37.5594 msgstr "使用 ssh 协议" 37.5595 37.5596 #. type: Content of: <book><chapter><sect1><para> 37.5597 -#: ../en/ch06-collab.xml:507 37.5598 +#: ../en/ch05-collab.xml:507 37.5599 msgid "" 37.5600 "You can pull and push changes securely over a network connection using the " 37.5601 "Secure Shell (<literal>ssh</literal>) protocol. To use this successfully, " 37.5602 @@ -6403,7 +5480,7 @@ 37.5603 msgstr "" 37.5604 37.5605 #. type: Content of: <book><chapter><sect1><para> 37.5606 -#: ../en/ch06-collab.xml:512 37.5607 +#: ../en/ch05-collab.xml:512 37.5608 msgid "" 37.5609 "If you're not familiar with ssh, it's a network protocol that lets you " 37.5610 "securely communicate with another computer. To use it with Mercurial, you'll " 37.5611 @@ -6412,31 +5489,31 @@ 37.5612 msgstr "" 37.5613 37.5614 #. type: Content of: <book><chapter><sect1><para> 37.5615 -#: ../en/ch06-collab.xml:518 37.5616 +#: ../en/ch05-collab.xml:518 37.5617 msgid "" 37.5618 "(If you <emphasis>are</emphasis> familiar with ssh, you'll probably find some " 37.5619 "of the material that follows to be elementary in nature.)" 37.5620 msgstr "" 37.5621 37.5622 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5623 -#: ../en/ch06-collab.xml:523 37.5624 +#: ../en/ch05-collab.xml:523 37.5625 msgid "How to read and write ssh URLs" 37.5626 msgstr "如何读写 ssh 路径" 37.5627 37.5628 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5629 -#: ../en/ch06-collab.xml:525 37.5630 +#: ../en/ch05-collab.xml:525 37.5631 msgid "An ssh URL tends to look like this:" 37.5632 msgstr "" 37.5633 37.5634 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.5635 -#: ../en/ch06-collab.xml:528 37.5636 +#: ../en/ch05-collab.xml:528 37.5637 msgid "" 37.5638 "The <quote><literal>ssh://</literal></quote> part tells Mercurial to use the " 37.5639 "ssh protocol." 37.5640 msgstr "" 37.5641 37.5642 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.5643 -#: ../en/ch06-collab.xml:531 37.5644 +#: ../en/ch05-collab.xml:531 37.5645 msgid "" 37.5646 "The <quote><literal>bos@</literal></quote> component indicates what username " 37.5647 "to log into the server as. You can leave this out if the remote username is " 37.5648 @@ -6444,28 +5521,28 @@ 37.5649 msgstr "" 37.5650 37.5651 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.5652 -#: ../en/ch06-collab.xml:536 37.5653 +#: ../en/ch05-collab.xml:536 37.5654 msgid "" 37.5655 "The <quote><literal>hg.serpentine.com</literal></quote> gives the hostname of " 37.5656 "the server to log into." 37.5657 msgstr "" 37.5658 37.5659 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.5660 -#: ../en/ch06-collab.xml:540 37.5661 +#: ../en/ch05-collab.xml:540 37.5662 msgid "" 37.5663 "The <quote>:22</quote> identifies the port number to connect to the server " 37.5664 -"on. The default port is 22, so you only need to specify this part if you're " 37.5665 -"<emphasis>not</emphasis> using port 22." 37.5666 +"on. The default port is 22, so you only need to specify a colon and port " 37.5667 +"number if you're <emphasis>not</emphasis> using port 22." 37.5668 msgstr "" 37.5669 37.5670 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.5671 -#: ../en/ch06-collab.xml:545 37.5672 +#: ../en/ch05-collab.xml:545 37.5673 msgid "" 37.5674 "The remainder of the URL is the local path to the repository on the server." 37.5675 msgstr "" 37.5676 37.5677 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5678 -#: ../en/ch06-collab.xml:549 37.5679 +#: ../en/ch05-collab.xml:549 37.5680 msgid "" 37.5681 "There's plenty of scope for confusion with the path component of ssh URLs, as " 37.5682 "there is no standard way for tools to interpret it. Some programs behave " 37.5683 @@ -6475,7 +5552,7 @@ 37.5684 msgstr "" 37.5685 37.5686 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5687 -#: ../en/ch06-collab.xml:556 37.5688 +#: ../en/ch05-collab.xml:556 37.5689 msgid "" 37.5690 "Mercurial treats the path to a repository on the server as relative to the " 37.5691 "remote user's home directory. For example, if user <literal>foo</literal> on " 37.5692 @@ -6486,7 +5563,7 @@ 37.5693 msgstr "" 37.5694 37.5695 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5696 -#: ../en/ch06-collab.xml:565 37.5697 +#: ../en/ch05-collab.xml:565 37.5698 msgid "" 37.5699 "If you want to specify a path relative to another user's home directory, you " 37.5700 "can use a path that starts with a tilde character followed by the user's name " 37.5701 @@ -6494,19 +5571,19 @@ 37.5702 msgstr "" 37.5703 37.5704 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5705 -#: ../en/ch06-collab.xml:571 37.5706 +#: ../en/ch05-collab.xml:571 37.5707 msgid "" 37.5708 "And if you really want to specify an <emphasis>absolute</emphasis> path on " 37.5709 "the server, begin the path component with two slashes, as in this example." 37.5710 msgstr "" 37.5711 37.5712 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5713 -#: ../en/ch06-collab.xml:578 37.5714 +#: ../en/ch05-collab.xml:578 37.5715 msgid "Finding an ssh client for your system" 37.5716 msgstr "为你的系统寻找 ssh 客户端" 37.5717 37.5718 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5719 -#: ../en/ch06-collab.xml:580 37.5720 +#: ../en/ch05-collab.xml:580 37.5721 msgid "" 37.5722 "Almost every Unix-like system comes with OpenSSH preinstalled. If you're " 37.5723 "using such a system, run <literal>which ssh</literal> to find out if the " 37.5724 @@ -6517,50 +5594,50 @@ 37.5725 msgstr "" 37.5726 37.5727 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5728 -#: ../en/ch06-collab.xml:588 37.5729 +#: ../en/ch05-collab.xml:588 37.5730 msgid "" 37.5731 "On Windows, you'll first need to download a suitable ssh client. There are " 37.5732 "two alternatives." 37.5733 msgstr "" 37.5734 37.5735 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5736 -#: ../en/ch06-collab.xml:591 37.5737 +#: ../en/ch05-collab.xml:591 37.5738 msgid "" 37.5739 "Simon Tatham's excellent PuTTY package <citation>web:putty</citation> " 37.5740 "provides a complete suite of ssh client commands." 37.5741 msgstr "" 37.5742 37.5743 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5744 -#: ../en/ch06-collab.xml:595 37.5745 +#: ../en/ch05-collab.xml:595 37.5746 msgid "" 37.5747 "If you have a high tolerance for pain, you can use the Cygwin port of OpenSSH." 37.5748 msgstr "" 37.5749 37.5750 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5751 -#: ../en/ch06-collab.xml:598 37.5752 -msgid "" 37.5753 -"In either case, you'll need to edit your \\hgini\\ file to tell Mercurial " 37.5754 -"where to find the actual client command. For example, if you're using PuTTY, " 37.5755 -"you'll need to use the <command>plink</command> command as a command-line ssh " 37.5756 -"client." 37.5757 +#: ../en/ch05-collab.xml:598 37.5758 +msgid "" 37.5759 +"In either case, you'll need to edit your <filename role=\"special\">hg.ini</" 37.5760 +"filename> file to tell Mercurial where to find the actual client command. " 37.5761 +"For example, if you're using PuTTY, you'll need to use the <command>plink</" 37.5762 +"command> command as a command-line ssh client." 37.5763 msgstr "" 37.5764 37.5765 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.5766 -#: ../en/ch06-collab.xml:607 37.5767 +#: ../en/ch05-collab.xml:608 37.5768 msgid "" 37.5769 "The path to <command>plink</command> shouldn't contain any whitespace " 37.5770 "characters, or Mercurial may not be able to run it correctly (so putting it " 37.5771 -"in <filename class=\"directory\">C:\\\\Program Files</filename> is probably " 37.5772 -"not a good idea)." 37.5773 -msgstr "" 37.5774 - 37.5775 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.5776 -#: ../en/ch06-collab.xml:616 37.5777 +"in <filename class=\"directory\">C:\\Program Files</filename> is probably not " 37.5778 +"a good idea)." 37.5779 +msgstr "" 37.5780 + 37.5781 +#. type: Content of: <book><chapter><sect1><sect2><title> 37.5782 +#: ../en/ch05-collab.xml:617 37.5783 msgid "Generating a key pair" 37.5784 msgstr "产生密钥对" 37.5785 37.5786 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5787 -#: ../en/ch06-collab.xml:618 37.5788 +#: ../en/ch05-collab.xml:619 37.5789 msgid "" 37.5790 "To avoid the need to repetitively type a password every time you need to use " 37.5791 "your ssh client, I recommend generating a key pair. On a Unix-like system, " 37.5792 @@ -6570,7 +5647,7 @@ 37.5793 msgstr "" 37.5794 37.5795 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5796 -#: ../en/ch06-collab.xml:626 37.5797 +#: ../en/ch05-collab.xml:627 37.5798 msgid "" 37.5799 "When you generate a key pair, it's usually <emphasis>highly</emphasis> " 37.5800 "advisable to protect it with a passphrase. (The only time that you might not " 37.5801 @@ -6579,7 +5656,7 @@ 37.5802 msgstr "" 37.5803 37.5804 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5805 -#: ../en/ch06-collab.xml:632 37.5806 +#: ../en/ch05-collab.xml:633 37.5807 msgid "" 37.5808 "Simply generating a key pair isn't enough, however. You'll need to add the " 37.5809 "public key to the set of authorised keys for whatever user you're logging in " 37.5810 @@ -6590,7 +5667,7 @@ 37.5811 msgstr "" 37.5812 37.5813 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5814 -#: ../en/ch06-collab.xml:641 37.5815 +#: ../en/ch05-collab.xml:642 37.5816 msgid "" 37.5817 "On a Unix-like system, your public key will have a <filename>.pub</filename> " 37.5818 "extension. If you're using <command>puttygen</command> on Windows, you can " 37.5819 @@ -6600,12 +5677,12 @@ 37.5820 msgstr "" 37.5821 37.5822 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5823 -#: ../en/ch06-collab.xml:650 37.5824 +#: ../en/ch05-collab.xml:651 37.5825 msgid "Using an authentication agent" 37.5826 msgstr "使用认证代理" 37.5827 37.5828 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5829 -#: ../en/ch06-collab.xml:652 37.5830 +#: ../en/ch05-collab.xml:653 37.5831 msgid "" 37.5832 "An authentication agent is a daemon that stores passphrases in memory (so it " 37.5833 "will forget passphrases if you log out and log back in again). An ssh client " 37.5834 @@ -6617,7 +5694,7 @@ 37.5835 msgstr "" 37.5836 37.5837 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5838 -#: ../en/ch06-collab.xml:661 37.5839 +#: ../en/ch05-collab.xml:662 37.5840 msgid "" 37.5841 "The downside of storing passphrases in an agent is that it's possible for a " 37.5842 "well-prepared attacker to recover the plain text of your passphrases, in some " 37.5843 @@ -6627,7 +5704,7 @@ 37.5844 msgstr "" 37.5845 37.5846 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5847 -#: ../en/ch06-collab.xml:668 37.5848 +#: ../en/ch05-collab.xml:669 37.5849 msgid "" 37.5850 "On Unix-like systems, the agent is called <command>ssh-agent</command>, and " 37.5851 "it's often run automatically for you when you log in. You'll need to use the " 37.5852 @@ -6638,12 +5715,12 @@ 37.5853 msgstr "" 37.5854 37.5855 #. type: Content of: <book><chapter><sect1><sect2><title> 37.5856 -#: ../en/ch06-collab.xml:679 37.5857 +#: ../en/ch05-collab.xml:680 37.5858 msgid "Configuring the server side properly" 37.5859 msgstr "正确配置服务器端" 37.5860 37.5861 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5862 -#: ../en/ch06-collab.xml:681 37.5863 +#: ../en/ch05-collab.xml:682 37.5864 msgid "" 37.5865 "Because ssh can be fiddly to set up if you're new to it, there's a variety of " 37.5866 "things that can go wrong. Add Mercurial on top, and there's plenty more " 37.5867 @@ -6653,7 +5730,7 @@ 37.5868 msgstr "" 37.5869 37.5870 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5871 -#: ../en/ch06-collab.xml:689 37.5872 +#: ../en/ch05-collab.xml:690 37.5873 msgid "" 37.5874 "Before you try using Mercurial to talk to an ssh server, it's best to make " 37.5875 "sure that you can use the normal <command>ssh</command> or <command>putty</" 37.5876 @@ -6666,7 +5743,7 @@ 37.5877 msgstr "" 37.5878 37.5879 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5880 -#: ../en/ch06-collab.xml:700 37.5881 +#: ../en/ch05-collab.xml:701 37.5882 msgid "" 37.5883 "The first thing to be sure of on the server side is that you can actually log " 37.5884 "in from another machine at all. If you can't use <command>ssh</command> or " 37.5885 @@ -6675,7 +5752,7 @@ 37.5886 msgstr "" 37.5887 37.5888 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5889 -#: ../en/ch06-collab.xml:707 37.5890 +#: ../en/ch05-collab.xml:708 37.5891 msgid "" 37.5892 "If you get a <quote>connection refused</quote> error, either there isn't an " 37.5893 "SSH daemon running on the server at all, or it's inaccessible due to firewall " 37.5894 @@ -6683,7 +5760,7 @@ 37.5895 msgstr "" 37.5896 37.5897 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5898 -#: ../en/ch06-collab.xml:712 37.5899 +#: ../en/ch05-collab.xml:713 37.5900 msgid "" 37.5901 "If you get a <quote>no route to host</quote> error, you either have an " 37.5902 "incorrect address for the server or a seriously locked down firewall that " 37.5903 @@ -6691,7 +5768,7 @@ 37.5904 msgstr "" 37.5905 37.5906 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5907 -#: ../en/ch06-collab.xml:717 37.5908 +#: ../en/ch05-collab.xml:718 37.5909 msgid "" 37.5910 "If you get a <quote>permission denied</quote> error, you may have mistyped " 37.5911 "the username on the server, or you could have mistyped your key's passphrase " 37.5912 @@ -6699,7 +5776,7 @@ 37.5913 msgstr "" 37.5914 37.5915 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5916 -#: ../en/ch06-collab.xml:722 37.5917 +#: ../en/ch05-collab.xml:723 37.5918 msgid "" 37.5919 "In summary, if you're having trouble talking to the server's ssh daemon, " 37.5920 "first make sure that one is running at all. On many systems it will be " 37.5921 @@ -6711,7 +5788,7 @@ 37.5922 msgstr "" 37.5923 37.5924 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5925 -#: ../en/ch06-collab.xml:732 37.5926 +#: ../en/ch05-collab.xml:733 37.5927 msgid "" 37.5928 "If you're using an authentication agent on the client side to store " 37.5929 "passphrases for your keys, you ought to be able to log into the server " 37.5930 @@ -6720,26 +5797,26 @@ 37.5931 msgstr "" 37.5932 37.5933 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5934 -#: ../en/ch06-collab.xml:738 37.5935 +#: ../en/ch05-collab.xml:739 37.5936 msgid "" 37.5937 "You might have forgotten to use <command>ssh-add</command> or " 37.5938 "<command>pageant</command> to store the passphrase." 37.5939 msgstr "" 37.5940 37.5941 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5942 -#: ../en/ch06-collab.xml:742 37.5943 +#: ../en/ch05-collab.xml:743 37.5944 msgid "You might have stored the passphrase for the wrong key." 37.5945 msgstr "" 37.5946 37.5947 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5948 -#: ../en/ch06-collab.xml:745 37.5949 +#: ../en/ch05-collab.xml:746 37.5950 msgid "" 37.5951 "If you're being prompted for the remote user's password, there are another " 37.5952 "few possible problems to check." 37.5953 msgstr "" 37.5954 37.5955 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5956 -#: ../en/ch06-collab.xml:748 37.5957 +#: ../en/ch05-collab.xml:749 37.5958 msgid "" 37.5959 "Either the user's home directory or their <filename role=\"special\" class=" 37.5960 "\"directory\">.ssh</filename> directory might have excessively liberal " 37.5961 @@ -6750,7 +5827,7 @@ 37.5962 msgstr "" 37.5963 37.5964 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.5965 -#: ../en/ch06-collab.xml:757 37.5966 +#: ../en/ch05-collab.xml:758 37.5967 msgid "" 37.5968 "The user's <filename role=\"special\">authorized_keys</filename> file may " 37.5969 "have a problem. If anyone other than the user owns or can write to that file, " 37.5970 @@ -6758,7 +5835,7 @@ 37.5971 msgstr "" 37.5972 37.5973 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5974 -#: ../en/ch06-collab.xml:764 37.5975 +#: ../en/ch05-collab.xml:765 37.5976 msgid "" 37.5977 "In the ideal world, you should be able to run the following command " 37.5978 "successfully, and it should print exactly one line of output, the current " 37.5979 @@ -6766,7 +5843,7 @@ 37.5980 msgstr "" 37.5981 37.5982 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5983 -#: ../en/ch06-collab.xml:769 37.5984 +#: ../en/ch05-collab.xml:770 37.5985 msgid "" 37.5986 "If, on your server, you have login scripts that print banners or other junk " 37.5987 "even when running non-interactive commands like this, you should fix them " 37.5988 @@ -6781,7 +5858,7 @@ 37.5989 msgstr "" 37.5990 37.5991 #. type: Content of: <book><chapter><sect1><sect2><para> 37.5992 -#: ../en/ch06-collab.xml:783 37.5993 +#: ../en/ch05-collab.xml:784 37.5994 msgid "" 37.5995 "Once you've verified that plain old ssh is working with your server, the next " 37.5996 "step is to ensure that Mercurial runs on the server. The following command " 37.5997 @@ -6789,7 +5866,7 @@ 37.5998 msgstr "" 37.5999 37.6000 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6001 -#: ../en/ch06-collab.xml:788 37.6002 +#: ../en/ch05-collab.xml:791 37.6003 msgid "" 37.6004 "If you see an error message instead of normal <command role=\"hg-cmd\">hg " 37.6005 "version</command> output, this is usually because you haven't installed " 37.6006 @@ -6799,21 +5876,21 @@ 37.6007 msgstr "" 37.6008 37.6009 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6010 -#: ../en/ch06-collab.xml:795 37.6011 +#: ../en/ch05-collab.xml:798 37.6012 msgid "" 37.6013 "Is Mercurial really installed on the server at all? I know this sounds " 37.6014 "trivial, but it's worth checking!" 37.6015 msgstr "" 37.6016 37.6017 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6018 -#: ../en/ch06-collab.xml:799 37.6019 +#: ../en/ch05-collab.xml:802 37.6020 msgid "" 37.6021 "Maybe your shell's search path (usually set via the <envar>PATH</envar> " 37.6022 "environment variable) is simply misconfigured." 37.6023 msgstr "" 37.6024 37.6025 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6026 -#: ../en/ch06-collab.xml:803 37.6027 +#: ../en/ch05-collab.xml:806 37.6028 msgid "" 37.6029 "Perhaps your <envar>PATH</envar> environment variable is only being set to " 37.6030 "point to the location of the <command>hg</command> executable if the login " 37.6031 @@ -6822,7 +5899,7 @@ 37.6032 msgstr "" 37.6033 37.6034 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6035 -#: ../en/ch06-collab.xml:810 37.6036 +#: ../en/ch05-collab.xml:813 37.6037 msgid "" 37.6038 "The <envar>PYTHONPATH</envar> environment variable may need to contain the " 37.6039 "path to the Mercurial Python modules. It might not be set at all; it could " 37.6040 @@ -6830,7 +5907,7 @@ 37.6041 msgstr "" 37.6042 37.6043 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6044 -#: ../en/ch06-collab.xml:817 37.6045 +#: ../en/ch05-collab.xml:820 37.6046 msgid "" 37.6047 "If you can run <command role=\"hg-cmd\">hg version</command> over an ssh " 37.6048 "connection, well done! You've got the server and client sorted out. You " 37.6049 @@ -6841,12 +5918,12 @@ 37.6050 msgstr "" 37.6051 37.6052 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6053 -#: ../en/ch06-collab.xml:827 37.6054 +#: ../en/ch05-collab.xml:830 37.6055 msgid "Using compression with ssh" 37.6056 msgstr "通过 ssh 使用压缩" 37.6057 37.6058 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6059 -#: ../en/ch06-collab.xml:829 37.6060 +#: ../en/ch05-collab.xml:832 37.6061 msgid "" 37.6062 "Mercurial does not compress data when it uses the ssh protocol, because the " 37.6063 "ssh protocol can transparently compress data. However, the default behaviour " 37.6064 @@ -6854,7 +5931,7 @@ 37.6065 msgstr "" 37.6066 37.6067 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6068 -#: ../en/ch06-collab.xml:834 37.6069 +#: ../en/ch05-collab.xml:837 37.6070 msgid "" 37.6071 "Over any network other than a fast LAN (even a wireless network), using " 37.6072 "compression is likely to significantly speed up Mercurial's network " 37.6073 @@ -6864,16 +5941,16 @@ 37.6074 msgstr "" 37.6075 37.6076 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6077 -#: ../en/ch06-collab.xml:841 37.6078 +#: ../en/ch05-collab.xml:844 37.6079 msgid "" 37.6080 "Both <command>ssh</command> and <command>plink</command> accept a <option " 37.6081 "role=\"cmd-opt-ssh\">-C</option> option which turns on compression. You can " 37.6082 -"easily edit your <filename role=\"special\"> /.hgrc</filename>\\ to enable " 37.6083 +"easily edit your <filename role=\"special\">~/.hgrc</filename> to enable " 37.6084 "compression for all of Mercurial's uses of the ssh protocol." 37.6085 msgstr "" 37.6086 37.6087 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6088 -#: ../en/ch06-collab.xml:848 37.6089 +#: ../en/ch05-collab.xml:852 37.6090 msgid "" 37.6091 "If you use <command>ssh</command>, you can configure it to always use " 37.6092 "compression when talking to your server. To do this, edit your <filename " 37.6093 @@ -6882,7 +5959,7 @@ 37.6094 msgstr "" 37.6095 37.6096 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6097 -#: ../en/ch06-collab.xml:855 37.6098 +#: ../en/ch05-collab.xml:860 37.6099 msgid "" 37.6100 "This defines an alias, <literal>hg</literal>. When you use it on the " 37.6101 "<command>ssh</command> command line or in a Mercurial <literal>ssh</literal>-" 37.6102 @@ -6892,19 +5969,19 @@ 37.6103 msgstr "" 37.6104 37.6105 #. type: Content of: <book><chapter><sect1><title> 37.6106 -#: ../en/ch06-collab.xml:866 37.6107 +#: ../en/ch05-collab.xml:871 37.6108 msgid "Serving over HTTP using CGI" 37.6109 msgstr "使用 CGI 通过 HTTP 提供服务" 37.6110 37.6111 #. type: Content of: <book><chapter><sect1><para> 37.6112 -#: ../en/ch06-collab.xml:868 37.6113 +#: ../en/ch05-collab.xml:873 37.6114 msgid "" 37.6115 "Depending on how ambitious you are, configuring Mercurial's CGI interface can " 37.6116 "take anything from a few moments to several hours." 37.6117 msgstr "" 37.6118 37.6119 #. type: Content of: <book><chapter><sect1><para> 37.6120 -#: ../en/ch06-collab.xml:872 37.6121 +#: ../en/ch05-collab.xml:877 37.6122 msgid "" 37.6123 "We'll begin with the simplest of examples, and work our way towards a more " 37.6124 "complex configuration. Even for the most basic case, you're almost certainly " 37.6125 @@ -6912,7 +5989,7 @@ 37.6126 msgstr "" 37.6127 37.6128 #. type: Content of: <book><chapter><sect1><note><para> 37.6129 -#: ../en/ch06-collab.xml:878 37.6130 +#: ../en/ch05-collab.xml:883 37.6131 msgid "" 37.6132 "Configuring a web server is a complex, fiddly, and highly system-dependent " 37.6133 "activity. I can't possibly give you instructions that will cover anything " 37.6134 @@ -6922,33 +5999,33 @@ 37.6135 msgstr "" 37.6136 37.6137 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6138 -#: ../en/ch06-collab.xml:888 37.6139 +#: ../en/ch05-collab.xml:893 37.6140 msgid "Web server configuration checklist" 37.6141 msgstr "Web 服务器配置检查表" 37.6142 37.6143 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6144 -#: ../en/ch06-collab.xml:890 37.6145 +#: ../en/ch05-collab.xml:895 37.6146 msgid "" 37.6147 "Before you continue, do take a few moments to check a few aspects of your " 37.6148 "system's setup." 37.6149 msgstr "" 37.6150 37.6151 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.6152 -#: ../en/ch06-collab.xml:894 37.6153 +#: ../en/ch05-collab.xml:899 37.6154 msgid "" 37.6155 "Do you have a web server installed at all? Mac OS X ships with Apache, but " 37.6156 "many other systems may not have a web server installed." 37.6157 msgstr "" 37.6158 37.6159 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.6160 -#: ../en/ch06-collab.xml:898 37.6161 +#: ../en/ch05-collab.xml:903 37.6162 msgid "" 37.6163 "If you have a web server installed, is it actually running? On most systems, " 37.6164 "even if one is present, it will be disabled by default." 37.6165 msgstr "" 37.6166 37.6167 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.6168 -#: ../en/ch06-collab.xml:902 37.6169 +#: ../en/ch05-collab.xml:907 37.6170 msgid "" 37.6171 "Is your server configured to allow you to run CGI programs in the directory " 37.6172 "where you plan to do so? Most servers default to explicitly disabling the " 37.6173 @@ -6956,7 +6033,7 @@ 37.6174 msgstr "" 37.6175 37.6176 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6177 -#: ../en/ch06-collab.xml:908 37.6178 +#: ../en/ch05-collab.xml:913 37.6179 msgid "" 37.6180 "If you don't have a web server installed, and don't have substantial " 37.6181 "experience configuring Apache, you should consider using the " 37.6182 @@ -6969,22 +6046,22 @@ 37.6183 msgstr "" 37.6184 37.6185 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6186 -#: ../en/ch06-collab.xml:921 37.6187 +#: ../en/ch05-collab.xml:926 37.6188 msgid "Basic CGI configuration" 37.6189 msgstr "基本 CGI 配置" 37.6190 37.6191 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6192 -#: ../en/ch06-collab.xml:923 37.6193 +#: ../en/ch05-collab.xml:928 37.6194 msgid "" 37.6195 "On Unix-like systems, it's common for users to have a subdirectory named " 37.6196 "something like <filename class=\"directory\">public_html</filename> in their " 37.6197 "home directory, from which they can serve up web pages. A file named " 37.6198 "<filename>foo</filename> in this directory will be accessible at a URL of the " 37.6199 -"form <literal>http://www.example.com/\\ {</literal>username/foo}." 37.6200 -msgstr "" 37.6201 - 37.6202 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.6203 -#: ../en/ch06-collab.xml:932 37.6204 +"form <literal>http://www.example.com/username/foo</literal>." 37.6205 +msgstr "" 37.6206 + 37.6207 +#. type: Content of: <book><chapter><sect1><sect2><para> 37.6208 +#: ../en/ch05-collab.xml:936 37.6209 msgid "" 37.6210 "To get started, find the <filename role=\"special\">hgweb.cgi</filename> " 37.6211 "script that should be present in your Mercurial installation. If you can't " 37.6212 @@ -6994,14 +6071,14 @@ 37.6213 msgstr "" 37.6214 37.6215 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6216 -#: ../en/ch06-collab.xml:939 ../en/ch06-collab.xml:1112 37.6217 +#: ../en/ch05-collab.xml:943 ../en/ch05-collab.xml:1112 37.6218 msgid "" 37.6219 "You'll need to copy this script into your <filename class=\"directory" 37.6220 "\">public_html</filename> directory, and ensure that it's executable." 37.6221 msgstr "" 37.6222 37.6223 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6224 -#: ../en/ch06-collab.xml:944 37.6225 +#: ../en/ch05-collab.xml:948 37.6226 msgid "" 37.6227 "The <literal>755</literal> argument to <command>chmod</command> is a little " 37.6228 "more general than just making the script executable: it ensures that the " 37.6229 @@ -7014,12 +6091,12 @@ 37.6230 msgstr "" 37.6231 37.6232 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6233 -#: ../en/ch06-collab.xml:958 37.6234 +#: ../en/ch05-collab.xml:962 37.6235 msgid "What could <emphasis>possibly</emphasis> go wrong?" 37.6236 msgstr "什么<emphasis>可能</emphasis>会出错?" 37.6237 37.6238 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6239 -#: ../en/ch06-collab.xml:961 37.6240 +#: ../en/ch05-collab.xml:965 37.6241 msgid "" 37.6242 "Once you've copied the CGI script into place, go into a web browser, and try " 37.6243 "to open the URL <ulink url=\"http://myhostname/ myuser/hgweb.cgi\">http://" 37.6244 @@ -7033,7 +6110,7 @@ 37.6245 msgstr "" 37.6246 37.6247 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6248 -#: ../en/ch06-collab.xml:975 37.6249 +#: ../en/ch05-collab.xml:979 37.6250 msgid "" 37.6251 "Your web server may have per-user directories disabled. If you're using " 37.6252 "Apache, search your config file for a <literal>UserDir</literal> directive. " 37.6253 @@ -7046,7 +6123,7 @@ 37.6254 msgstr "" 37.6255 37.6256 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6257 -#: ../en/ch06-collab.xml:986 37.6258 +#: ../en/ch05-collab.xml:990 37.6259 msgid "" 37.6260 "Your file access permissions may be too restrictive. The web server must be " 37.6261 "able to traverse your home directory and directories under your <filename " 37.6262 @@ -7056,7 +6133,7 @@ 37.6263 msgstr "" 37.6264 37.6265 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6266 -#: ../en/ch06-collab.xml:996 37.6267 +#: ../en/ch05-collab.xml:1000 37.6268 msgid "" 37.6269 "The other possibility with permissions is that you might get a completely " 37.6270 "empty window when you try to load the script. In this case, it's likely that " 37.6271 @@ -7066,15 +6143,21 @@ 37.6272 msgstr "" 37.6273 37.6274 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6275 -#: ../en/ch06-collab.xml:1003 37.6276 +#: ../en/ch05-collab.xml:1007 37.6277 msgid "" 37.6278 "Your web server may be configured to disallow execution of CGI programs in " 37.6279 "your per-user web directory. Here's Apache's default per-user configuration " 37.6280 "from my Fedora system." 37.6281 msgstr "" 37.6282 37.6283 +#. type: CDATA 37.6284 +#: ../en/ch05-collab.xml:1012 37.6285 +#, no-wrap 37.6286 +msgid "&ch06-apache-config.lst;]]" 37.6287 +msgstr "" 37.6288 + 37.6289 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6290 -#: ../en/ch06-collab.xml:1014 37.6291 +#: ../en/ch05-collab.xml:1014 37.6292 msgid "" 37.6293 "If you find a similar-looking <literal>Directory</literal> group in your " 37.6294 "Apache configuration, the directive to look at inside it is <literal>Options</" 37.6295 @@ -7083,7 +6166,7 @@ 37.6296 msgstr "" 37.6297 37.6298 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6299 -#: ../en/ch06-collab.xml:1021 37.6300 +#: ../en/ch05-collab.xml:1021 37.6301 msgid "" 37.6302 "If you find that Apache serves you the text of the CGI script instead of " 37.6303 "executing it, you may need to either uncomment (if already present) or add a " 37.6304 @@ -7091,7 +6174,7 @@ 37.6305 msgstr "" 37.6306 37.6307 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6308 -#: ../en/ch06-collab.xml:1027 37.6309 +#: ../en/ch05-collab.xml:1027 37.6310 msgid "" 37.6311 "The next possibility is that you might be served with a colourful Python " 37.6312 "backtrace claiming that it can't import a <literal>mercurial</literal>-" 37.6313 @@ -7106,7 +6189,7 @@ 37.6314 msgstr "" 37.6315 37.6316 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6317 -#: ../en/ch06-collab.xml:1041 37.6318 +#: ../en/ch05-collab.xml:1041 37.6319 msgid "" 37.6320 "Finally, you are <emphasis>certain</emphasis> to by served with another " 37.6321 "colourful Python backtrace: this one will complain that it can't find " 37.6322 @@ -7117,19 +6200,19 @@ 37.6323 msgstr "" 37.6324 37.6325 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6326 -#: ../en/ch06-collab.xml:1051 37.6327 +#: ../en/ch05-collab.xml:1051 37.6328 msgid "" 37.6329 "At this point, when you try to reload the page, you should be presented with " 37.6330 "a nice HTML view of your repository's history. Whew!" 37.6331 msgstr "" 37.6332 37.6333 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6334 -#: ../en/ch06-collab.xml:1057 37.6335 +#: ../en/ch05-collab.xml:1057 37.6336 msgid "Configuring lighttpd" 37.6337 msgstr "配置 lighttpd" 37.6338 37.6339 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6340 -#: ../en/ch06-collab.xml:1059 37.6341 +#: ../en/ch05-collab.xml:1059 37.6342 msgid "" 37.6343 "To be exhaustive in my experiments, I tried configuring the increasingly " 37.6344 "popular <literal>lighttpd</literal> web server to serve the same repository " 37.6345 @@ -7140,7 +6223,7 @@ 37.6346 msgstr "" 37.6347 37.6348 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6349 -#: ../en/ch06-collab.xml:1069 37.6350 +#: ../en/ch05-collab.xml:1069 37.6351 msgid "" 37.6352 "Once I had Apache running, getting <literal>lighttpd</literal> to serve the " 37.6353 "repository was a snap (in other words, even if you're trying to use " 37.6354 @@ -7152,7 +6235,7 @@ 37.6355 msgstr "" 37.6356 37.6357 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6358 -#: ../en/ch06-collab.xml:1081 37.6359 +#: ../en/ch05-collab.xml:1081 37.6360 msgid "" 37.6361 "With this done, <literal>lighttpd</literal> ran immediately for me. If I had " 37.6362 "configured <literal>lighttpd</literal> before Apache, I'd almost certainly " 37.6363 @@ -7163,12 +6246,12 @@ 37.6364 msgstr "" 37.6365 37.6366 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6367 -#: ../en/ch06-collab.xml:1094 37.6368 +#: ../en/ch05-collab.xml:1094 37.6369 msgid "Sharing multiple repositories with one CGI script" 37.6370 msgstr "使用一个 CGI 脚本共享多个版本库" 37.6371 37.6372 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6373 -#: ../en/ch06-collab.xml:1096 37.6374 +#: ../en/ch05-collab.xml:1096 37.6375 msgid "" 37.6376 "The <filename role=\"special\">hgweb.cgi</filename> script only lets you " 37.6377 "publish a single repository, which is an annoying restriction. If you want " 37.6378 @@ -7178,7 +6261,7 @@ 37.6379 msgstr "" 37.6380 37.6381 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6382 -#: ../en/ch06-collab.xml:1104 37.6383 +#: ../en/ch05-collab.xml:1104 37.6384 msgid "" 37.6385 "The procedure to configure <filename role=\"special\">hgwebdir.cgi</filename> " 37.6386 "is only a little more involved than for <filename role=\"special\">hgweb.cgi</" 37.6387 @@ -7189,7 +6272,7 @@ 37.6388 msgstr "" 37.6389 37.6390 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6391 -#: ../en/ch06-collab.xml:1117 37.6392 +#: ../en/ch05-collab.xml:1117 37.6393 msgid "" 37.6394 "With basic configuration out of the way, try to visit <ulink url=\"http://" 37.6395 "myhostname/ myuser/hgwebdir.cgi\">http://myhostname/ myuser/hgwebdir.cgi</" 37.6396 @@ -7199,7 +6282,7 @@ 37.6397 msgstr "" 37.6398 37.6399 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6400 -#: ../en/ch06-collab.xml:1126 37.6401 +#: ../en/ch05-collab.xml:1126 37.6402 msgid "" 37.6403 "The <filename role=\"special\">hgwebdir.cgi</filename> script relies on an " 37.6404 "external configuration file. By default, it searches for a file named " 37.6405 @@ -7211,7 +6294,7 @@ 37.6406 msgstr "" 37.6407 37.6408 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6409 -#: ../en/ch06-collab.xml:1136 37.6410 +#: ../en/ch05-collab.xml:1136 37.6411 msgid "" 37.6412 "The easiest way to configure <filename role=\"special\">hgwebdir.cgi</" 37.6413 "filename> is with a section named <literal>collections</literal>. This will " 37.6414 @@ -7220,7 +6303,7 @@ 37.6415 msgstr "" 37.6416 37.6417 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6418 -#: ../en/ch06-collab.xml:1144 37.6419 +#: ../en/ch05-collab.xml:1144 37.6420 msgid "" 37.6421 "Mercurial interprets this by looking at the directory name on the " 37.6422 "<emphasis>right</emphasis> hand side of the <quote><literal>=</literal></" 37.6423 @@ -7232,7 +6315,7 @@ 37.6424 msgstr "" 37.6425 37.6426 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6427 -#: ../en/ch06-collab.xml:1153 37.6428 +#: ../en/ch05-collab.xml:1153 37.6429 msgid "" 37.6430 "Given the example above, if we have a repository whose local path is " 37.6431 "<filename class=\"directory\">/my/root/this/repo</filename>, the CGI script " 37.6432 @@ -7246,7 +6329,7 @@ 37.6433 msgstr "" 37.6434 37.6435 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6436 -#: ../en/ch06-collab.xml:1167 37.6437 +#: ../en/ch05-collab.xml:1167 37.6438 msgid "" 37.6439 "If we replace <filename class=\"directory\">/my/root</filename> on the left " 37.6440 "hand side of this example with <filename class=\"directory\">/my</filename>, " 37.6441 @@ -7257,7 +6340,7 @@ 37.6442 msgstr "" 37.6443 37.6444 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6445 -#: ../en/ch06-collab.xml:1177 37.6446 +#: ../en/ch05-collab.xml:1177 37.6447 msgid "" 37.6448 "The <filename role=\"special\">hgwebdir.cgi</filename> script will " 37.6449 "recursively search each directory listed in the <literal>collections</" 37.6450 @@ -7266,7 +6349,7 @@ 37.6451 msgstr "" 37.6452 37.6453 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6454 -#: ../en/ch06-collab.xml:1183 37.6455 +#: ../en/ch05-collab.xml:1183 37.6456 msgid "" 37.6457 "The <literal>collections</literal> mechanism makes it easy to publish many " 37.6458 "repositories in a <quote>fire and forget</quote> manner. You only need to " 37.6459 @@ -7277,12 +6360,12 @@ 37.6460 msgstr "" 37.6461 37.6462 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6463 -#: ../en/ch06-collab.xml:1193 37.6464 +#: ../en/ch05-collab.xml:1193 37.6465 msgid "Explicitly specifying which repositories to publish" 37.6466 msgstr "明确指出要发布的版本库" 37.6467 37.6468 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6469 -#: ../en/ch06-collab.xml:1196 37.6470 +#: ../en/ch05-collab.xml:1196 37.6471 msgid "" 37.6472 "In addition to the <literal>collections</literal> mechanism, the <filename " 37.6473 "role=\"special\">hgwebdir.cgi</filename> script allows you to publish a " 37.6474 @@ -7291,7 +6374,7 @@ 37.6475 msgstr "" 37.6476 37.6477 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6478 -#: ../en/ch06-collab.xml:1204 37.6479 +#: ../en/ch05-collab.xml:1205 37.6480 msgid "" 37.6481 "In this case, the virtual path (the component that will appear in a URL) is " 37.6482 "on the left hand side of each definition, while the path to the repository is " 37.6483 @@ -7301,7 +6384,7 @@ 37.6484 msgstr "" 37.6485 37.6486 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6487 -#: ../en/ch06-collab.xml:1211 37.6488 +#: ../en/ch05-collab.xml:1212 37.6489 msgid "" 37.6490 "If you wish, you can use both the <literal>collections</literal> and " 37.6491 "<literal>paths</literal> mechanisms simultaneously in a single configuration " 37.6492 @@ -7309,7 +6392,7 @@ 37.6493 msgstr "" 37.6494 37.6495 #. type: Content of: <book><chapter><sect1><sect2><sect3><note><para> 37.6496 -#: ../en/ch06-collab.xml:1217 37.6497 +#: ../en/ch05-collab.xml:1218 37.6498 msgid "" 37.6499 "If multiple repositories have the same virtual path, <filename role=\"special" 37.6500 "\">hgwebdir.cgi</filename> will not report an error. Instead, it will behave " 37.6501 @@ -7317,12 +6400,12 @@ 37.6502 msgstr "" 37.6503 37.6504 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6505 -#: ../en/ch06-collab.xml:1226 37.6506 +#: ../en/ch05-collab.xml:1227 37.6507 msgid "Downloading source archives" 37.6508 msgstr "下载源代码档案包" 37.6509 37.6510 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6511 -#: ../en/ch06-collab.xml:1228 37.6512 +#: ../en/ch05-collab.xml:1229 37.6513 msgid "" 37.6514 "Mercurial's web interface lets users download an archive of any revision. " 37.6515 "This archive will contain a snapshot of the working directory as of that " 37.6516 @@ -7330,21 +6413,21 @@ 37.6517 msgstr "" 37.6518 37.6519 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6520 -#: ../en/ch06-collab.xml:1233 37.6521 +#: ../en/ch05-collab.xml:1234 37.6522 msgid "" 37.6523 "By default, this feature is not enabled. To enable it, you'll need to add an " 37.6524 "<envar role=\"rc-item-web\">allow_archive</envar> item to the <literal role=" 37.6525 -"\"rc-web\">web</literal> section of your <filename role=\"special\"> /.hgrc</" 37.6526 +"\"rc-web\">web</literal> section of your <filename role=\"special\">~/.hgrc</" 37.6527 "filename>." 37.6528 msgstr "" 37.6529 37.6530 #. type: Content of: <book><chapter><sect1><sect2><title> 37.6531 -#: ../en/ch06-collab.xml:1241 37.6532 +#: ../en/ch05-collab.xml:1242 37.6533 msgid "Web configuration options" 37.6534 msgstr "Web 配置选项" 37.6535 37.6536 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6537 -#: ../en/ch06-collab.xml:1243 37.6538 +#: ../en/ch05-collab.xml:1244 37.6539 msgid "" 37.6540 "Mercurial's web interfaces (the <command role=\"hg-cmd\">hg serve</command> " 37.6541 "command, and the <filename role=\"special\">hgweb.cgi</filename> and " 37.6542 @@ -7354,7 +6437,7 @@ 37.6543 msgstr "" 37.6544 37.6545 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6546 -#: ../en/ch06-collab.xml:1251 37.6547 +#: ../en/ch05-collab.xml:1252 37.6548 msgid "" 37.6549 "<envar role=\"rc-item-web\">allow_archive</envar>: Determines which (if any) " 37.6550 "archive download mechanisms Mercurial supports. If you enable this feature, " 37.6551 @@ -7364,7 +6447,7 @@ 37.6552 msgstr "" 37.6553 37.6554 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> 37.6555 -#: ../en/ch06-collab.xml:1260 37.6556 +#: ../en/ch05-collab.xml:1261 37.6557 msgid "" 37.6558 "<literal>bz2</literal>: A <command>tar</command> archive, compressed using " 37.6559 "<literal>bzip2</literal> compression. This has the best compression ratio, " 37.6560 @@ -7372,14 +6455,14 @@ 37.6561 msgstr "" 37.6562 37.6563 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> 37.6564 -#: ../en/ch06-collab.xml:1266 37.6565 +#: ../en/ch05-collab.xml:1267 37.6566 msgid "" 37.6567 "<literal>gz</literal>: A <command>tar</command> archive, compressed using " 37.6568 "<literal>gzip</literal> compression." 37.6569 msgstr "" 37.6570 37.6571 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> 37.6572 -#: ../en/ch06-collab.xml:1270 37.6573 +#: ../en/ch05-collab.xml:1271 37.6574 msgid "" 37.6575 "<literal>zip</literal>: A <command>zip</command> archive, compressed using " 37.6576 "LZW compression. This format has the worst compression ratio, but is widely " 37.6577 @@ -7387,7 +6470,7 @@ 37.6578 msgstr "" 37.6579 37.6580 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6581 -#: ../en/ch06-collab.xml:1276 37.6582 +#: ../en/ch05-collab.xml:1277 37.6583 msgid "" 37.6584 "If you provide an empty list, or don't have an <envar role=\"rc-item-web" 37.6585 "\">allow_archive</envar> entry at all, this feature will be disabled. Here " 37.6586 @@ -7395,7 +6478,7 @@ 37.6587 msgstr "" 37.6588 37.6589 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6590 -#: ../en/ch06-collab.xml:1283 37.6591 +#: ../en/ch05-collab.xml:1284 37.6592 msgid "" 37.6593 "<envar role=\"rc-item-web\">allowpull</envar>: Boolean. Determines whether " 37.6594 "the web interface allows remote users to <command role=\"hg-cmd\">hg pull</" 37.6595 @@ -7405,33 +6488,33 @@ 37.6596 msgstr "" 37.6597 37.6598 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6599 -#: ../en/ch06-collab.xml:1292 37.6600 +#: ../en/ch05-collab.xml:1293 37.6601 msgid "" 37.6602 "<envar role=\"rc-item-web\">contact</envar>: String. A free-form (but " 37.6603 "preferably brief) string identifying the person or group in charge of the " 37.6604 "repository. This often contains the name and email address of a person or " 37.6605 "mailing list. It often makes sense to place this entry in a repository's own " 37.6606 "<filename role=\"special\">.hg/hgrc</filename> file, but it can make sense to " 37.6607 -"use in a global <filename role=\"special\"> /.hgrc</filename>\\ if every " 37.6608 +"use in a global <filename role=\"special\">~/.hgrc</filename> if every " 37.6609 "repository has a single maintainer." 37.6610 msgstr "" 37.6611 37.6612 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6613 -#: ../en/ch06-collab.xml:1303 37.6614 +#: ../en/ch05-collab.xml:1304 37.6615 msgid "" 37.6616 "<envar role=\"rc-item-web\">maxchanges</envar>: Integer. The default maximum " 37.6617 "number of changesets to display in a single page of output." 37.6618 msgstr "" 37.6619 37.6620 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6621 -#: ../en/ch06-collab.xml:1307 37.6622 +#: ../en/ch05-collab.xml:1308 37.6623 msgid "" 37.6624 "<envar role=\"rc-item-web\">maxfiles</envar>: Integer. The default maximum " 37.6625 "number of modified files to display in a single page of output." 37.6626 msgstr "" 37.6627 37.6628 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6629 -#: ../en/ch06-collab.xml:1311 37.6630 +#: ../en/ch05-collab.xml:1312 37.6631 msgid "" 37.6632 "<envar role=\"rc-item-web\">stripes</envar>: Integer. If the web interface " 37.6633 "displays alternating <quote>stripes</quote> to make it easier to visually " 37.6634 @@ -7440,7 +6523,7 @@ 37.6635 msgstr "" 37.6636 37.6637 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6638 -#: ../en/ch06-collab.xml:1317 37.6639 +#: ../en/ch05-collab.xml:1318 37.6640 msgid "" 37.6641 "<envar role=\"rc-item-web\">style</envar>: Controls the template Mercurial " 37.6642 "uses to display the web interface. Mercurial ships with two web templates, " 37.6643 @@ -7451,7 +6534,7 @@ 37.6644 msgstr "" 37.6645 37.6646 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.6647 -#: ../en/ch06-collab.xml:1328 37.6648 +#: ../en/ch05-collab.xml:1330 37.6649 msgid "" 37.6650 "<envar role=\"rc-item-web\">templates</envar>: Path. The directory in which " 37.6651 "to search for template files. By default, Mercurial searches in the " 37.6652 @@ -7459,32 +6542,32 @@ 37.6653 msgstr "" 37.6654 37.6655 #. type: Content of: <book><chapter><sect1><sect2><para> 37.6656 -#: ../en/ch06-collab.xml:1333 37.6657 +#: ../en/ch05-collab.xml:1335 37.6658 msgid "" 37.6659 "If you are using <filename role=\"special\">hgwebdir.cgi</filename>, you can " 37.6660 "place a few configuration items in a <literal role=\"rc-web\">web</literal> " 37.6661 "section of the <filename role=\"special\">hgweb.config</filename> file " 37.6662 -"instead of a <filename role=\"special\"> /.hgrc</filename>\\ file, for " 37.6663 +"instead of a <filename role=\"special\">~/.hgrc</filename> file, for " 37.6664 "convenience. These items are <envar role=\"rc-item-web\">motd</envar> and " 37.6665 "<envar role=\"rc-item-web\">style</envar>." 37.6666 msgstr "" 37.6667 37.6668 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6669 -#: ../en/ch06-collab.xml:1344 37.6670 +#: ../en/ch05-collab.xml:1346 37.6671 msgid "Options specific to an individual repository" 37.6672 msgstr "针对单个版本库的选项" 37.6673 37.6674 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6675 -#: ../en/ch06-collab.xml:1346 37.6676 +#: ../en/ch05-collab.xml:1348 37.6677 msgid "" 37.6678 "A few <literal role=\"rc-web\">web</literal> configuration items ought to be " 37.6679 "placed in a repository's local <filename role=\"special\">.hg/hgrc</" 37.6680 -"filename>, rather than a user's or global <filename role=\"special\"> /.hgrc</" 37.6681 +"filename>, rather than a user's or global <filename role=\"special\">~/.hgrc</" 37.6682 "filename>." 37.6683 msgstr "" 37.6684 37.6685 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6686 -#: ../en/ch06-collab.xml:1352 37.6687 +#: ../en/ch05-collab.xml:1353 37.6688 msgid "" 37.6689 "<envar role=\"rc-item-web\">description</envar>: String. A free-form (but " 37.6690 "preferably brief) string that describes the contents or purpose of the " 37.6691 @@ -7492,7 +6575,7 @@ 37.6692 msgstr "" 37.6693 37.6694 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6695 -#: ../en/ch06-collab.xml:1357 37.6696 +#: ../en/ch05-collab.xml:1358 37.6697 msgid "" 37.6698 "<envar role=\"rc-item-web\">name</envar>: String. The name to use for the " 37.6699 "repository in the web interface. This overrides the default name, which is " 37.6700 @@ -7500,21 +6583,21 @@ 37.6701 msgstr "" 37.6702 37.6703 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6704 -#: ../en/ch06-collab.xml:1365 37.6705 +#: ../en/ch05-collab.xml:1366 37.6706 msgid "" 37.6707 "Options specific to the <command role=\"hg-cmd\">hg serve</command> command" 37.6708 msgstr "命令 <command role=\"hg-cmd\">hg serve</command> 的选项" 37.6709 37.6710 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6711 -#: ../en/ch06-collab.xml:1368 37.6712 +#: ../en/ch05-collab.xml:1369 37.6713 msgid "" 37.6714 "Some of the items in the <literal role=\"rc-web\">web</literal> section of a " 37.6715 -"<filename role=\"special\"> /.hgrc</filename>\\ file are only for use with " 37.6716 -"the <command role=\"hg-cmd\">hg serve</command> command." 37.6717 +"<filename role=\"special\">~/.hgrc</filename> file are only for use with the " 37.6718 +"<command role=\"hg-cmd\">hg serve</command> command." 37.6719 msgstr "" 37.6720 37.6721 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6722 -#: ../en/ch06-collab.xml:1374 37.6723 +#: ../en/ch05-collab.xml:1375 37.6724 msgid "" 37.6725 "<envar role=\"rc-item-web\">accesslog</envar>: Path. The name of a file into " 37.6726 "which to write an access log. By default, the <command role=\"hg-cmd\">hg " 37.6727 @@ -7524,7 +6607,7 @@ 37.6728 msgstr "" 37.6729 37.6730 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6731 -#: ../en/ch06-collab.xml:1382 37.6732 +#: ../en/ch05-collab.xml:1383 37.6733 msgid "" 37.6734 "<envar role=\"rc-item-web\">address</envar>: String. The local address on " 37.6735 "which the server should listen for incoming connections. By default, the " 37.6736 @@ -7532,7 +6615,7 @@ 37.6737 msgstr "" 37.6738 37.6739 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6740 -#: ../en/ch06-collab.xml:1387 37.6741 +#: ../en/ch05-collab.xml:1388 37.6742 msgid "" 37.6743 "<envar role=\"rc-item-web\">errorlog</envar>: Path. The name of a file into " 37.6744 "which to write an error log. By default, the <command role=\"hg-cmd\">hg " 37.6745 @@ -7541,30 +6624,31 @@ 37.6746 msgstr "" 37.6747 37.6748 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6749 -#: ../en/ch06-collab.xml:1393 37.6750 +#: ../en/ch05-collab.xml:1394 37.6751 msgid "" 37.6752 "<envar role=\"rc-item-web\">ipv6</envar>: Boolean. Whether to use the IPv6 " 37.6753 "protocol. By default, IPv6 is not used." 37.6754 msgstr "" 37.6755 37.6756 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.6757 -#: ../en/ch06-collab.xml:1397 37.6758 +#: ../en/ch05-collab.xml:1398 37.6759 msgid "" 37.6760 "<envar role=\"rc-item-web\">port</envar>: Integer. The TCP port number on " 37.6761 "which the server should listen. The default port number used is 8000." 37.6762 msgstr "" 37.6763 37.6764 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.6765 -#: ../en/ch06-collab.xml:1404 37.6766 -msgid "" 37.6767 -"Choosing the right <filename role=\"special\"> /.hgrc</filename>\\ file to " 37.6768 -"add <literal role=\"rc-web\">web</literal> items to" 37.6769 +#: ../en/ch05-collab.xml:1405 37.6770 +#, fuzzy 37.6771 +msgid "" 37.6772 +"Choosing the right <filename role=\"special\">~/.hgrc</filename> file to add " 37.6773 +"<literal role=\"rc-web\">web</literal> items to" 37.6774 msgstr "" 37.6775 "选择正确的 <filename role=\"special\"> /.hgrc</filename> 文件增加到 <literal " 37.6776 "role=\"rc-web\">web</literal> 条目" 37.6777 37.6778 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6779 -#: ../en/ch06-collab.xml:1408 37.6780 +#: ../en/ch05-collab.xml:1409 37.6781 msgid "" 37.6782 "It is important to remember that a web server like Apache or " 37.6783 "<literal>lighttpd</literal> will run under a user ID that is different to " 37.6784 @@ -7573,38 +6657,37 @@ 37.6785 msgstr "" 37.6786 37.6787 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.6788 -#: ../en/ch06-collab.xml:1415 37.6789 +#: ../en/ch05-collab.xml:1416 37.6790 msgid "" 37.6791 "If you add <literal role=\"rc-web\">web</literal> items to your own personal " 37.6792 -"<filename role=\"special\"> /.hgrc</filename>\\ file, CGI scripts won't read " 37.6793 -"that <filename role=\"special\"> /.hgrc</filename>\\ file. Those settings " 37.6794 -"will thus only affect the behaviour of the <command role=\"hg-cmd\">hg serve</" 37.6795 +"<filename role=\"special\">~/.hgrc</filename> file, CGI scripts won't read " 37.6796 +"that <filename role=\"special\">~/.hgrc</filename> file. Those settings will " 37.6797 +"thus only affect the behaviour of the <command role=\"hg-cmd\">hg serve</" 37.6798 "command> command when you run it. To cause CGI scripts to see your settings, " 37.6799 -"either create a <filename role=\"special\"> /.hgrc</filename>\\ file in the " 37.6800 +"either create a <filename role=\"special\">~/.hgrc</filename> file in the " 37.6801 "home directory of the user ID that runs your web server, or add those " 37.6802 -"settings to a system-wide <filename role=\"special\"> /.hgrc</filename>\\ " 37.6803 -"file." 37.6804 +"settings to a system-wide <filename role=\"special\">~/.hgrc</filename> file." 37.6805 msgstr "" 37.6806 37.6807 #. type: Content of: <book><chapter><title> 37.6808 -#: ../en/ch07-filenames.xml:5 37.6809 +#: ../en/ch06-filenames.xml:5 37.6810 msgid "File names and pattern matching" 37.6811 msgstr "文件名称与模式匹配" 37.6812 37.6813 #. type: Content of: <book><chapter><para> 37.6814 -#: ../en/ch07-filenames.xml:7 37.6815 +#: ../en/ch06-filenames.xml:7 37.6816 msgid "" 37.6817 "Mercurial provides mechanisms that let you work with file names in a " 37.6818 "consistent and expressive way." 37.6819 msgstr "" 37.6820 37.6821 #. type: Content of: <book><chapter><sect1><title> 37.6822 -#: ../en/ch07-filenames.xml:11 37.6823 +#: ../en/ch06-filenames.xml:11 37.6824 msgid "Simple file naming" 37.6825 msgstr "简单文件名称" 37.6826 37.6827 #. type: Content of: <book><chapter><sect1><para> 37.6828 -#: ../en/ch07-filenames.xml:13 37.6829 +#: ../en/ch06-filenames.xml:13 37.6830 msgid "" 37.6831 "Mercurial uses a unified piece of machinery <quote>under the hood</quote> to " 37.6832 "handle file names. Every command behaves uniformly with respect to file " 37.6833 @@ -7612,7 +6695,7 @@ 37.6834 msgstr "" 37.6835 37.6836 #. type: Content of: <book><chapter><sect1><para> 37.6837 -#: ../en/ch07-filenames.xml:18 37.6838 +#: ../en/ch06-filenames.xml:18 37.6839 msgid "" 37.6840 "If you explicitly name real files on the command line, Mercurial works with " 37.6841 "exactly those files, as you would expect. &interaction.filenames.files;" 37.6842 @@ -7620,7 +6703,7 @@ 37.6843 37.6844 # 37.6845 #. type: Content of: <book><chapter><sect1><para> 37.6846 -#: ../en/ch07-filenames.xml:22 37.6847 +#: ../en/ch06-filenames.xml:22 37.6848 msgid "" 37.6849 "When you provide a directory name, Mercurial will interpret this as " 37.6850 "<quote>operate on every file in this directory and its subdirectories</" 37.6851 @@ -7630,12 +6713,12 @@ 37.6852 msgstr "" 37.6853 37.6854 #. type: Content of: <book><chapter><sect1><title> 37.6855 -#: ../en/ch07-filenames.xml:33 37.6856 +#: ../en/ch06-filenames.xml:33 37.6857 msgid "Running commands without any file names" 37.6858 msgstr "不提供文件名称的执行命令" 37.6859 37.6860 #. type: Content of: <book><chapter><sect1><para> 37.6861 -#: ../en/ch07-filenames.xml:35 37.6862 +#: ../en/ch06-filenames.xml:35 37.6863 msgid "" 37.6864 "Mercurial's commands that work with file names have useful default behaviours " 37.6865 "when you invoke them without providing any file names or patterns. What kind " 37.6866 @@ -7645,14 +6728,14 @@ 37.6867 msgstr "" 37.6868 37.6869 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.6870 -#: ../en/ch07-filenames.xml:42 37.6871 +#: ../en/ch06-filenames.xml:42 37.6872 msgid "" 37.6873 "Most commands will operate on the entire working directory. This is what the " 37.6874 "<command role=\"hg-cmd\">hg add</command> command does, for example." 37.6875 msgstr "" 37.6876 37.6877 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.6878 -#: ../en/ch07-filenames.xml:46 37.6879 +#: ../en/ch06-filenames.xml:46 37.6880 msgid "" 37.6881 "If the command has effects that are difficult or impossible to reverse, it " 37.6882 "will force you to explicitly provide at least one name or pattern (see " 37.6883 @@ -7662,7 +6745,7 @@ 37.6884 37.6885 # 37.6886 #. type: Content of: <book><chapter><sect1><para> 37.6887 -#: ../en/ch07-filenames.xml:54 37.6888 +#: ../en/ch06-filenames.xml:54 37.6889 msgid "" 37.6890 "It's easy to work around these default behaviours if they don't suit you. If " 37.6891 "a command normally operates on the whole working directory, you can invoke it " 37.6892 @@ -7672,7 +6755,7 @@ 37.6893 37.6894 # 37.6895 #. type: Content of: <book><chapter><sect1><para> 37.6896 -#: ../en/ch07-filenames.xml:62 37.6897 +#: ../en/ch06-filenames.xml:62 37.6898 msgid "" 37.6899 "Along the same lines, some commands normally print file names relative to the " 37.6900 "root of the repository, even if you're invoking them from a subdirectory. " 37.6901 @@ -7685,12 +6768,12 @@ 37.6902 msgstr "" 37.6903 37.6904 #. type: Content of: <book><chapter><sect1><title> 37.6905 -#: ../en/ch07-filenames.xml:76 37.6906 +#: ../en/ch06-filenames.xml:76 37.6907 msgid "Telling you what's going on" 37.6908 msgstr "告诉你正在做什么" 37.6909 37.6910 #. type: Content of: <book><chapter><sect1><para> 37.6911 -#: ../en/ch07-filenames.xml:78 37.6912 +#: ../en/ch06-filenames.xml:78 37.6913 msgid "" 37.6914 "The <command role=\"hg-cmd\">hg add</command> example in the preceding " 37.6915 "section illustrates something else that's helpful about Mercurial commands. " 37.6916 @@ -7700,7 +6783,7 @@ 37.6917 msgstr "" 37.6918 37.6919 #. type: Content of: <book><chapter><sect1><para> 37.6920 -#: ../en/ch07-filenames.xml:85 37.6921 +#: ../en/ch06-filenames.xml:85 37.6922 msgid "" 37.6923 "The principle here is of <emphasis>least surprise</emphasis>. If you've " 37.6924 "exactly named a file on the command line, there's no point in repeating it " 37.6925 @@ -7710,7 +6793,7 @@ 37.6926 msgstr "" 37.6927 37.6928 #. type: Content of: <book><chapter><sect1><para> 37.6929 -#: ../en/ch07-filenames.xml:92 37.6930 +#: ../en/ch06-filenames.xml:92 37.6931 msgid "" 37.6932 "For commands that behave this way, you can silence them using the <option " 37.6933 "role=\"hg-opt-global\">-q</option> option. You can also get them to print " 37.6934 @@ -7719,12 +6802,12 @@ 37.6935 msgstr "" 37.6936 37.6937 #. type: Content of: <book><chapter><sect1><title> 37.6938 -#: ../en/ch07-filenames.xml:100 37.6939 +#: ../en/ch06-filenames.xml:100 37.6940 msgid "Using patterns to identify files" 37.6941 msgstr "使用模式标识文件" 37.6942 37.6943 #. type: Content of: <book><chapter><sect1><para> 37.6944 -#: ../en/ch07-filenames.xml:102 37.6945 +#: ../en/ch06-filenames.xml:102 37.6946 msgid "" 37.6947 "In addition to working with file and directory names, Mercurial lets you use " 37.6948 "<emphasis>patterns</emphasis> to identify files. Mercurial's pattern " 37.6949 @@ -7732,7 +6815,7 @@ 37.6950 msgstr "" 37.6951 37.6952 #. type: Content of: <book><chapter><sect1><para> 37.6953 -#: ../en/ch07-filenames.xml:106 37.6954 +#: ../en/ch06-filenames.xml:106 37.6955 msgid "" 37.6956 "On Unix-like systems (Linux, MacOS, etc.), the job of matching file names to " 37.6957 "patterns normally falls to the shell. On these systems, you must explicitly " 37.6958 @@ -7742,21 +6825,21 @@ 37.6959 msgstr "" 37.6960 37.6961 #. type: Content of: <book><chapter><sect1><para> 37.6962 -#: ../en/ch07-filenames.xml:113 37.6963 +#: ../en/ch06-filenames.xml:113 37.6964 msgid "" 37.6965 "To provide a pattern in place of a regular name on the command line, the " 37.6966 "mechanism is simple:" 37.6967 msgstr "" 37.6968 37.6969 #. type: Content of: <book><chapter><sect1><para> 37.6970 -#: ../en/ch07-filenames.xml:116 37.6971 +#: ../en/ch06-filenames.xml:116 37.6972 msgid "" 37.6973 "That is, a pattern is identified by a short text string that says what kind " 37.6974 "of pattern this is, followed by a colon, followed by the actual pattern." 37.6975 msgstr "" 37.6976 37.6977 #. type: Content of: <book><chapter><sect1><para> 37.6978 -#: ../en/ch07-filenames.xml:120 37.6979 +#: ../en/ch06-filenames.xml:120 37.6980 msgid "" 37.6981 "Mercurial supports two kinds of pattern syntax. The most frequently used is " 37.6982 "called <literal>glob</literal>; this is the same kind of pattern matching " 37.6983 @@ -7765,7 +6848,7 @@ 37.6984 msgstr "" 37.6985 37.6986 #. type: Content of: <book><chapter><sect1><para> 37.6987 -#: ../en/ch07-filenames.xml:125 37.6988 +#: ../en/ch06-filenames.xml:125 37.6989 msgid "" 37.6990 "When Mercurial does automatic pattern matching on Windows, it uses " 37.6991 "<literal>glob</literal> syntax. You can thus omit the <quote><literal>glob:</" 37.6992 @@ -7773,14 +6856,14 @@ 37.6993 msgstr "" 37.6994 37.6995 #. type: Content of: <book><chapter><sect1><para> 37.6996 -#: ../en/ch07-filenames.xml:130 37.6997 +#: ../en/ch06-filenames.xml:130 37.6998 msgid "" 37.6999 "The <literal>re</literal> syntax is more powerful; it lets you specify " 37.7000 "patterns using regular expressions, also known as regexps." 37.7001 msgstr "" 37.7002 37.7003 #. type: Content of: <book><chapter><sect1><para> 37.7004 -#: ../en/ch07-filenames.xml:134 37.7005 +#: ../en/ch06-filenames.xml:134 37.7006 msgid "" 37.7007 "By the way, in the examples that follow, notice that I'm careful to wrap all " 37.7008 "of my patterns in quote characters, so that they won't get expanded by the " 37.7009 @@ -7788,12 +6871,12 @@ 37.7010 msgstr "" 37.7011 37.7012 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7013 -#: ../en/ch07-filenames.xml:140 37.7014 +#: ../en/ch06-filenames.xml:140 37.7015 msgid "Shell-style <literal>glob</literal> patterns" 37.7016 msgstr "外壳风格的 <literal>glob</literal> 模式" 37.7017 37.7018 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7019 -#: ../en/ch07-filenames.xml:142 37.7020 +#: ../en/ch06-filenames.xml:142 37.7021 msgid "" 37.7022 "This is an overview of the kinds of patterns you can use when you're matching " 37.7023 "on glob patterns." 37.7024 @@ -7801,7 +6884,7 @@ 37.7025 37.7026 # 37.7027 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7028 -#: ../en/ch07-filenames.xml:145 37.7029 +#: ../en/ch06-filenames.xml:145 37.7030 msgid "" 37.7031 "The <quote><literal>*</literal></quote> character matches any string, within " 37.7032 "a single directory." 37.7033 @@ -7809,7 +6892,7 @@ 37.7034 37.7035 # 37.7036 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7037 -#: ../en/ch07-filenames.xml:150 37.7038 +#: ../en/ch06-filenames.xml:150 37.7039 msgid "" 37.7040 "The <quote><literal>**</literal></quote> pattern matches any string, and " 37.7041 "crosses directory boundaries. It's not a standard Unix glob token, but it's " 37.7042 @@ -7818,13 +6901,13 @@ 37.7043 37.7044 # 37.7045 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7046 -#: ../en/ch07-filenames.xml:157 37.7047 +#: ../en/ch06-filenames.xml:157 37.7048 msgid "" 37.7049 "The <quote><literal>?</literal></quote> pattern matches any single character." 37.7050 msgstr "" 37.7051 37.7052 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7053 -#: ../en/ch07-filenames.xml:162 37.7054 +#: ../en/ch06-filenames.xml:162 37.7055 msgid "" 37.7056 "The <quote><literal>[</literal></quote> character begins a " 37.7057 "<emphasis>character class</emphasis>. This matches any single character " 37.7058 @@ -7835,7 +6918,7 @@ 37.7059 msgstr "" 37.7060 37.7061 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7062 -#: ../en/ch07-filenames.xml:172 37.7063 +#: ../en/ch06-filenames.xml:172 37.7064 msgid "" 37.7065 "If the first character after the <quote><literal>[</literal></quote> in a " 37.7066 "character class is a <quote><literal>!</literal></quote>, it " 37.7067 @@ -7844,7 +6927,7 @@ 37.7068 msgstr "" 37.7069 37.7070 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7071 -#: ../en/ch07-filenames.xml:178 37.7072 +#: ../en/ch06-filenames.xml:178 37.7073 msgid "" 37.7074 "A <quote><literal>{</literal></quote> begins a group of subpatterns, where " 37.7075 "the whole group matches if any subpattern in the group matches. The " 37.7076 @@ -7853,13 +6936,13 @@ 37.7077 msgstr "" 37.7078 37.7079 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.7080 -#: ../en/ch07-filenames.xml:187 37.7081 +#: ../en/ch06-filenames.xml:187 37.7082 msgid "Watch out!" 37.7083 msgstr "千万小心!" 37.7084 37.7085 # 37.7086 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.7087 -#: ../en/ch07-filenames.xml:189 37.7088 +#: ../en/ch06-filenames.xml:189 37.7089 msgid "" 37.7090 "Don't forget that if you want to match a pattern in any directory, you should " 37.7091 "not be using the <quote><literal>*</literal></quote> match-any token, as this " 37.7092 @@ -7869,12 +6952,12 @@ 37.7093 msgstr "" 37.7094 37.7095 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7096 -#: ../en/ch07-filenames.xml:201 37.7097 +#: ../en/ch06-filenames.xml:201 37.7098 msgid "Regular expression matching with <literal>re</literal> patterns" 37.7099 msgstr "使用 <literal>re</literal> 模式的正则表达式匹配" 37.7100 37.7101 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7102 -#: ../en/ch07-filenames.xml:204 37.7103 +#: ../en/ch06-filenames.xml:204 37.7104 msgid "" 37.7105 "Mercurial accepts the same regular expression syntax as the Python " 37.7106 "programming language (it uses Python's regexp engine internally). This is " 37.7107 @@ -7883,7 +6966,7 @@ 37.7108 msgstr "" 37.7109 37.7110 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7111 -#: ../en/ch07-filenames.xml:210 37.7112 +#: ../en/ch06-filenames.xml:210 37.7113 msgid "" 37.7114 "I won't discuss Mercurial's regexp dialect in any detail here, as regexps are " 37.7115 "not often used. Perl-style regexps are in any case already exhaustively " 37.7116 @@ -7893,7 +6976,7 @@ 37.7117 msgstr "" 37.7118 37.7119 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7120 -#: ../en/ch07-filenames.xml:217 37.7121 +#: ../en/ch06-filenames.xml:217 37.7122 msgid "" 37.7123 "A regexp is matched against an entire file name, relative to the root of the " 37.7124 "repository. In other words, even if you're already in subbdirectory " 37.7125 @@ -7903,7 +6986,7 @@ 37.7126 msgstr "" 37.7127 37.7128 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7129 -#: ../en/ch07-filenames.xml:224 37.7130 +#: ../en/ch06-filenames.xml:224 37.7131 msgid "" 37.7132 "One thing to note, if you're familiar with Perl-style regexps, is that " 37.7133 "Mercurial's are <emphasis>rooted</emphasis>. That is, a regexp starts " 37.7134 @@ -7913,12 +6996,12 @@ 37.7135 msgstr "" 37.7136 37.7137 #. type: Content of: <book><chapter><sect1><title> 37.7138 -#: ../en/ch07-filenames.xml:234 37.7139 +#: ../en/ch06-filenames.xml:234 37.7140 msgid "Filtering files" 37.7141 msgstr "过滤文件" 37.7142 37.7143 #. type: Content of: <book><chapter><sect1><para> 37.7144 -#: ../en/ch07-filenames.xml:236 37.7145 +#: ../en/ch06-filenames.xml:236 37.7146 msgid "" 37.7147 "Not only does Mercurial give you a variety of ways to specify files; it lets " 37.7148 "you further winnow those files using <emphasis>filters</emphasis>. Commands " 37.7149 @@ -7926,7 +7009,7 @@ 37.7150 msgstr "" 37.7151 37.7152 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7153 -#: ../en/ch07-filenames.xml:241 37.7154 +#: ../en/ch06-filenames.xml:241 37.7155 msgid "" 37.7156 "<option role=\"hg-opt-global\">-I</option>, or <option role=\"hg-opt-global" 37.7157 "\">--include</option>, lets you specify a pattern that file names must match " 37.7158 @@ -7934,7 +7017,7 @@ 37.7159 msgstr "" 37.7160 37.7161 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7162 -#: ../en/ch07-filenames.xml:246 37.7163 +#: ../en/ch06-filenames.xml:246 37.7164 msgid "" 37.7165 "<option role=\"hg-opt-global\">-X</option>, or <option role=\"hg-opt-global" 37.7166 "\">--exclude</option>, gives you a way to <emphasis>avoid</emphasis> " 37.7167 @@ -7942,7 +7025,7 @@ 37.7168 msgstr "" 37.7169 37.7170 #. type: Content of: <book><chapter><sect1><para> 37.7171 -#: ../en/ch07-filenames.xml:251 37.7172 +#: ../en/ch06-filenames.xml:251 37.7173 msgid "" 37.7174 "You can provide multiple <option role=\"hg-opt-global\">-I</option> and " 37.7175 "<option role=\"hg-opt-global\">-X</option> options on the command line, and " 37.7176 @@ -7951,36 +7034,36 @@ 37.7177 msgstr "" 37.7178 37.7179 #. type: Content of: <book><chapter><sect1><para> 37.7180 -#: ../en/ch07-filenames.xml:258 37.7181 +#: ../en/ch06-filenames.xml:258 37.7182 msgid "" 37.7183 "You can read a <option role=\"hg-opt-global\">-I</option> filter as " 37.7184 "<quote>process only the files that match this filter</quote>." 37.7185 msgstr "" 37.7186 37.7187 #. type: Content of: <book><chapter><sect1><para> 37.7188 -#: ../en/ch07-filenames.xml:264 37.7189 +#: ../en/ch06-filenames.xml:264 37.7190 msgid "" 37.7191 "The <option role=\"hg-opt-global\">-X</option> filter is best read as " 37.7192 "<quote>process only the files that don't match this pattern</quote>." 37.7193 msgstr "" 37.7194 37.7195 #. type: Content of: <book><chapter><sect1><title> 37.7196 -#: ../en/ch07-filenames.xml:272 37.7197 +#: ../en/ch06-filenames.xml:272 37.7198 msgid "Ignoring unwanted files and directories" 37.7199 msgstr "忽略不需要的文件和目录" 37.7200 37.7201 #. type: Content of: <book><chapter><sect1><para> 37.7202 -#: ../en/ch07-filenames.xml:274 37.7203 +#: ../en/ch06-filenames.xml:274 37.7204 msgid "XXX." 37.7205 msgstr "" 37.7206 37.7207 #. type: Content of: <book><chapter><sect1><title> 37.7208 -#: ../en/ch07-filenames.xml:278 37.7209 +#: ../en/ch06-filenames.xml:278 37.7210 msgid "Case sensitivity" 37.7211 msgstr "大小写敏感性" 37.7212 37.7213 #. type: Content of: <book><chapter><sect1><para> 37.7214 -#: ../en/ch07-filenames.xml:280 37.7215 +#: ../en/ch06-filenames.xml:280 37.7216 msgid "" 37.7217 "If you're working in a mixed development environment that contains both Linux " 37.7218 "(or other Unix) systems and Macs or Windows systems, you should keep in the " 37.7219 @@ -7991,7 +7074,7 @@ 37.7220 msgstr "" 37.7221 37.7222 #. type: Content of: <book><chapter><sect1><para> 37.7223 -#: ../en/ch07-filenames.xml:289 37.7224 +#: ../en/ch06-filenames.xml:289 37.7225 msgid "" 37.7226 "Operating systems and filesystems differ in the way they handle the " 37.7227 "<emphasis>case</emphasis> of characters in file and directory names. There " 37.7228 @@ -7999,7 +7082,7 @@ 37.7229 msgstr "" 37.7230 37.7231 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7232 -#: ../en/ch07-filenames.xml:294 37.7233 +#: ../en/ch06-filenames.xml:294 37.7234 msgid "" 37.7235 "Completely case insensitive. Uppercase and lowercase versions of a letter " 37.7236 "are treated as identical, both when creating a file and during subsequent " 37.7237 @@ -8007,7 +7090,7 @@ 37.7238 msgstr "" 37.7239 37.7240 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7241 -#: ../en/ch07-filenames.xml:299 37.7242 +#: ../en/ch06-filenames.xml:299 37.7243 msgid "" 37.7244 "Case preserving, but insensitive. When a file or directory is created, the " 37.7245 "case of its name is stored, and can be retrieved and displayed by the " 37.7246 @@ -8019,7 +7102,7 @@ 37.7247 msgstr "" 37.7248 37.7249 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7250 -#: ../en/ch07-filenames.xml:310 37.7251 +#: ../en/ch06-filenames.xml:310 37.7252 msgid "" 37.7253 "Case sensitive. The case of a name is significant at all times. The names " 37.7254 "<filename>foo</filename> and {FoO} identify different files. This is the way " 37.7255 @@ -8027,7 +7110,7 @@ 37.7256 msgstr "" 37.7257 37.7258 #. type: Content of: <book><chapter><sect1><para> 37.7259 -#: ../en/ch07-filenames.xml:316 37.7260 +#: ../en/ch06-filenames.xml:316 37.7261 msgid "" 37.7262 "On Unix-like systems, it is possible to have any or all of the above ways of " 37.7263 "handling case in action at once. For example, if you use a USB thumb drive " 37.7264 @@ -8036,12 +7119,12 @@ 37.7265 msgstr "" 37.7266 37.7267 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7268 -#: ../en/ch07-filenames.xml:323 37.7269 +#: ../en/ch06-filenames.xml:323 37.7270 msgid "Safe, portable repository storage" 37.7271 msgstr "安全,可移植的版本库存储" 37.7272 37.7273 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7274 -#: ../en/ch07-filenames.xml:325 37.7275 +#: ../en/ch06-filenames.xml:325 37.7276 msgid "" 37.7277 "Mercurial's repository storage mechanism is <emphasis>case safe</emphasis>. " 37.7278 "It translates file names so that they can be safely stored on both case " 37.7279 @@ -8052,12 +7135,12 @@ 37.7280 msgstr "" 37.7281 37.7282 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7283 -#: ../en/ch07-filenames.xml:336 37.7284 +#: ../en/ch06-filenames.xml:336 37.7285 msgid "Detecting case conflicts" 37.7286 msgstr "检测大小写冲突" 37.7287 37.7288 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7289 -#: ../en/ch07-filenames.xml:338 37.7290 +#: ../en/ch06-filenames.xml:338 37.7291 msgid "" 37.7292 "When operating in the working directory, Mercurial honours the naming policy " 37.7293 "of the filesystem where the working directory is located. If the filesystem " 37.7294 @@ -8066,7 +7149,7 @@ 37.7295 msgstr "" 37.7296 37.7297 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7298 -#: ../en/ch07-filenames.xml:344 37.7299 +#: ../en/ch06-filenames.xml:344 37.7300 msgid "" 37.7301 "An important aspect of this approach is that it is possible to commit a " 37.7302 "changeset on a case sensitive (typically Linux or Unix) filesystem that will " 37.7303 @@ -8079,7 +7162,7 @@ 37.7304 msgstr "" 37.7305 37.7306 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7307 -#: ../en/ch07-filenames.xml:355 37.7308 +#: ../en/ch06-filenames.xml:355 37.7309 msgid "" 37.7310 "If a Windows or Mac user pulls this change, they will not initially have a " 37.7311 "problem, because Mercurial's repository storage mechanism is case safe. " 37.7312 @@ -8091,12 +7174,12 @@ 37.7313 msgstr "" 37.7314 37.7315 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7316 -#: ../en/ch07-filenames.xml:367 37.7317 +#: ../en/ch06-filenames.xml:367 37.7318 msgid "Fixing a case conflict" 37.7319 msgstr "修正大小写冲突" 37.7320 37.7321 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7322 -#: ../en/ch07-filenames.xml:369 37.7323 +#: ../en/ch06-filenames.xml:369 37.7324 msgid "" 37.7325 "If you are using Windows or a Mac in a mixed environment where some of your " 37.7326 "collaborators are using Linux or Unix, and Mercurial reports a case folding " 37.7327 @@ -8106,7 +7189,7 @@ 37.7328 msgstr "" 37.7329 37.7330 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7331 -#: ../en/ch07-filenames.xml:376 37.7332 +#: ../en/ch06-filenames.xml:376 37.7333 msgid "" 37.7334 "Just find a nearby Linux or Unix box, clone the problem repository onto it, " 37.7335 "and use Mercurial's <command role=\"hg-cmd\">hg rename</command> command to " 37.7336 @@ -8118,7 +7201,7 @@ 37.7337 msgstr "" 37.7338 37.7339 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7340 -#: ../en/ch07-filenames.xml:386 37.7341 +#: ../en/ch06-filenames.xml:386 37.7342 msgid "" 37.7343 "The changeset with case-conflicting names will remain in your project's " 37.7344 "history, and you still won't be able to <command role=\"hg-cmd\">hg update</" 37.7345 @@ -8127,7 +7210,7 @@ 37.7346 msgstr "" 37.7347 37.7348 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.7349 -#: ../en/ch07-filenames.xml:393 37.7350 +#: ../en/ch06-filenames.xml:393 37.7351 msgid "" 37.7352 "Prior to version 0.9.3, Mercurial did not use a case safe repository storage " 37.7353 "mechanism, and did not detect case folding conflicts. If you are using an " 37.7354 @@ -8136,12 +7219,12 @@ 37.7355 msgstr "" 37.7356 37.7357 #. type: Content of: <book><chapter><title> 37.7358 -#: ../en/ch08-branch.xml:5 37.7359 +#: ../en/ch07-branch.xml:5 37.7360 msgid "Managing releases and branchy development" 37.7361 msgstr "发布管理与分支开发" 37.7362 37.7363 #. type: Content of: <book><chapter><para> 37.7364 -#: ../en/ch08-branch.xml:7 37.7365 +#: ../en/ch07-branch.xml:7 37.7366 msgid "" 37.7367 "Mercurial provides several mechanisms for you to manage a project that is " 37.7368 "making progress on multiple fronts at once. To understand these mechanisms, " 37.7369 @@ -8149,7 +7232,7 @@ 37.7370 msgstr "" 37.7371 37.7372 #. type: Content of: <book><chapter><para> 37.7373 -#: ../en/ch08-branch.xml:12 37.7374 +#: ../en/ch07-branch.xml:12 37.7375 msgid "" 37.7376 "Many software projects issue periodic <quote>major</quote> releases that " 37.7377 "contain substantial new features. In parallel, they may issue <quote>minor</" 37.7378 @@ -8158,7 +7241,7 @@ 37.7379 msgstr "" 37.7380 37.7381 #. type: Content of: <book><chapter><para> 37.7382 -#: ../en/ch08-branch.xml:18 37.7383 +#: ../en/ch07-branch.xml:18 37.7384 msgid "" 37.7385 "In this chapter, we'll start by talking about how to keep records of project " 37.7386 "milestones such as releases. We'll then continue on to talk about the flow " 37.7387 @@ -8167,12 +7250,12 @@ 37.7388 msgstr "" 37.7389 37.7390 #. type: Content of: <book><chapter><sect1><title> 37.7391 -#: ../en/ch08-branch.xml:25 37.7392 +#: ../en/ch07-branch.xml:25 37.7393 msgid "Giving a persistent name to a revision" 37.7394 msgstr "给版本指定一个永久的名称" 37.7395 37.7396 #. type: Content of: <book><chapter><sect1><para> 37.7397 -#: ../en/ch08-branch.xml:27 37.7398 +#: ../en/ch07-branch.xml:27 37.7399 msgid "" 37.7400 "Once you decide that you'd like to call a particular revision a " 37.7401 "<quote>release</quote>, it's a good idea to record the identity of that " 37.7402 @@ -8183,7 +7266,7 @@ 37.7403 37.7404 # 37.7405 #. type: Content of: <book><chapter><sect1><para> 37.7406 -#: ../en/ch08-branch.xml:34 37.7407 +#: ../en/ch07-branch.xml:34 37.7408 msgid "" 37.7409 "Mercurial lets you give a permanent name to any revision using the <command " 37.7410 "role=\"hg-cmd\">hg tag</command> command. Not surprisingly, these names are " 37.7411 @@ -8191,7 +7274,7 @@ 37.7412 msgstr "" 37.7413 37.7414 #. type: Content of: <book><chapter><sect1><para> 37.7415 -#: ../en/ch08-branch.xml:40 37.7416 +#: ../en/ch07-branch.xml:40 37.7417 msgid "" 37.7418 "A tag is nothing more than a <quote>symbolic name</quote> for a revision. " 37.7419 "Tags exist purely for your convenience, so that you have a handy permanent " 37.7420 @@ -8202,22 +7285,22 @@ 37.7421 msgstr "" 37.7422 37.7423 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7424 -#: ../en/ch08-branch.xml:49 37.7425 +#: ../en/ch07-branch.xml:49 37.7426 msgid "Colon (ASCII 58, <quote><literal>:</literal></quote>)" 37.7427 msgstr "" 37.7428 37.7429 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7430 -#: ../en/ch08-branch.xml:52 37.7431 +#: ../en/ch07-branch.xml:52 37.7432 msgid "Carriage return (ASCII 13, <quote><literal>\\r</literal></quote>)" 37.7433 msgstr "" 37.7434 37.7435 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7436 -#: ../en/ch08-branch.xml:55 37.7437 +#: ../en/ch07-branch.xml:55 37.7438 msgid "Newline (ASCII 10, <quote><literal>\\n</literal></quote>)" 37.7439 msgstr "" 37.7440 37.7441 #. type: Content of: <book><chapter><sect1><para> 37.7442 -#: ../en/ch08-branch.xml:59 37.7443 +#: ../en/ch07-branch.xml:59 37.7444 msgid "" 37.7445 "You can use the <command role=\"hg-cmd\">hg tags</command> command to display " 37.7446 "the tags present in your repository. In the output, each tagged revision is " 37.7447 @@ -8226,7 +7309,7 @@ 37.7448 msgstr "" 37.7449 37.7450 #. type: Content of: <book><chapter><sect1><para> 37.7451 -#: ../en/ch08-branch.xml:67 37.7452 +#: ../en/ch07-branch.xml:67 37.7453 msgid "" 37.7454 "Notice that <literal>tip</literal> is listed in the output of <command role=" 37.7455 "\"hg-cmd\">hg tags</command>. The <literal>tip</literal> tag is a special " 37.7456 @@ -8235,7 +7318,7 @@ 37.7457 msgstr "" 37.7458 37.7459 #. type: Content of: <book><chapter><sect1><para> 37.7460 -#: ../en/ch08-branch.xml:73 37.7461 +#: ../en/ch07-branch.xml:73 37.7462 msgid "" 37.7463 "In the output of the <command role=\"hg-cmd\">hg tags</command> command, tags " 37.7464 "are listed in reverse order, by revision number. This usually means that " 37.7465 @@ -8245,7 +7328,7 @@ 37.7466 msgstr "" 37.7467 37.7468 #. type: Content of: <book><chapter><sect1><para> 37.7469 -#: ../en/ch08-branch.xml:80 37.7470 +#: ../en/ch07-branch.xml:80 37.7471 msgid "" 37.7472 "When you run <command role=\"hg-cmd\">hg log</command>, if it displays a " 37.7473 "revision that has tags associated with it, it will print those tags." 37.7474 @@ -8253,7 +7336,7 @@ 37.7475 37.7476 # 37.7477 #. type: Content of: <book><chapter><sect1><para> 37.7478 -#: ../en/ch08-branch.xml:86 37.7479 +#: ../en/ch07-branch.xml:86 37.7480 msgid "" 37.7481 "Any time you need to provide a revision ID to a Mercurial command, the " 37.7482 "command will accept a tag name in its place. Internally, Mercurial will " 37.7483 @@ -8261,7 +7344,7 @@ 37.7484 msgstr "" 37.7485 37.7486 #. type: Content of: <book><chapter><sect1><para> 37.7487 -#: ../en/ch08-branch.xml:93 37.7488 +#: ../en/ch07-branch.xml:93 37.7489 msgid "" 37.7490 "There's no limit on the number of tags you can have in a repository, or on " 37.7491 "the number of tags that a single revision can have. As a practical matter, " 37.7492 @@ -8272,7 +7355,7 @@ 37.7493 msgstr "" 37.7494 37.7495 #. type: Content of: <book><chapter><sect1><para> 37.7496 -#: ../en/ch08-branch.xml:101 37.7497 +#: ../en/ch07-branch.xml:101 37.7498 msgid "" 37.7499 "For example, if your project has milestones as frequent as every few days, " 37.7500 "it's perfectly reasonable to tag each one of those. But if you have a " 37.7501 @@ -8283,14 +7366,14 @@ 37.7502 msgstr "" 37.7503 37.7504 #. type: Content of: <book><chapter><sect1><para> 37.7505 -#: ../en/ch08-branch.xml:109 37.7506 +#: ../en/ch07-branch.xml:109 37.7507 msgid "" 37.7508 "If you want to remove a tag that you no longer want, use <command role=\"hg-" 37.7509 "cmd\">hg tag --remove</command>." 37.7510 msgstr "" 37.7511 37.7512 #. type: Content of: <book><chapter><sect1><para> 37.7513 -#: ../en/ch08-branch.xml:114 37.7514 +#: ../en/ch07-branch.xml:114 37.7515 msgid "" 37.7516 "You can also modify a tag at any time, so that it identifies a different " 37.7517 "revision, by simply issuing a new <command role=\"hg-cmd\">hg tag</command> " 37.7518 @@ -8300,7 +7383,7 @@ 37.7519 msgstr "" 37.7520 37.7521 #. type: Content of: <book><chapter><sect1><para> 37.7522 -#: ../en/ch08-branch.xml:123 37.7523 +#: ../en/ch07-branch.xml:123 37.7524 msgid "" 37.7525 "There will still be a permanent record of the previous identity of the tag, " 37.7526 "but Mercurial will no longer use it. There's thus no penalty to tagging the " 37.7527 @@ -8310,7 +7393,7 @@ 37.7528 37.7529 # 37.7530 #. type: Content of: <book><chapter><sect1><para> 37.7531 -#: ../en/ch08-branch.xml:129 37.7532 +#: ../en/ch07-branch.xml:129 37.7533 msgid "" 37.7534 "Mercurial stores tags in a normal revision-controlled file in your " 37.7535 "repository. If you've created any tags, you'll find them in a file named " 37.7536 @@ -8322,12 +7405,12 @@ 37.7537 msgstr "" 37.7538 37.7539 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7540 -#: ../en/ch08-branch.xml:142 37.7541 +#: ../en/ch07-branch.xml:142 37.7542 msgid "Handling tag conflicts during a merge" 37.7543 msgstr "在合并期间处理标签冲突" 37.7544 37.7545 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7546 -#: ../en/ch08-branch.xml:144 37.7547 +#: ../en/ch07-branch.xml:144 37.7548 msgid "" 37.7549 "You won't often need to care about the <filename role=\"special\">.hgtags</" 37.7550 "filename> file, but it sometimes makes its presence known during a merge. " 37.7551 @@ -8337,7 +7420,7 @@ 37.7552 msgstr "" 37.7553 37.7554 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7555 -#: ../en/ch08-branch.xml:151 37.7556 +#: ../en/ch07-branch.xml:151 37.7557 msgid "" 37.7558 "If you're resolving a conflict in the <filename role=\"special\">.hgtags</" 37.7559 "filename> file during a merge, there's one twist to modifying the <filename " 37.7560 @@ -8348,7 +7431,7 @@ 37.7561 msgstr "" 37.7562 37.7563 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7564 -#: ../en/ch08-branch.xml:161 37.7565 +#: ../en/ch07-branch.xml:161 37.7566 msgid "" 37.7567 "An unfortunate consequence of this design is that you can't actually verify " 37.7568 "that your merged <filename role=\"special\">.hgtags</filename> file is " 37.7569 @@ -8362,12 +7445,12 @@ 37.7570 msgstr "" 37.7571 37.7572 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7573 -#: ../en/ch08-branch.xml:176 37.7574 +#: ../en/ch07-branch.xml:176 37.7575 msgid "Tags and cloning" 37.7576 msgstr "标签与克隆" 37.7577 37.7578 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7579 -#: ../en/ch08-branch.xml:178 37.7580 +#: ../en/ch07-branch.xml:178 37.7581 msgid "" 37.7582 "You may have noticed that the <command role=\"hg-cmd\">hg clone</command> " 37.7583 "command has a <option role=\"hg-opt-clone\">-r</option> option that lets you " 37.7584 @@ -8377,7 +7460,7 @@ 37.7585 msgstr "" 37.7586 37.7587 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7588 -#: ../en/ch08-branch.xml:186 37.7589 +#: ../en/ch07-branch.xml:186 37.7590 msgid "" 37.7591 "Recall that a tag is stored as a revision to the <filename role=\"special\">." 37.7592 "hgtags</filename> file, so that when you create a tag, the changeset in which " 37.7593 @@ -8391,12 +7474,12 @@ 37.7594 msgstr "" 37.7595 37.7596 #. type: Content of: <book><chapter><sect1><sect2><title> 37.7597 -#: ../en/ch08-branch.xml:201 37.7598 +#: ../en/ch07-branch.xml:201 37.7599 msgid "When permanent tags are too much" 37.7600 msgstr "当永久标签太多的时候" 37.7601 37.7602 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7603 -#: ../en/ch08-branch.xml:203 37.7604 +#: ../en/ch07-branch.xml:203 37.7605 msgid "" 37.7606 "Since Mercurial's tags are revision controlled and carried around with a " 37.7607 "project's history, everyone you work with will see the tags you create. But " 37.7608 @@ -8407,7 +7490,7 @@ 37.7609 msgstr "" 37.7610 37.7611 #. type: Content of: <book><chapter><sect1><sect2><para> 37.7612 -#: ../en/ch08-branch.xml:213 37.7613 +#: ../en/ch07-branch.xml:213 37.7614 msgid "" 37.7615 "For cases like this, what you might want to use are <emphasis>local</" 37.7616 "emphasis> tags. You can create a local tag with the <option role=\"hg-opt-tag" 37.7617 @@ -8421,12 +7504,12 @@ 37.7618 msgstr "" 37.7619 37.7620 #. type: Content of: <book><chapter><sect1><title> 37.7621 -#: ../en/ch08-branch.xml:228 37.7622 +#: ../en/ch07-branch.xml:228 37.7623 msgid "The flow of changes&emdash;big picture vs. little" 37.7624 msgstr "修改流程&emdash;宏观与微观" 37.7625 37.7626 #. type: Content of: <book><chapter><sect1><para> 37.7627 -#: ../en/ch08-branch.xml:230 37.7628 +#: ../en/ch07-branch.xml:230 37.7629 msgid "" 37.7630 "To return to the outline I sketched at the beginning of a chapter, let's " 37.7631 "think about a project that has multiple concurrent pieces of work under " 37.7632 @@ -8434,7 +7517,7 @@ 37.7633 msgstr "" 37.7634 37.7635 #. type: Content of: <book><chapter><sect1><para> 37.7636 -#: ../en/ch08-branch.xml:234 37.7637 +#: ../en/ch07-branch.xml:234 37.7638 msgid "" 37.7639 "There might be a push for a new <quote>main</quote> release; a new minor " 37.7640 "bugfix release to the last main release; and an unexpected <quote>hot fix</" 37.7641 @@ -8442,7 +7525,7 @@ 37.7642 msgstr "" 37.7643 37.7644 #. type: Content of: <book><chapter><sect1><para> 37.7645 -#: ../en/ch08-branch.xml:239 37.7646 +#: ../en/ch07-branch.xml:239 37.7647 msgid "" 37.7648 "The usual way people refer to these different concurrent directions of " 37.7649 "development is as <quote>branches</quote>. However, we've already seen " 37.7650 @@ -8452,14 +7535,14 @@ 37.7651 msgstr "" 37.7652 37.7653 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7654 -#: ../en/ch08-branch.xml:246 37.7655 +#: ../en/ch07-branch.xml:246 37.7656 msgid "" 37.7657 "<quote>Big picture</quote> branches represent the sweep of a project's " 37.7658 "evolution; people give them names, and talk about them in conversation." 37.7659 msgstr "" 37.7660 37.7661 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.7662 -#: ../en/ch08-branch.xml:250 37.7663 +#: ../en/ch07-branch.xml:250 37.7664 msgid "" 37.7665 "<quote>Little picture</quote> branches are artefacts of the day-to-day " 37.7666 "activity of developing and merging changes. They expose the narrative of how " 37.7667 @@ -8467,12 +7550,12 @@ 37.7668 msgstr "" 37.7669 37.7670 #. type: Content of: <book><chapter><sect1><title> 37.7671 -#: ../en/ch08-branch.xml:258 37.7672 +#: ../en/ch07-branch.xml:258 37.7673 msgid "Managing big-picture branches in repositories" 37.7674 msgstr "在版本库中管理分支" 37.7675 37.7676 #. type: Content of: <book><chapter><sect1><para> 37.7677 -#: ../en/ch08-branch.xml:260 37.7678 +#: ../en/ch07-branch.xml:260 37.7679 msgid "" 37.7680 "The easiest way to isolate a <quote>big picture</quote> branch in Mercurial " 37.7681 "is in a dedicated repository. If you have an existing shared " 37.7682 @@ -8483,14 +7566,14 @@ 37.7683 msgstr "" 37.7684 37.7685 #. type: Content of: <book><chapter><sect1><para> 37.7686 -#: ../en/ch08-branch.xml:270 37.7687 +#: ../en/ch07-branch.xml:270 37.7688 msgid "" 37.7689 "You can then clone a new shared <literal>myproject-1.0.1</literal> repository " 37.7690 "as of that tag." 37.7691 msgstr "" 37.7692 37.7693 #. type: Content of: <book><chapter><sect1><para> 37.7694 -#: ../en/ch08-branch.xml:276 37.7695 +#: ../en/ch07-branch.xml:276 37.7696 msgid "" 37.7697 "Afterwards, if someone needs to work on a bug fix that ought to go into an " 37.7698 "upcoming 1.0.1 minor release, they clone the <literal>myproject-1.0.1</" 37.7699 @@ -8498,19 +7581,19 @@ 37.7700 msgstr "" 37.7701 37.7702 #. type: Content of: <book><chapter><sect1><para> 37.7703 -#: ../en/ch08-branch.xml:283 37.7704 +#: ../en/ch07-branch.xml:283 37.7705 msgid "" 37.7706 "Meanwhile, development for the next major release can continue, isolated and " 37.7707 "unabated, in the <literal>myproject</literal> repository." 37.7708 msgstr "" 37.7709 37.7710 #. type: Content of: <book><chapter><sect1><title> 37.7711 -#: ../en/ch08-branch.xml:291 37.7712 +#: ../en/ch07-branch.xml:291 37.7713 msgid "Don't repeat yourself: merging across branches" 37.7714 msgstr "不要重复劳动:在分支间合并" 37.7715 37.7716 #. type: Content of: <book><chapter><sect1><para> 37.7717 -#: ../en/ch08-branch.xml:293 37.7718 +#: ../en/ch07-branch.xml:293 37.7719 msgid "" 37.7720 "In many cases, if you have a bug to fix on a maintenance branch, the chances " 37.7721 "are good that the bug exists on your project's main branch (and possibly " 37.7722 @@ -8520,26 +7603,26 @@ 37.7723 msgstr "" 37.7724 37.7725 #. type: Content of: <book><chapter><sect1><para> 37.7726 -#: ../en/ch08-branch.xml:301 37.7727 +#: ../en/ch07-branch.xml:301 37.7728 msgid "" 37.7729 "In the simplest instance, all you need to do is pull changes from your " 37.7730 "maintenance branch into your local clone of the target branch." 37.7731 msgstr "" 37.7732 37.7733 #. type: Content of: <book><chapter><sect1><para> 37.7734 -#: ../en/ch08-branch.xml:307 37.7735 +#: ../en/ch07-branch.xml:307 37.7736 msgid "" 37.7737 "You'll then need to merge the heads of the two branches, and push back to the " 37.7738 "main branch." 37.7739 msgstr "" 37.7740 37.7741 #. type: Content of: <book><chapter><sect1><title> 37.7742 -#: ../en/ch08-branch.xml:314 37.7743 +#: ../en/ch07-branch.xml:314 37.7744 msgid "Naming branches within one repository" 37.7745 msgstr "版本库中的命名分支" 37.7746 37.7747 #. type: Content of: <book><chapter><sect1><para> 37.7748 -#: ../en/ch08-branch.xml:316 37.7749 +#: ../en/ch07-branch.xml:316 37.7750 msgid "" 37.7751 "In most instances, isolating branches in repositories is the right approach. " 37.7752 "Its simplicity makes it easy to understand; and so it's hard to make " 37.7753 @@ -8549,7 +7632,7 @@ 37.7754 msgstr "" 37.7755 37.7756 #. type: Content of: <book><chapter><sect1><para> 37.7757 -#: ../en/ch08-branch.xml:323 37.7758 +#: ../en/ch07-branch.xml:323 37.7759 msgid "" 37.7760 "If you're more in the <quote>power user</quote> category (<emphasis>and</" 37.7761 "emphasis> your collaborators are too), there is an alternative way of " 37.7762 @@ -8562,7 +7645,7 @@ 37.7763 msgstr "" 37.7764 37.7765 #. type: Content of: <book><chapter><sect1><para> 37.7766 -#: ../en/ch08-branch.xml:334 37.7767 +#: ../en/ch07-branch.xml:334 37.7768 msgid "" 37.7769 "The key to working this way is that Mercurial lets you assign a persistent " 37.7770 "<emphasis>name</emphasis> to a branch. There always exists a branch named " 37.7771 @@ -8572,7 +7655,7 @@ 37.7772 msgstr "" 37.7773 37.7774 #. type: Content of: <book><chapter><sect1><para> 37.7775 -#: ../en/ch08-branch.xml:341 37.7776 +#: ../en/ch07-branch.xml:341 37.7777 msgid "" 37.7778 "As an example, when you run the <command role=\"hg-cmd\">hg commit</command> " 37.7779 "command, and it pops up your editor so that you can enter a commit message, " 37.7780 @@ -8582,7 +7665,7 @@ 37.7781 msgstr "" 37.7782 37.7783 #. type: Content of: <book><chapter><sect1><para> 37.7784 -#: ../en/ch08-branch.xml:348 37.7785 +#: ../en/ch07-branch.xml:348 37.7786 msgid "" 37.7787 "To start working with named branches, use the <command role=\"hg-cmd\">hg " 37.7788 "branches</command> command. This command lists the named branches already " 37.7789 @@ -8590,14 +7673,14 @@ 37.7790 msgstr "" 37.7791 37.7792 #. type: Content of: <book><chapter><sect1><para> 37.7793 -#: ../en/ch08-branch.xml:355 37.7794 +#: ../en/ch07-branch.xml:355 37.7795 msgid "" 37.7796 "Since you haven't created any named branches yet, the only one that exists is " 37.7797 "<literal>default</literal>." 37.7798 msgstr "" 37.7799 37.7800 #. type: Content of: <book><chapter><sect1><para> 37.7801 -#: ../en/ch08-branch.xml:358 37.7802 +#: ../en/ch07-branch.xml:358 37.7803 msgid "" 37.7804 "To find out what the <quote>current</quote> branch is, run the <command role=" 37.7805 "\"hg-cmd\">hg branch</command> command, giving it no arguments. This tells " 37.7806 @@ -8606,7 +7689,7 @@ 37.7807 37.7808 # 37.7809 #. type: Content of: <book><chapter><sect1><para> 37.7810 -#: ../en/ch08-branch.xml:365 37.7811 +#: ../en/ch07-branch.xml:365 37.7812 msgid "" 37.7813 "To create a new branch, run the <command role=\"hg-cmd\">hg branch</command> " 37.7814 "command again. This time, give it one argument: the name of the branch you " 37.7815 @@ -8614,7 +7697,7 @@ 37.7816 msgstr "" 37.7817 37.7818 #. type: Content of: <book><chapter><sect1><para> 37.7819 -#: ../en/ch08-branch.xml:371 37.7820 +#: ../en/ch07-branch.xml:371 37.7821 msgid "" 37.7822 "After you've created a branch, you might wonder what effect the <command role=" 37.7823 "\"hg-cmd\">hg branch</command> command has had. What do the <command role=" 37.7824 @@ -8623,7 +7706,7 @@ 37.7825 msgstr "" 37.7826 37.7827 #. type: Content of: <book><chapter><sect1><para> 37.7828 -#: ../en/ch08-branch.xml:378 37.7829 +#: ../en/ch07-branch.xml:378 37.7830 msgid "" 37.7831 "Nothing has changed in the working directory, and there's been no new history " 37.7832 "created. As this suggests, running the <command role=\"hg-cmd\">hg branch</" 37.7833 @@ -8632,7 +7715,7 @@ 37.7834 msgstr "" 37.7835 37.7836 #. type: Content of: <book><chapter><sect1><para> 37.7837 -#: ../en/ch08-branch.xml:385 37.7838 +#: ../en/ch07-branch.xml:385 37.7839 msgid "" 37.7840 "When you commit a change, Mercurial records the name of the branch on which " 37.7841 "you committed. Once you've switched from the <literal>default</literal> " 37.7842 @@ -8643,7 +7726,7 @@ 37.7843 msgstr "" 37.7844 37.7845 #. type: Content of: <book><chapter><sect1><para> 37.7846 -#: ../en/ch08-branch.xml:395 37.7847 +#: ../en/ch07-branch.xml:395 37.7848 msgid "" 37.7849 "The <command role=\"hg-cmd\">hg log</command>-like commands will print the " 37.7850 "branch name of every changeset that's not on the <literal>default</literal> " 37.7851 @@ -8652,7 +7735,7 @@ 37.7852 msgstr "" 37.7853 37.7854 #. type: Content of: <book><chapter><sect1><para> 37.7855 -#: ../en/ch08-branch.xml:400 37.7856 +#: ../en/ch07-branch.xml:400 37.7857 msgid "" 37.7858 "Once you've named a branch and committed a change with that name, every " 37.7859 "subsequent commit that descends from that change will inherit the same branch " 37.7860 @@ -8661,19 +7744,19 @@ 37.7861 msgstr "" 37.7862 37.7863 #. type: Content of: <book><chapter><sect1><para> 37.7864 -#: ../en/ch08-branch.xml:408 37.7865 +#: ../en/ch07-branch.xml:408 37.7866 msgid "" 37.7867 "In practice, this is something you won't do very often, as branch names tend " 37.7868 "to have fairly long lifetimes. (This isn't a rule, just an observation.)" 37.7869 msgstr "" 37.7870 37.7871 #. type: Content of: <book><chapter><sect1><title> 37.7872 -#: ../en/ch08-branch.xml:414 37.7873 +#: ../en/ch07-branch.xml:414 37.7874 msgid "Dealing with multiple named branches in a repository" 37.7875 msgstr "在版本库中处理多个命名分支" 37.7876 37.7877 #. type: Content of: <book><chapter><sect1><para> 37.7878 -#: ../en/ch08-branch.xml:417 37.7879 +#: ../en/ch07-branch.xml:417 37.7880 msgid "" 37.7881 "If you have more than one named branch in a repository, Mercurial will " 37.7882 "remember the branch that your working directory on when you start a command " 37.7883 @@ -8686,7 +7769,7 @@ 37.7884 msgstr "" 37.7885 37.7886 #. type: Content of: <book><chapter><sect1><para> 37.7887 -#: ../en/ch08-branch.xml:427 37.7888 +#: ../en/ch07-branch.xml:427 37.7889 msgid "" 37.7890 "This behaviour is a little subtle, so let's see it in action. First, let's " 37.7891 "remind ourselves what branch we're currently on, and what branches are in our " 37.7892 @@ -8694,14 +7777,14 @@ 37.7893 msgstr "" 37.7894 37.7895 #. type: Content of: <book><chapter><sect1><para> 37.7896 -#: ../en/ch08-branch.xml:433 37.7897 +#: ../en/ch07-branch.xml:433 37.7898 msgid "" 37.7899 "We're on the <literal>bar</literal> branch, but there also exists an older " 37.7900 "<command role=\"hg-cmd\">hg foo</command> branch." 37.7901 msgstr "" 37.7902 37.7903 #. type: Content of: <book><chapter><sect1><para> 37.7904 -#: ../en/ch08-branch.xml:437 37.7905 +#: ../en/ch07-branch.xml:437 37.7906 msgid "" 37.7907 "We can <command role=\"hg-cmd\">hg update</command> back and forth between " 37.7908 "the tips of the <literal>foo</literal> and <literal>bar</literal> branches " 37.7909 @@ -8712,7 +7795,7 @@ 37.7910 37.7911 # 37.7912 #. type: Content of: <book><chapter><sect1><para> 37.7913 -#: ../en/ch08-branch.xml:446 37.7914 +#: ../en/ch07-branch.xml:446 37.7915 msgid "" 37.7916 "If we go back to the <literal>foo</literal> branch and then run <command role=" 37.7917 "\"hg-cmd\">hg update</command>, it will keep us on <literal>foo</literal>, " 37.7918 @@ -8721,19 +7804,19 @@ 37.7919 37.7920 # 37.7921 #. type: Content of: <book><chapter><sect1><para> 37.7922 -#: ../en/ch08-branch.xml:453 37.7923 +#: ../en/ch07-branch.xml:453 37.7924 msgid "" 37.7925 "Committing a new change on the <literal>foo</literal> branch introduces a new " 37.7926 "head." 37.7927 msgstr "" 37.7928 37.7929 #. type: Content of: <book><chapter><sect1><title> 37.7930 -#: ../en/ch08-branch.xml:460 37.7931 +#: ../en/ch07-branch.xml:460 37.7932 msgid "Branch names and merging" 37.7933 msgstr "分支名称与合并" 37.7934 37.7935 #. type: Content of: <book><chapter><sect1><para> 37.7936 -#: ../en/ch08-branch.xml:462 37.7937 +#: ../en/ch07-branch.xml:462 37.7938 msgid "" 37.7939 "As you've probably noticed, merges in Mercurial are not symmetrical. Let's " 37.7940 "say our repository has two heads, 17 and 23. If I <command role=\"hg-cmd" 37.7941 @@ -8745,7 +7828,7 @@ 37.7942 msgstr "" 37.7943 37.7944 #. type: Content of: <book><chapter><sect1><para> 37.7945 -#: ../en/ch08-branch.xml:472 37.7946 +#: ../en/ch07-branch.xml:472 37.7947 msgid "" 37.7948 "This affects Mercurial's choice of branch name when you merge. After a " 37.7949 "merge, Mercurial will retain the branch name of the first parent when you " 37.7950 @@ -8755,7 +7838,7 @@ 37.7951 msgstr "" 37.7952 37.7953 #. type: Content of: <book><chapter><sect1><para> 37.7954 -#: ../en/ch08-branch.xml:479 37.7955 +#: ../en/ch07-branch.xml:479 37.7956 msgid "" 37.7957 "It's not unusual for a repository to contain multiple heads, each with the " 37.7958 "same branch name. Let's say I'm working on the <literal>foo</literal> " 37.7959 @@ -8767,7 +7850,7 @@ 37.7960 37.7961 # 37.7962 #. type: Content of: <book><chapter><sect1><para> 37.7963 -#: ../en/ch08-branch.xml:487 37.7964 +#: ../en/ch07-branch.xml:487 37.7965 msgid "" 37.7966 "But if I'm working on the <literal>bar</literal> branch, and I merge work " 37.7967 "from the <literal>foo</literal> branch, the result will remain on the " 37.7968 @@ -8775,7 +7858,7 @@ 37.7969 msgstr "" 37.7970 37.7971 #. type: Content of: <book><chapter><sect1><para> 37.7972 -#: ../en/ch08-branch.xml:493 37.7973 +#: ../en/ch07-branch.xml:493 37.7974 msgid "" 37.7975 "To give a more concrete example, if I'm working on the <literal>bleeding-" 37.7976 "edge</literal> branch, and I want to bring in the latest fixes from the " 37.7977 @@ -8785,12 +7868,12 @@ 37.7978 msgstr "" 37.7979 37.7980 #. type: Content of: <book><chapter><sect1><title> 37.7981 -#: ../en/ch08-branch.xml:502 37.7982 +#: ../en/ch07-branch.xml:502 37.7983 msgid "Branch naming is generally useful" 37.7984 msgstr "分支名称通常都很有用" 37.7985 37.7986 #. type: Content of: <book><chapter><sect1><para> 37.7987 -#: ../en/ch08-branch.xml:504 37.7988 +#: ../en/ch07-branch.xml:504 37.7989 msgid "" 37.7990 "You shouldn't think of named branches as applicable only to situations where " 37.7991 "you have multiple long-lived branches cohabiting in a single repository. " 37.7992 @@ -8798,7 +7881,7 @@ 37.7993 msgstr "" 37.7994 37.7995 #. type: Content of: <book><chapter><sect1><para> 37.7996 -#: ../en/ch08-branch.xml:509 37.7997 +#: ../en/ch07-branch.xml:509 37.7998 msgid "" 37.7999 "In the simplest case, giving a name to each branch gives you a permanent " 37.8000 "record of which branch a changeset originated on. This gives you more " 37.8001 @@ -8807,7 +7890,7 @@ 37.8002 msgstr "" 37.8003 37.8004 #. type: Content of: <book><chapter><sect1><para> 37.8005 -#: ../en/ch08-branch.xml:514 37.8006 +#: ../en/ch07-branch.xml:514 37.8007 msgid "" 37.8008 "If you're working with shared repositories, you can set up a <literal role=" 37.8009 "\"hook\">pretxnchangegroup</literal> hook on each that will block incoming " 37.8010 @@ -8819,12 +7902,12 @@ 37.8011 msgstr "" 37.8012 37.8013 #. type: Content of: <book><chapter><title> 37.8014 -#: ../en/ch09-undo.xml:5 37.8015 +#: ../en/ch08-undo.xml:5 37.8016 msgid "Finding and fixing mistakes" 37.8017 msgstr "查找和修改错误" 37.8018 37.8019 #. type: Content of: <book><chapter><para> 37.8020 -#: ../en/ch09-undo.xml:7 37.8021 +#: ../en/ch08-undo.xml:7 37.8022 msgid "" 37.8023 "To err might be human, but to really handle the consequences well takes a top-" 37.8024 "notch revision control system. In this chapter, we'll discuss some of the " 37.8025 @@ -8834,17 +7917,17 @@ 37.8026 msgstr "" 37.8027 37.8028 #. type: Content of: <book><chapter><sect1><title> 37.8029 -#: ../en/ch09-undo.xml:15 37.8030 +#: ../en/ch08-undo.xml:15 37.8031 msgid "Erasing local history" 37.8032 msgstr "销毁本地历史" 37.8033 37.8034 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8035 -#: ../en/ch09-undo.xml:18 37.8036 +#: ../en/ch08-undo.xml:18 37.8037 msgid "The accidental commit" 37.8038 msgstr "意外的提交" 37.8039 37.8040 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8041 -#: ../en/ch09-undo.xml:20 37.8042 +#: ../en/ch08-undo.xml:20 37.8043 msgid "" 37.8044 "I have the occasional but persistent problem of typing rather more quickly " 37.8045 "than I can think, which sometimes results in me committing a changeset that " 37.8046 @@ -8855,12 +7938,12 @@ 37.8047 msgstr "" 37.8048 37.8049 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8050 -#: ../en/ch09-undo.xml:31 37.8051 +#: ../en/ch08-undo.xml:31 37.8052 msgid "Rolling back a transaction" 37.8053 msgstr "回滚一个事务" 37.8054 37.8055 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8056 -#: ../en/ch09-undo.xml:33 37.8057 +#: ../en/ch08-undo.xml:33 37.8058 msgid "" 37.8059 "In section <xref linkend=\"sec.concepts.txn\"/>, I mentioned that Mercurial " 37.8060 "treats each modification of a repository as a <emphasis>transaction</" 37.8061 @@ -8873,7 +7956,7 @@ 37.8062 msgstr "" 37.8063 37.8064 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8065 -#: ../en/ch09-undo.xml:43 37.8066 +#: ../en/ch08-undo.xml:43 37.8067 msgid "" 37.8068 "Here's a mistake that I often find myself making: committing a change in " 37.8069 "which I've created a new file, but forgotten to <command role=\"hg-cmd\">hg " 37.8070 @@ -8881,14 +7964,14 @@ 37.8071 msgstr "" 37.8072 37.8073 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8074 -#: ../en/ch09-undo.xml:50 37.8075 +#: ../en/ch08-undo.xml:50 37.8076 msgid "" 37.8077 "Looking at the output of <command role=\"hg-cmd\">hg status</command> after " 37.8078 "the commit immediately confirms the error." 37.8079 msgstr "" 37.8080 37.8081 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8082 -#: ../en/ch09-undo.xml:56 37.8083 +#: ../en/ch08-undo.xml:56 37.8084 msgid "" 37.8085 "The commit captured the changes to the file <filename>a</filename>, but not " 37.8086 "the new file <filename>b</filename>. If I were to push this changeset to a " 37.8087 @@ -8899,7 +7982,7 @@ 37.8088 msgstr "" 37.8089 37.8090 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8091 -#: ../en/ch09-undo.xml:65 37.8092 +#: ../en/ch08-undo.xml:65 37.8093 msgid "" 37.8094 "However, luck is with me&emdash;I've caught my error before I pushed the " 37.8095 "changeset. I use the <command role=\"hg-cmd\">hg rollback</command> command, " 37.8096 @@ -8907,7 +7990,7 @@ 37.8097 msgstr "" 37.8098 37.8099 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8100 -#: ../en/ch09-undo.xml:72 37.8101 +#: ../en/ch08-undo.xml:72 37.8102 msgid "" 37.8103 "Notice that the changeset is no longer present in the repository's history, " 37.8104 "and the working directory once again thinks that the file <filename>a</" 37.8105 @@ -8918,12 +8001,12 @@ 37.8106 msgstr "" 37.8107 37.8108 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8109 -#: ../en/ch09-undo.xml:85 37.8110 +#: ../en/ch08-undo.xml:85 37.8111 msgid "The erroneous pull" 37.8112 msgstr "错误的抓取" 37.8113 37.8114 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8115 -#: ../en/ch09-undo.xml:87 37.8116 +#: ../en/ch08-undo.xml:87 37.8117 msgid "" 37.8118 "It's common practice with Mercurial to maintain separate development branches " 37.8119 "of a project in different repositories. Your development team might have one " 37.8120 @@ -8932,7 +8015,7 @@ 37.8121 msgstr "" 37.8122 37.8123 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8124 -#: ../en/ch09-undo.xml:94 37.8125 +#: ../en/ch08-undo.xml:94 37.8126 msgid "" 37.8127 "Given this, you can imagine that the consequences could be messy if you had a " 37.8128 "local <quote>0.9</quote> repository, and accidentally pulled changes from the " 37.8129 @@ -8945,7 +8028,7 @@ 37.8130 msgstr "" 37.8131 37.8132 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8133 -#: ../en/ch09-undo.xml:106 37.8134 +#: ../en/ch08-undo.xml:106 37.8135 msgid "" 37.8136 "The <command role=\"hg-cmd\">hg rollback</command> command will work nicely " 37.8137 "to expunge all of the changesets that you just pulled. Mercurial groups all " 37.8138 @@ -8955,12 +8038,12 @@ 37.8139 msgstr "" 37.8140 37.8141 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8142 -#: ../en/ch09-undo.xml:115 37.8143 +#: ../en/ch08-undo.xml:115 37.8144 msgid "Rolling back is useless once you've pushed" 37.8145 msgstr "当完成推送后,回滚是无效的" 37.8146 37.8147 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8148 -#: ../en/ch09-undo.xml:117 37.8149 +#: ../en/ch08-undo.xml:117 37.8150 msgid "" 37.8151 "The value of the <command role=\"hg-cmd\">hg rollback</command> command drops " 37.8152 "to zero once you've pushed your changes to another repository. Rolling back " 37.8153 @@ -8971,7 +8054,7 @@ 37.8154 msgstr "" 37.8155 37.8156 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8157 -#: ../en/ch09-undo.xml:126 37.8158 +#: ../en/ch08-undo.xml:126 37.8159 msgid "" 37.8160 "If you've pushed a change to another repository&emdash;particularly if it's a " 37.8161 "shared repository&emdash;it has essentially <quote>escaped into the wild,</" 37.8162 @@ -8982,7 +8065,7 @@ 37.8163 msgstr "" 37.8164 37.8165 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8166 -#: ../en/ch09-undo.xml:135 37.8167 +#: ../en/ch08-undo.xml:135 37.8168 msgid "" 37.8169 "(If you absolutely know for sure that the change you want to roll back is the " 37.8170 "most recent change in the repository that you pushed to, <emphasis>and</" 37.8171 @@ -8994,12 +8077,12 @@ 37.8172 msgstr "" 37.8173 37.8174 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8175 -#: ../en/ch09-undo.xml:147 37.8176 +#: ../en/ch08-undo.xml:147 37.8177 msgid "You can only roll back once" 37.8178 msgstr "你只能回滚一次" 37.8179 37.8180 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8181 -#: ../en/ch09-undo.xml:149 37.8182 +#: ../en/ch08-undo.xml:149 37.8183 msgid "" 37.8184 "Mercurial stores exactly one transaction in its transaction log; that " 37.8185 "transaction is the most recent one that occurred in the repository. This " 37.8186 @@ -9009,19 +8092,19 @@ 37.8187 msgstr "" 37.8188 37.8189 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8190 -#: ../en/ch09-undo.xml:158 37.8191 +#: ../en/ch08-undo.xml:158 37.8192 msgid "" 37.8193 "Once you've rolled back one transaction in a repository, you can't roll back " 37.8194 "again in that repository until you perform another commit or pull." 37.8195 msgstr "" 37.8196 37.8197 #. type: Content of: <book><chapter><sect1><title> 37.8198 -#: ../en/ch09-undo.xml:165 37.8199 +#: ../en/ch08-undo.xml:165 37.8200 msgid "Reverting the mistaken change" 37.8201 msgstr "撤销错误的修改" 37.8202 37.8203 #. type: Content of: <book><chapter><sect1><para> 37.8204 -#: ../en/ch09-undo.xml:167 37.8205 +#: ../en/ch08-undo.xml:167 37.8206 msgid "" 37.8207 "If you make a modification to a file, and decide that you really didn't want " 37.8208 "to change the file at all, and you haven't yet committed your changes, the " 37.8209 @@ -9033,7 +8116,7 @@ 37.8210 msgstr "" 37.8211 37.8212 #. type: Content of: <book><chapter><sect1><para> 37.8213 -#: ../en/ch09-undo.xml:176 37.8214 +#: ../en/ch08-undo.xml:176 37.8215 msgid "" 37.8216 "Let's illustrate how the <command role=\"hg-cmd\">hg revert</command> command " 37.8217 "works with yet another small example. We'll begin by modifying a file that " 37.8218 @@ -9041,14 +8124,14 @@ 37.8219 msgstr "" 37.8220 37.8221 #. type: Content of: <book><chapter><sect1><para> 37.8222 -#: ../en/ch09-undo.xml:183 37.8223 +#: ../en/ch08-undo.xml:183 37.8224 msgid "" 37.8225 "If we don't want that change, we can simply <command role=\"hg-cmd\">hg " 37.8226 "revert</command> the file." 37.8227 msgstr "" 37.8228 37.8229 #. type: Content of: <book><chapter><sect1><para> 37.8230 -#: ../en/ch09-undo.xml:189 37.8231 +#: ../en/ch08-undo.xml:189 37.8232 msgid "" 37.8233 "The <command role=\"hg-cmd\">hg revert</command> command provides us with an " 37.8234 "extra degree of safety by saving our modified file with a <filename>.orig</" 37.8235 @@ -9056,7 +8139,7 @@ 37.8236 msgstr "" 37.8237 37.8238 #. type: Content of: <book><chapter><sect1><para> 37.8239 -#: ../en/ch09-undo.xml:196 37.8240 +#: ../en/ch08-undo.xml:196 37.8241 msgid "" 37.8242 "Here is a summary of the cases that the <command role=\"hg-cmd\">hg revert</" 37.8243 "command> command can deal with. We will describe each of these in more " 37.8244 @@ -9064,26 +8147,26 @@ 37.8245 msgstr "" 37.8246 37.8247 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8248 -#: ../en/ch09-undo.xml:201 37.8249 +#: ../en/ch08-undo.xml:201 37.8250 msgid "If you modify a file, it will restore the file to its unmodified state." 37.8251 msgstr "" 37.8252 37.8253 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8254 -#: ../en/ch09-undo.xml:204 37.8255 +#: ../en/ch08-undo.xml:204 37.8256 msgid "" 37.8257 "If you <command role=\"hg-cmd\">hg add</command> a file, it will undo the " 37.8258 "<quote>added</quote> state of the file, but leave the file itself untouched." 37.8259 msgstr "" 37.8260 37.8261 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8262 -#: ../en/ch09-undo.xml:208 37.8263 +#: ../en/ch08-undo.xml:208 37.8264 msgid "" 37.8265 "If you delete a file without telling Mercurial, it will restore the file to " 37.8266 "its unmodified contents." 37.8267 msgstr "" 37.8268 37.8269 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8270 -#: ../en/ch09-undo.xml:211 37.8271 +#: ../en/ch08-undo.xml:211 37.8272 msgid "" 37.8273 "If you use the <command role=\"hg-cmd\">hg remove</command> command to remove " 37.8274 "a file, it will undo the <quote>removed</quote> state of the file, and " 37.8275 @@ -9091,12 +8174,12 @@ 37.8276 msgstr "" 37.8277 37.8278 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8279 -#: ../en/ch09-undo.xml:218 37.8280 +#: ../en/ch08-undo.xml:218 37.8281 msgid "File management errors" 37.8282 msgstr "文件管理错误" 37.8283 37.8284 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8285 -#: ../en/ch09-undo.xml:220 37.8286 +#: ../en/ch08-undo.xml:220 37.8287 msgid "" 37.8288 "The <command role=\"hg-cmd\">hg revert</command> command is useful for more " 37.8289 "than just modified files. It lets you reverse the results of all of " 37.8290 @@ -9106,7 +8189,7 @@ 37.8291 37.8292 # 37.8293 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8294 -#: ../en/ch09-undo.xml:226 37.8295 +#: ../en/ch08-undo.xml:226 37.8296 msgid "" 37.8297 "If you <command role=\"hg-cmd\">hg add</command> a file, then decide that in " 37.8298 "fact you don't want Mercurial to track it, use <command role=\"hg-cmd\">hg " 37.8299 @@ -9115,7 +8198,7 @@ 37.8300 msgstr "" 37.8301 37.8302 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8303 -#: ../en/ch09-undo.xml:234 37.8304 +#: ../en/ch08-undo.xml:234 37.8305 msgid "" 37.8306 "Similarly, if you ask Mercurial to <command role=\"hg-cmd\">hg remove</" 37.8307 "command> a file, you can use <command role=\"hg-cmd\">hg revert</command> to " 37.8308 @@ -9127,7 +8210,7 @@ 37.8309 37.8310 # 37.8311 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8312 -#: ../en/ch09-undo.xml:245 37.8313 +#: ../en/ch08-undo.xml:245 37.8314 msgid "" 37.8315 "If you revert a <command role=\"hg-cmd\">hg copy</command>, the copied-to " 37.8316 "file remains in your working directory afterwards, untracked. Since a copy " 37.8317 @@ -9136,12 +8219,12 @@ 37.8318 msgstr "" 37.8319 37.8320 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.8321 -#: ../en/ch09-undo.xml:254 37.8322 +#: ../en/ch08-undo.xml:254 37.8323 msgid "A slightly special case: reverting a rename" 37.8324 msgstr "一个稍微特别的案例:撤销改名" 37.8325 37.8326 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8327 -#: ../en/ch09-undo.xml:256 37.8328 +#: ../en/ch08-undo.xml:256 37.8329 msgid "" 37.8330 "If you <command role=\"hg-cmd\">hg rename</command> a file, there is one " 37.8331 "small detail that you should remember. When you <command role=\"hg-cmd\">hg " 37.8332 @@ -9150,7 +8233,7 @@ 37.8333 msgstr "" 37.8334 37.8335 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8336 -#: ../en/ch09-undo.xml:264 37.8337 +#: ../en/ch08-undo.xml:264 37.8338 msgid "" 37.8339 "As you can see from the output of <command role=\"hg-cmd\">hg status</" 37.8340 "command>, the renamed-to file is no longer identified as added, but the " 37.8341 @@ -9159,19 +8242,19 @@ 37.8342 msgstr "" 37.8343 37.8344 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8345 -#: ../en/ch09-undo.xml:273 37.8346 +#: ../en/ch08-undo.xml:273 37.8347 msgid "" 37.8348 "So remember, to revert a <command role=\"hg-cmd\">hg rename</command>, you " 37.8349 "must provide <emphasis>both</emphasis> the source and destination names." 37.8350 msgstr "" 37.8351 37.8352 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8353 -#: ../en/ch09-undo.xml:278 37.8354 +#: ../en/ch08-undo.xml:278 37.8355 msgid "% TODO: the output doesn't look like it will be removed!" 37.8356 msgstr "" 37.8357 37.8358 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8359 -#: ../en/ch09-undo.xml:281 37.8360 +#: ../en/ch08-undo.xml:281 37.8361 msgid "" 37.8362 "(By the way, if you rename a file, then modify the renamed-to file, then " 37.8363 "revert both components of the rename, when Mercurial restores the file that " 37.8364 @@ -9181,19 +8264,19 @@ 37.8365 msgstr "" 37.8366 37.8367 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8368 -#: ../en/ch09-undo.xml:288 37.8369 +#: ../en/ch08-undo.xml:288 37.8370 msgid "" 37.8371 "These fiddly aspects of reverting a rename arguably constitute a small bug in " 37.8372 "Mercurial." 37.8373 msgstr "" 37.8374 37.8375 #. type: Content of: <book><chapter><sect1><title> 37.8376 -#: ../en/ch09-undo.xml:295 37.8377 +#: ../en/ch08-undo.xml:295 37.8378 msgid "Dealing with committed changes" 37.8379 msgstr "处理已经提交的修改" 37.8380 37.8381 #. type: Content of: <book><chapter><sect1><para> 37.8382 -#: ../en/ch09-undo.xml:297 37.8383 +#: ../en/ch08-undo.xml:297 37.8384 msgid "" 37.8385 "Consider a case where you have committed a change $a$, and another change $b$ " 37.8386 "on top of it; you then realise that change $a$ was incorrect. Mercurial lets " 37.8387 @@ -9202,7 +8285,7 @@ 37.8388 msgstr "" 37.8389 37.8390 #. type: Content of: <book><chapter><sect1><para> 37.8391 -#: ../en/ch09-undo.xml:303 37.8392 +#: ../en/ch08-undo.xml:303 37.8393 msgid "" 37.8394 "Before you read this section, here's something to keep in mind: the <command " 37.8395 "role=\"hg-cmd\">hg backout</command> command undoes changes by " 37.8396 @@ -9213,12 +8296,12 @@ 37.8397 msgstr "" 37.8398 37.8399 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8400 -#: ../en/ch09-undo.xml:312 37.8401 +#: ../en/ch08-undo.xml:312 37.8402 msgid "Backing out a changeset" 37.8403 msgstr "恢复一个修改集" 37.8404 37.8405 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8406 -#: ../en/ch09-undo.xml:314 37.8407 +#: ../en/ch08-undo.xml:314 37.8408 msgid "" 37.8409 "The <command role=\"hg-cmd\">hg backout</command> command lets you " 37.8410 "<quote>undo</quote> the effects of an entire changeset in an automated " 37.8411 @@ -9230,7 +8313,7 @@ 37.8412 37.8413 # 37.8414 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8415 -#: ../en/ch09-undo.xml:323 37.8416 +#: ../en/ch08-undo.xml:323 37.8417 msgid "" 37.8418 "The operation of the <command role=\"hg-cmd\">hg backout</command> command is " 37.8419 "a little intricate, so let's illustrate it with some examples. First, we'll " 37.8420 @@ -9238,7 +8321,7 @@ 37.8421 msgstr "" 37.8422 37.8423 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8424 -#: ../en/ch09-undo.xml:330 37.8425 +#: ../en/ch08-undo.xml:330 37.8426 msgid "" 37.8427 "The <command role=\"hg-cmd\">hg backout</command> command takes a single " 37.8428 "changeset ID as its argument; this is the changeset to back out. Normally, " 37.8429 @@ -9249,17 +8332,17 @@ 37.8430 msgstr "" 37.8431 37.8432 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8433 -#: ../en/ch09-undo.xml:341 37.8434 +#: ../en/ch08-undo.xml:341 37.8435 msgid "Backing out the tip changeset" 37.8436 msgstr "恢复顶点修改集" 37.8437 37.8438 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8439 -#: ../en/ch09-undo.xml:343 37.8440 +#: ../en/ch08-undo.xml:343 37.8441 msgid "We're going to start by backing out the last changeset we committed." 37.8442 msgstr "" 37.8443 37.8444 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8445 -#: ../en/ch09-undo.xml:348 37.8446 +#: ../en/ch08-undo.xml:348 37.8447 msgid "" 37.8448 "You can see that the second line from <filename>myfile</filename> is no " 37.8449 "longer present. Taking a look at the output of <command role=\"hg-cmd\">hg " 37.8450 @@ -9273,25 +8356,25 @@ 37.8451 msgstr "" 37.8452 37.8453 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.8454 -#: ../en/ch09-undo.xml:364 37.8455 +#: ../en/ch08-undo.xml:364 37.8456 msgid "" 37.8457 "<imageobject><imagedata fileref=\"images/undo-simple.png\"/> </imageobject>" 37.8458 msgstr "" 37.8459 37.8460 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.8461 -#: ../en/ch09-undo.xml:367 ../en/ch09-undo.xml:486 37.8462 +#: ../en/ch08-undo.xml:367 ../en/ch08-undo.xml:486 37.8463 msgid "" 37.8464 "Backing out a change using the <command role=\"hg-cmd\">hg backout</command> " 37.8465 "command" 37.8466 msgstr "" 37.8467 37.8468 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8469 -#: ../en/ch09-undo.xml:376 37.8470 +#: ../en/ch08-undo.xml:376 37.8471 msgid "Backing out a non-tip change" 37.8472 msgstr "恢复非顶点的修改" 37.8473 37.8474 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8475 -#: ../en/ch09-undo.xml:378 37.8476 +#: ../en/ch08-undo.xml:378 37.8477 msgid "" 37.8478 "If you want to back out a change other than the last one you committed, pass " 37.8479 "the <option role=\"hg-opt-backout\">--merge</option> option to the <command " 37.8480 @@ -9299,14 +8382,14 @@ 37.8481 msgstr "" 37.8482 37.8483 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8484 -#: ../en/ch09-undo.xml:385 37.8485 +#: ../en/ch08-undo.xml:385 37.8486 msgid "" 37.8487 "This makes backing out any changeset a <quote>one-shot</quote> operation " 37.8488 "that's usually simple and fast." 37.8489 msgstr "" 37.8490 37.8491 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8492 -#: ../en/ch09-undo.xml:391 37.8493 +#: ../en/ch08-undo.xml:391 37.8494 msgid "" 37.8495 "If you take a look at the contents of <filename>myfile</filename> after the " 37.8496 "backout finishes, you'll see that the first and third changes are present, " 37.8497 @@ -9314,7 +8397,7 @@ 37.8498 msgstr "" 37.8499 37.8500 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8501 -#: ../en/ch09-undo.xml:398 37.8502 +#: ../en/ch08-undo.xml:398 37.8503 msgid "" 37.8504 "As the graphical history in figure <xref endterm=\"fig.undo.backout-non-tip." 37.8505 "caption\" linkend=\"fig.undo.backout-non-tip\"/> illustrates, Mercurial " 37.8506 @@ -9327,27 +8410,27 @@ 37.8507 msgstr "" 37.8508 37.8509 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8510 -#: ../en/ch09-undo.xml:410 37.8511 +#: ../en/ch08-undo.xml:410 37.8512 msgid "" 37.8513 "% TODO: to me it looks like mercurial doesn't commit the second merge " 37.8514 "automatically!" 37.8515 msgstr "" 37.8516 37.8517 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.8518 -#: ../en/ch09-undo.xml:415 37.8519 +#: ../en/ch08-undo.xml:415 37.8520 msgid "" 37.8521 "<imageobject><imagedata fileref=\"images/undo-non-tip.png\"/> </imageobject>" 37.8522 msgstr "" 37.8523 37.8524 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.8525 -#: ../en/ch09-undo.xml:418 37.8526 +#: ../en/ch08-undo.xml:418 37.8527 msgid "" 37.8528 "Automated backout of a non-tip change using the <command role=\"hg-cmd\">hg " 37.8529 "backout</command> command" 37.8530 msgstr "" 37.8531 37.8532 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8533 -#: ../en/ch09-undo.xml:424 37.8534 +#: ../en/ch08-undo.xml:424 37.8535 msgid "" 37.8536 "The result is that you end up <quote>back where you were</quote>, only with " 37.8537 "some extra history that undoes the effect of the changeset you wanted to back " 37.8538 @@ -9355,12 +8438,12 @@ 37.8539 msgstr "" 37.8540 37.8541 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.8542 -#: ../en/ch09-undo.xml:429 37.8543 +#: ../en/ch08-undo.xml:429 37.8544 msgid "Always use the <option role=\"hg-opt-backout\">--merge</option> option" 37.8545 msgstr "始终使用选项 <option role=\"hg-opt-backout\">--merge</option>" 37.8546 37.8547 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.8548 -#: ../en/ch09-undo.xml:432 37.8549 +#: ../en/ch08-undo.xml:432 37.8550 msgid "" 37.8551 "In fact, since the <option role=\"hg-opt-backout\">--merge</option> option " 37.8552 "will do the <quote>right thing</quote> whether or not the changeset you're " 37.8553 @@ -9370,12 +8453,12 @@ 37.8554 msgstr "" 37.8555 37.8556 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8557 -#: ../en/ch09-undo.xml:443 37.8558 +#: ../en/ch08-undo.xml:443 37.8559 msgid "Gaining more control of the backout process" 37.8560 msgstr "在恢复处理中获得更多控制" 37.8561 37.8562 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8563 -#: ../en/ch09-undo.xml:445 37.8564 +#: ../en/ch08-undo.xml:445 37.8565 msgid "" 37.8566 "While I've recommended that you always use the <option role=\"hg-opt-backout" 37.8567 "\">--merge</option> option when backing out a change, the <command role=\"hg-" 37.8568 @@ -9388,14 +8471,14 @@ 37.8569 msgstr "" 37.8570 37.8571 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8572 -#: ../en/ch09-undo.xml:458 37.8573 +#: ../en/ch08-undo.xml:458 37.8574 msgid "" 37.8575 "As with our earlier example, We'll commit a third changeset, then back out " 37.8576 "its parent, and see what happens." 37.8577 msgstr "" 37.8578 37.8579 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8580 -#: ../en/ch09-undo.xml:464 37.8581 +#: ../en/ch08-undo.xml:464 37.8582 msgid "" 37.8583 "Our new changeset is again a descendant of the changeset we backout out; it's " 37.8584 "thus a new head, <emphasis>not</emphasis> a descendant of the changeset that " 37.8585 @@ -9404,7 +8487,7 @@ 37.8586 msgstr "" 37.8587 37.8588 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8589 -#: ../en/ch09-undo.xml:472 37.8590 +#: ../en/ch08-undo.xml:472 37.8591 msgid "" 37.8592 "Again, it's easier to see what has happened by looking at a graph of the " 37.8593 "revision history, in figure <xref endterm=\"fig.undo.backout-manual.caption\" " 37.8594 @@ -9415,13 +8498,13 @@ 37.8595 msgstr "" 37.8596 37.8597 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.8598 -#: ../en/ch09-undo.xml:483 37.8599 +#: ../en/ch08-undo.xml:483 37.8600 msgid "" 37.8601 "<imageobject><imagedata fileref=\"images/undo-manual.png\"/> </imageobject>" 37.8602 msgstr "" 37.8603 37.8604 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8605 -#: ../en/ch09-undo.xml:492 37.8606 +#: ../en/ch08-undo.xml:492 37.8607 msgid "" 37.8608 "After the <command role=\"hg-cmd\">hg backout</command> command has " 37.8609 "completed, it leaves the new <quote>backout</quote> changeset as the parent " 37.8610 @@ -9429,12 +8512,12 @@ 37.8611 msgstr "" 37.8612 37.8613 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8614 -#: ../en/ch09-undo.xml:499 37.8615 +#: ../en/ch08-undo.xml:499 37.8616 msgid "Now we have two isolated sets of changes." 37.8617 msgstr "" 37.8618 37.8619 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8620 -#: ../en/ch09-undo.xml:503 37.8621 +#: ../en/ch08-undo.xml:503 37.8622 msgid "" 37.8623 "Let's think about what we expect to see as the contents of <filename>myfile</" 37.8624 "filename> now. The first change should be present, because we've never " 37.8625 @@ -9445,14 +8528,14 @@ 37.8626 msgstr "" 37.8627 37.8628 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8629 -#: ../en/ch09-undo.xml:513 37.8630 +#: ../en/ch08-undo.xml:513 37.8631 msgid "" 37.8632 "To get the third change back into the file, we just do a normal merge of our " 37.8633 "two heads." 37.8634 msgstr "" 37.8635 37.8636 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8637 -#: ../en/ch09-undo.xml:518 37.8638 +#: ../en/ch08-undo.xml:518 37.8639 msgid "" 37.8640 "Afterwards, the graphical history of our repository looks like figure <xref " 37.8641 "endterm=\"fig.undo.backout-manual-merge.caption\" linkend=\"fig.undo.backout-" 37.8642 @@ -9460,45 +8543,45 @@ 37.8643 msgstr "" 37.8644 37.8645 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.8646 -#: ../en/ch09-undo.xml:525 37.8647 +#: ../en/ch08-undo.xml:525 37.8648 msgid "" 37.8649 "<imageobject><imagedata fileref=\"images/undo-manual-merge.png\"/> </" 37.8650 "imageobject>" 37.8651 msgstr "" 37.8652 37.8653 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.8654 -#: ../en/ch09-undo.xml:528 37.8655 +#: ../en/ch08-undo.xml:528 37.8656 msgid "Manually merging a backout change" 37.8657 msgstr "" 37.8658 37.8659 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8660 -#: ../en/ch09-undo.xml:535 37.8661 +#: ../en/ch08-undo.xml:535 37.8662 msgid "Why <command role=\"hg-cmd\">hg backout</command> works as it does" 37.8663 msgstr "<command role=\"hg-cmd\">hg backout</command> 的内幕" 37.8664 37.8665 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8666 -#: ../en/ch09-undo.xml:538 37.8667 +#: ../en/ch08-undo.xml:538 37.8668 msgid "" 37.8669 "Here's a brief description of how the <command role=\"hg-cmd\">hg backout</" 37.8670 "command> command works." 37.8671 msgstr "" 37.8672 37.8673 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8674 -#: ../en/ch09-undo.xml:541 37.8675 +#: ../en/ch08-undo.xml:541 37.8676 msgid "" 37.8677 "It ensures that the working directory is <quote>clean</quote>, i.e. that the " 37.8678 "output of <command role=\"hg-cmd\">hg status</command> would be empty." 37.8679 msgstr "" 37.8680 37.8681 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8682 -#: ../en/ch09-undo.xml:545 37.8683 +#: ../en/ch08-undo.xml:545 37.8684 msgid "" 37.8685 "It remembers the current parent of the working directory. Let's call this " 37.8686 "changeset <literal>orig</literal>" 37.8687 msgstr "" 37.8688 37.8689 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8690 -#: ../en/ch09-undo.xml:549 37.8691 +#: ../en/ch08-undo.xml:549 37.8692 msgid "" 37.8693 "It does the equivalent of a <command role=\"hg-cmd\">hg update</command> to " 37.8694 "sync the working directory to the changeset you want to back out. Let's call " 37.8695 @@ -9506,14 +8589,14 @@ 37.8696 msgstr "" 37.8697 37.8698 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8699 -#: ../en/ch09-undo.xml:554 37.8700 +#: ../en/ch08-undo.xml:554 37.8701 msgid "" 37.8702 "It finds the parent of that changeset. Let's call that changeset " 37.8703 "<literal>parent</literal>." 37.8704 msgstr "" 37.8705 37.8706 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8707 -#: ../en/ch09-undo.xml:557 37.8708 +#: ../en/ch08-undo.xml:557 37.8709 msgid "" 37.8710 "For each file that the <literal>backout</literal> changeset affected, it does " 37.8711 "the equivalent of a <command role=\"hg-cmd\">hg revert -r parent</command> on " 37.8712 @@ -9522,14 +8605,14 @@ 37.8713 msgstr "" 37.8714 37.8715 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8716 -#: ../en/ch09-undo.xml:564 37.8717 +#: ../en/ch08-undo.xml:564 37.8718 msgid "" 37.8719 "It commits the result as a new changeset. This changeset has " 37.8720 "<literal>backout</literal> as its parent." 37.8721 msgstr "" 37.8722 37.8723 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.8724 -#: ../en/ch09-undo.xml:568 37.8725 +#: ../en/ch08-undo.xml:568 37.8726 msgid "" 37.8727 "If you specify <option role=\"hg-opt-backout\">--merge</option> on the " 37.8728 "command line, it merges with <literal>orig</literal>, and commits the result " 37.8729 @@ -9537,7 +8620,7 @@ 37.8730 msgstr "" 37.8731 37.8732 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8733 -#: ../en/ch09-undo.xml:574 37.8734 +#: ../en/ch08-undo.xml:574 37.8735 msgid "" 37.8736 "An alternative way to implement the <command role=\"hg-cmd\">hg backout</" 37.8737 "command> command would be to <command role=\"hg-cmd\">hg export</command> the " 37.8738 @@ -9548,7 +8631,7 @@ 37.8739 msgstr "" 37.8740 37.8741 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8742 -#: ../en/ch09-undo.xml:584 37.8743 +#: ../en/ch08-undo.xml:584 37.8744 msgid "" 37.8745 "The reason that <command role=\"hg-cmd\">hg backout</command> does an update, " 37.8746 "a commit, a merge, and another commit is to give the merge machinery the best " 37.8747 @@ -9557,7 +8640,7 @@ 37.8748 msgstr "" 37.8749 37.8750 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8751 -#: ../en/ch09-undo.xml:591 37.8752 +#: ../en/ch08-undo.xml:591 37.8753 msgid "" 37.8754 "If you're backing out a changeset that's 100 revisions back in your project's " 37.8755 "history, the chances that the <command>patch</command> command will be able " 37.8756 @@ -9572,12 +8655,12 @@ 37.8757 msgstr "" 37.8758 37.8759 #. type: Content of: <book><chapter><sect1><title> 37.8760 -#: ../en/ch09-undo.xml:608 37.8761 +#: ../en/ch08-undo.xml:608 37.8762 msgid "Changes that should never have been" 37.8763 msgstr "不该发生的修改" 37.8764 37.8765 #. type: Content of: <book><chapter><sect1><para> 37.8766 -#: ../en/ch09-undo.xml:610 37.8767 +#: ../en/ch08-undo.xml:610 37.8768 msgid "" 37.8769 "Most of the time, the <command role=\"hg-cmd\">hg backout</command> command " 37.8770 "is exactly what you need if you want to undo the effects of a change. It " 37.8771 @@ -9586,7 +8669,7 @@ 37.8772 msgstr "" 37.8773 37.8774 #. type: Content of: <book><chapter><sect1><para> 37.8775 -#: ../en/ch09-undo.xml:616 37.8776 +#: ../en/ch08-undo.xml:616 37.8777 msgid "" 37.8778 "On rare occasions, though, you may find that you've committed a change that " 37.8779 "really should not be present in the repository at all. For example, it would " 37.8780 @@ -9598,7 +8681,7 @@ 37.8781 msgstr "" 37.8782 37.8783 #. type: Content of: <book><chapter><sect1><para> 37.8784 -#: ../en/ch09-undo.xml:625 37.8785 +#: ../en/ch08-undo.xml:625 37.8786 msgid "" 37.8787 "Before I discuss the options that you have if you commit a <quote>brown paper " 37.8788 "bag</quote> change (the kind that's so bad that you want to pull a brown " 37.8789 @@ -9607,7 +8690,7 @@ 37.8790 msgstr "" 37.8791 37.8792 #. type: Content of: <book><chapter><sect1><para> 37.8793 -#: ../en/ch09-undo.xml:630 37.8794 +#: ../en/ch08-undo.xml:630 37.8795 msgid "" 37.8796 "Since Mercurial treats history as accumulative&emdash;every change builds on " 37.8797 "top of all changes that preceded it&emdash;you generally can't just make " 37.8798 @@ -9619,7 +8702,7 @@ 37.8799 msgstr "" 37.8800 37.8801 #. type: Content of: <book><chapter><sect1><para> 37.8802 -#: ../en/ch09-undo.xml:639 37.8803 +#: ../en/ch08-undo.xml:639 37.8804 msgid "" 37.8805 "After you've pushed a bad change to another repository, you <emphasis>could</" 37.8806 "emphasis> still use <command role=\"hg-cmd\">hg rollback</command> to make " 37.8807 @@ -9629,7 +8712,7 @@ 37.8808 msgstr "" 37.8809 37.8810 #. type: Content of: <book><chapter><sect1><para> 37.8811 -#: ../en/ch09-undo.xml:647 37.8812 +#: ../en/ch08-undo.xml:647 37.8813 msgid "" 37.8814 "If a situation like this arises, and you know which repositories your bad " 37.8815 "change has propagated into, you can <emphasis>try</emphasis> to get rid of " 37.8816 @@ -9640,7 +8723,7 @@ 37.8817 msgstr "" 37.8818 37.8819 #. type: Content of: <book><chapter><sect1><para> 37.8820 -#: ../en/ch09-undo.xml:655 37.8821 +#: ../en/ch08-undo.xml:655 37.8822 msgid "" 37.8823 "If you've committed one or more changes <emphasis>after</emphasis> the change " 37.8824 "that you'd like to see disappear, your options are further reduced. Mercurial " 37.8825 @@ -9649,7 +8732,7 @@ 37.8826 msgstr "" 37.8827 37.8828 #. type: Content of: <book><chapter><sect1><para> 37.8829 -#: ../en/ch09-undo.xml:661 37.8830 +#: ../en/ch08-undo.xml:661 37.8831 msgid "" 37.8832 "XXX This needs filling out. The <literal>hg-replay</literal> script in the " 37.8833 "<literal>examples</literal> directory works, but doesn't handle merge " 37.8834 @@ -9657,12 +8740,12 @@ 37.8835 msgstr "" 37.8836 37.8837 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8838 -#: ../en/ch09-undo.xml:667 37.8839 +#: ../en/ch08-undo.xml:667 37.8840 msgid "Protect yourself from <quote>escaped</quote> changes" 37.8841 msgstr "使用<quote>校验</quote>修改来保护你自己" 37.8842 37.8843 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8844 -#: ../en/ch09-undo.xml:670 37.8845 +#: ../en/ch08-undo.xml:670 37.8846 msgid "" 37.8847 "If you've committed some changes to your local repository and they've been " 37.8848 "pushed or pulled somewhere else, this isn't necessarily a disaster. You can " 37.8849 @@ -9672,7 +8755,7 @@ 37.8850 msgstr "" 37.8851 37.8852 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8853 -#: ../en/ch09-undo.xml:677 37.8854 +#: ../en/ch08-undo.xml:677 37.8855 msgid "" 37.8856 "By configuring some hooks on that repository to validate incoming changesets " 37.8857 "(see chapter <xref linkend=\"chap.hook\"/>), you can automatically prevent " 37.8858 @@ -9684,7 +8767,7 @@ 37.8859 msgstr "" 37.8860 37.8861 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8862 -#: ../en/ch09-undo.xml:687 37.8863 +#: ../en/ch08-undo.xml:687 37.8864 msgid "" 37.8865 "For instance, an incoming change hook that verifies that a changeset will " 37.8866 "actually compile can prevent people from inadvertantly <quote>breaking the " 37.8867 @@ -9692,12 +8775,12 @@ 37.8868 msgstr "" 37.8869 37.8870 #. type: Content of: <book><chapter><sect1><title> 37.8871 -#: ../en/ch09-undo.xml:694 37.8872 +#: ../en/ch08-undo.xml:694 37.8873 msgid "Finding the source of a bug" 37.8874 msgstr "查找问题的根源" 37.8875 37.8876 #. type: Content of: <book><chapter><sect1><para> 37.8877 -#: ../en/ch09-undo.xml:696 37.8878 +#: ../en/ch08-undo.xml:696 37.8879 msgid "" 37.8880 "While it's all very well to be able to back out a changeset that introduced a " 37.8881 "bug, this requires that you know which changeset to back out. Mercurial " 37.8882 @@ -9707,7 +8790,7 @@ 37.8883 msgstr "" 37.8884 37.8885 #. type: Content of: <book><chapter><sect1><para> 37.8886 -#: ../en/ch09-undo.xml:703 37.8887 +#: ../en/ch08-undo.xml:703 37.8888 msgid "" 37.8889 "The idea behind the <command role=\"hg-cmd\">hg bisect</command> command is " 37.8890 "that a changeset has introduced some change of behaviour that you can " 37.8891 @@ -9719,14 +8802,14 @@ 37.8892 msgstr "" 37.8893 37.8894 #. type: Content of: <book><chapter><sect1><para> 37.8895 -#: ../en/ch09-undo.xml:712 37.8896 +#: ../en/ch08-undo.xml:712 37.8897 msgid "" 37.8898 "Here are a few scenarios to help you understand how you might apply this " 37.8899 "command." 37.8900 msgstr "" 37.8901 37.8902 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8903 -#: ../en/ch09-undo.xml:715 37.8904 +#: ../en/ch08-undo.xml:715 37.8905 msgid "" 37.8906 "The most recent version of your software has a bug that you remember wasn't " 37.8907 "present a few weeks ago, but you don't know when it was introduced. Here, " 37.8908 @@ -9734,7 +8817,7 @@ 37.8909 msgstr "" 37.8910 37.8911 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8912 -#: ../en/ch09-undo.xml:720 37.8913 +#: ../en/ch08-undo.xml:720 37.8914 msgid "" 37.8915 "You fixed a bug in a rush, and now it's time to close the entry in your " 37.8916 "team's bug database. The bug database requires a changeset ID when you close " 37.8917 @@ -9743,7 +8826,7 @@ 37.8918 msgstr "" 37.8919 37.8920 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8921 -#: ../en/ch09-undo.xml:727 37.8922 +#: ../en/ch08-undo.xml:727 37.8923 msgid "" 37.8924 "Your software works correctly, but runs 15% slower than the last time you " 37.8925 "measured it. You want to know which changeset introduced the performance " 37.8926 @@ -9752,14 +8835,14 @@ 37.8927 msgstr "" 37.8928 37.8929 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.8930 -#: ../en/ch09-undo.xml:734 37.8931 +#: ../en/ch08-undo.xml:734 37.8932 msgid "" 37.8933 "The sizes of the components of your project that you ship exploded recently, " 37.8934 "and you suspect that something changed in the way you build your project." 37.8935 msgstr "" 37.8936 37.8937 #. type: Content of: <book><chapter><sect1><para> 37.8938 -#: ../en/ch09-undo.xml:739 37.8939 +#: ../en/ch08-undo.xml:739 37.8940 msgid "" 37.8941 "From these examples, it should be clear that the <command role=\"hg-cmd\">hg " 37.8942 "bisect</command> command is not useful only for finding the sources of bugs. " 37.8943 @@ -9769,7 +8852,7 @@ 37.8944 msgstr "" 37.8945 37.8946 #. type: Content of: <book><chapter><sect1><para> 37.8947 -#: ../en/ch09-undo.xml:746 37.8948 +#: ../en/ch08-undo.xml:746 37.8949 msgid "" 37.8950 "We'll introduce a little bit of terminology here, just to make it clear which " 37.8951 "parts of the search process are your responsibility, and which are " 37.8952 @@ -9783,7 +8866,7 @@ 37.8953 msgstr "" 37.8954 37.8955 #. type: Content of: <book><chapter><sect1><para> 37.8956 -#: ../en/ch09-undo.xml:759 37.8957 +#: ../en/ch08-undo.xml:759 37.8958 msgid "" 37.8959 "One simple way to automate the searching process would be simply to probe " 37.8960 "every changeset. However, this scales poorly. If it took ten minutes to " 37.8961 @@ -9796,7 +8879,7 @@ 37.8962 msgstr "" 37.8963 37.8964 #. type: Content of: <book><chapter><sect1><para> 37.8965 -#: ../en/ch09-undo.xml:769 37.8966 +#: ../en/ch08-undo.xml:769 37.8967 msgid "" 37.8968 "What the <command role=\"hg-cmd\">hg bisect</command> command does is use its " 37.8969 "knowledge of the <quote>shape</quote> of your project's revision history to " 37.8970 @@ -9809,7 +8892,7 @@ 37.8971 msgstr "" 37.8972 37.8973 #. type: Content of: <book><chapter><sect1><para> 37.8974 -#: ../en/ch09-undo.xml:780 37.8975 +#: ../en/ch08-undo.xml:780 37.8976 msgid "" 37.8977 "The <command role=\"hg-cmd\">hg bisect</command> command is aware of the " 37.8978 "<quote>branchy</quote> nature of a Mercurial project's revision history, so " 37.8979 @@ -9819,18 +8902,18 @@ 37.8980 msgstr "" 37.8981 37.8982 #. type: Content of: <book><chapter><sect1><sect2><title> 37.8983 -#: ../en/ch09-undo.xml:788 37.8984 +#: ../en/ch08-undo.xml:788 37.8985 msgid "Using the <command role=\"hg-cmd\">hg bisect</command> command" 37.8986 msgstr "使用命令 <command role=\"hg-cmd\">hg bisect</command>" 37.8987 37.8988 #. type: Content of: <book><chapter><sect1><sect2><para> 37.8989 -#: ../en/ch09-undo.xml:791 37.8990 +#: ../en/ch08-undo.xml:791 37.8991 msgid "" 37.8992 "Here's an example of <command role=\"hg-cmd\">hg bisect</command> in action." 37.8993 msgstr "" 37.8994 37.8995 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.8996 -#: ../en/ch09-undo.xml:795 37.8997 +#: ../en/ch08-undo.xml:795 37.8998 msgid "" 37.8999 "In versions 0.9.5 and earlier of Mercurial, <command role=\"hg-cmd\">hg " 37.9000 "bisect</command> was not a core command: it was distributed with Mercurial as " 37.9001 @@ -9839,14 +8922,14 @@ 37.9002 msgstr "" 37.9003 37.9004 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9005 -#: ../en/ch09-undo.xml:802 37.9006 +#: ../en/ch08-undo.xml:802 37.9007 msgid "" 37.9008 "Now let's create a repository, so that we can try out the <command role=\"hg-" 37.9009 "cmd\">hg bisect</command> command in isolation." 37.9010 msgstr "" 37.9011 37.9012 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9013 -#: ../en/ch09-undo.xml:808 37.9014 +#: ../en/ch08-undo.xml:808 37.9015 msgid "" 37.9016 "We'll simulate a project that has a bug in it in a simple-minded way: create " 37.9017 "trivial changes in a loop, and nominate one specific change that will have " 37.9018 @@ -9856,7 +8939,7 @@ 37.9019 msgstr "" 37.9020 37.9021 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9022 -#: ../en/ch09-undo.xml:818 37.9023 +#: ../en/ch08-undo.xml:818 37.9024 msgid "" 37.9025 "The next thing that we'd like to do is figure out how to use the <command " 37.9026 "role=\"hg-cmd\">hg bisect</command> command. We can use Mercurial's normal " 37.9027 @@ -9864,46 +8947,46 @@ 37.9028 msgstr "" 37.9029 37.9030 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9031 -#: ../en/ch09-undo.xml:825 37.9032 +#: ../en/ch08-undo.xml:825 37.9033 msgid "" 37.9034 "The <command role=\"hg-cmd\">hg bisect</command> command works in steps. " 37.9035 "Each step proceeds as follows." 37.9036 msgstr "" 37.9037 37.9038 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.9039 -#: ../en/ch09-undo.xml:828 37.9040 +#: ../en/ch08-undo.xml:828 37.9041 msgid "You run your binary test." 37.9042 msgstr "" 37.9043 37.9044 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><itemizedlist><listitem><para> 37.9045 -#: ../en/ch09-undo.xml:830 37.9046 +#: ../en/ch08-undo.xml:830 37.9047 msgid "" 37.9048 "If the test succeeded, you tell <command role=\"hg-cmd\">hg bisect</command> " 37.9049 "by running the <command role=\"hg-cmd\">hg bisect good</command> command." 37.9050 msgstr "" 37.9051 37.9052 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><itemizedlist><listitem><para> 37.9053 -#: ../en/ch09-undo.xml:835 37.9054 +#: ../en/ch08-undo.xml:835 37.9055 msgid "" 37.9056 "If it failed, run the <command role=\"hg-cmd\">hg bisect bad</command> " 37.9057 "command." 37.9058 msgstr "" 37.9059 37.9060 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.9061 -#: ../en/ch09-undo.xml:839 37.9062 +#: ../en/ch08-undo.xml:839 37.9063 msgid "" 37.9064 "The command uses your information to decide which changeset to test next." 37.9065 msgstr "" 37.9066 37.9067 #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> 37.9068 -#: ../en/ch09-undo.xml:842 37.9069 +#: ../en/ch08-undo.xml:842 37.9070 msgid "" 37.9071 "It updates the working directory to that changeset, and the process begins " 37.9072 "again." 37.9073 msgstr "" 37.9074 37.9075 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9076 -#: ../en/ch09-undo.xml:845 37.9077 +#: ../en/ch08-undo.xml:845 37.9078 msgid "" 37.9079 "The process ends when <command role=\"hg-cmd\">hg bisect</command> identifies " 37.9080 "a unique changeset that marks the point where your test transitioned from " 37.9081 @@ -9912,14 +8995,14 @@ 37.9082 37.9083 # 37.9084 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9085 -#: ../en/ch09-undo.xml:850 37.9086 +#: ../en/ch08-undo.xml:850 37.9087 msgid "" 37.9088 "To start the search, we must run the <command role=\"hg-cmd\">hg bisect --" 37.9089 "reset</command> command." 37.9090 msgstr "" 37.9091 37.9092 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9093 -#: ../en/ch09-undo.xml:855 37.9094 +#: ../en/ch08-undo.xml:855 37.9095 msgid "" 37.9096 "In our case, the binary test we use is simple: we check to see if any file in " 37.9097 "the repository contains the string <quote>i have a gub</quote>. If it does, " 37.9098 @@ -9929,7 +9012,7 @@ 37.9099 msgstr "" 37.9100 37.9101 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9102 -#: ../en/ch09-undo.xml:863 37.9103 +#: ../en/ch08-undo.xml:863 37.9104 msgid "" 37.9105 "Most of the time, the revision to which the working directory is synced " 37.9106 "(usually the tip) already exhibits the problem introduced by the buggy " 37.9107 @@ -9938,7 +9021,7 @@ 37.9108 37.9109 # 37.9110 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9111 -#: ../en/ch09-undo.xml:870 37.9112 +#: ../en/ch08-undo.xml:870 37.9113 msgid "" 37.9114 "Our next task is to nominate a changeset that we know <emphasis>doesn't</" 37.9115 "emphasis> have the bug; the <command role=\"hg-cmd\">hg bisect</command> " 37.9116 @@ -9949,26 +9032,26 @@ 37.9117 msgstr "" 37.9118 37.9119 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9120 -#: ../en/ch09-undo.xml:880 37.9121 +#: ../en/ch08-undo.xml:880 37.9122 msgid "Notice that this command printed some output." 37.9123 msgstr "" 37.9124 37.9125 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9126 -#: ../en/ch09-undo.xml:882 37.9127 +#: ../en/ch08-undo.xml:882 37.9128 msgid "" 37.9129 "It told us how many changesets it must consider before it can identify the " 37.9130 "one that introduced the bug, and how many tests that will require." 37.9131 msgstr "" 37.9132 37.9133 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9134 -#: ../en/ch09-undo.xml:886 37.9135 +#: ../en/ch08-undo.xml:886 37.9136 msgid "" 37.9137 "It updated the working directory to the next changeset to test, and told us " 37.9138 "which changeset it's testing." 37.9139 msgstr "" 37.9140 37.9141 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9142 -#: ../en/ch09-undo.xml:891 37.9143 +#: ../en/ch08-undo.xml:891 37.9144 msgid "" 37.9145 "We now run our test in the working directory. We use the <command>grep</" 37.9146 "command> command to see if our <quote>bad</quote> file is present in the " 37.9147 @@ -9977,26 +9060,26 @@ 37.9148 msgstr "" 37.9149 37.9150 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9151 -#: ../en/ch09-undo.xml:897 37.9152 +#: ../en/ch08-undo.xml:897 37.9153 msgid "" 37.9154 "This test looks like a perfect candidate for automation, so let's turn it " 37.9155 "into a shell function." 37.9156 msgstr "" 37.9157 37.9158 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9159 -#: ../en/ch09-undo.xml:901 37.9160 +#: ../en/ch08-undo.xml:901 37.9161 msgid "" 37.9162 "We can now run an entire test step with a single command, <literal>mytest</" 37.9163 "literal>." 37.9164 msgstr "" 37.9165 37.9166 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9167 -#: ../en/ch09-undo.xml:906 37.9168 +#: ../en/ch08-undo.xml:906 37.9169 msgid "A few more invocations of our canned test step command, and we're done." 37.9170 msgstr "" 37.9171 37.9172 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9173 -#: ../en/ch09-undo.xml:911 37.9174 +#: ../en/ch08-undo.xml:911 37.9175 msgid "" 37.9176 "Even though we had 40 changesets to search through, the <command role=\"hg-cmd" 37.9177 "\">hg bisect</command> command let us find the changeset that introduced our " 37.9178 @@ -10008,13 +9091,13 @@ 37.9179 msgstr "" 37.9180 37.9181 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9182 -#: ../en/ch09-undo.xml:922 37.9183 +#: ../en/ch08-undo.xml:922 37.9184 msgid "Cleaning up after your search" 37.9185 msgstr "搜索后的清理" 37.9186 37.9187 # 37.9188 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9189 -#: ../en/ch09-undo.xml:924 37.9190 +#: ../en/ch08-undo.xml:924 37.9191 msgid "" 37.9192 "When you're finished using the <command role=\"hg-cmd\">hg bisect</command> " 37.9193 "command in a repository, you can use the <command role=\"hg-cmd\">hg bisect " 37.9194 @@ -10026,17 +9109,17 @@ 37.9195 msgstr "" 37.9196 37.9197 #. type: Content of: <book><chapter><sect1><title> 37.9198 -#: ../en/ch09-undo.xml:939 37.9199 +#: ../en/ch08-undo.xml:939 37.9200 msgid "Tips for finding bugs effectively" 37.9201 msgstr "有效查找问题的技巧" 37.9202 37.9203 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9204 -#: ../en/ch09-undo.xml:942 37.9205 +#: ../en/ch08-undo.xml:942 37.9206 msgid "Give consistent input" 37.9207 msgstr "给出一致的输入" 37.9208 37.9209 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9210 -#: ../en/ch09-undo.xml:944 37.9211 +#: ../en/ch08-undo.xml:944 37.9212 msgid "" 37.9213 "The <command role=\"hg-cmd\">hg bisect</command> command requires that you " 37.9214 "correctly report the result of every test you perform. If you tell it that a " 37.9215 @@ -10048,12 +9131,12 @@ 37.9216 msgstr "" 37.9217 37.9218 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9219 -#: ../en/ch09-undo.xml:956 37.9220 +#: ../en/ch08-undo.xml:956 37.9221 msgid "Automate as much as possible" 37.9222 msgstr "尽量自动" 37.9223 37.9224 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9225 -#: ../en/ch09-undo.xml:958 37.9226 +#: ../en/ch08-undo.xml:958 37.9227 msgid "" 37.9228 "When I started using the <command role=\"hg-cmd\">hg bisect</command> " 37.9229 "command, I tried a few times to run my tests by hand, on the command line. " 37.9230 @@ -10063,7 +9146,7 @@ 37.9231 msgstr "" 37.9232 37.9233 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9234 -#: ../en/ch09-undo.xml:966 37.9235 +#: ../en/ch08-undo.xml:966 37.9236 msgid "" 37.9237 "My initial problems with driving the <command role=\"hg-cmd\">hg bisect</" 37.9238 "command> command by hand occurred even with simple searches on small " 37.9239 @@ -10074,24 +9157,24 @@ 37.9240 msgstr "" 37.9241 37.9242 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9243 -#: ../en/ch09-undo.xml:975 37.9244 +#: ../en/ch08-undo.xml:975 37.9245 msgid "The key to automated testing is twofold:" 37.9246 msgstr "" 37.9247 37.9248 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9249 -#: ../en/ch09-undo.xml:977 37.9250 +#: ../en/ch08-undo.xml:977 37.9251 msgid "always test for the same symptom, and" 37.9252 msgstr "" 37.9253 37.9254 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9255 -#: ../en/ch09-undo.xml:979 37.9256 +#: ../en/ch08-undo.xml:979 37.9257 msgid "" 37.9258 "always feed consistent input to the <command role=\"hg-cmd\">hg bisect</" 37.9259 "command> command." 37.9260 msgstr "" 37.9261 37.9262 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9263 -#: ../en/ch09-undo.xml:982 37.9264 +#: ../en/ch08-undo.xml:982 37.9265 msgid "" 37.9266 "In my tutorial example above, the <command>grep</command> command tests for " 37.9267 "the symptom, and the <literal>if</literal> statement takes the result of this " 37.9268 @@ -10102,12 +9185,12 @@ 37.9269 msgstr "" 37.9270 37.9271 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9272 -#: ../en/ch09-undo.xml:992 37.9273 +#: ../en/ch08-undo.xml:992 37.9274 msgid "Check your results" 37.9275 msgstr "检查你的结果" 37.9276 37.9277 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9278 -#: ../en/ch09-undo.xml:994 37.9279 +#: ../en/ch08-undo.xml:994 37.9280 msgid "" 37.9281 "Because the output of a <command role=\"hg-cmd\">hg bisect</command> search " 37.9282 "is only as good as the input you give it, don't take the changeset it reports " 37.9283 @@ -10116,32 +9199,32 @@ 37.9284 msgstr "" 37.9285 37.9286 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9287 -#: ../en/ch09-undo.xml:1000 37.9288 +#: ../en/ch08-undo.xml:1000 37.9289 msgid "" 37.9290 "The changeset that it reports as the first bad revision. Your test should " 37.9291 "still report this as bad." 37.9292 msgstr "" 37.9293 37.9294 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9295 -#: ../en/ch09-undo.xml:1004 37.9296 +#: ../en/ch08-undo.xml:1004 37.9297 msgid "" 37.9298 "The parent of that changeset (either parent, if it's a merge). Your test " 37.9299 "should report this changeset as good." 37.9300 msgstr "" 37.9301 37.9302 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.9303 -#: ../en/ch09-undo.xml:1008 37.9304 +#: ../en/ch08-undo.xml:1008 37.9305 msgid "" 37.9306 "A child of that changeset. Your test should report this changeset as bad." 37.9307 msgstr "" 37.9308 37.9309 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9310 -#: ../en/ch09-undo.xml:1014 37.9311 +#: ../en/ch08-undo.xml:1014 37.9312 msgid "Beware interference between bugs" 37.9313 msgstr "谨防问题之间的冲突" 37.9314 37.9315 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9316 -#: ../en/ch09-undo.xml:1016 37.9317 +#: ../en/ch08-undo.xml:1016 37.9318 msgid "" 37.9319 "It's possible that your search for one bug could be disrupted by the presence " 37.9320 "of another. For example, let's say your software crashes at revision 100, " 37.9321 @@ -10151,7 +9234,7 @@ 37.9322 msgstr "" 37.9323 37.9324 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9325 -#: ../en/ch09-undo.xml:1024 37.9326 +#: ../en/ch08-undo.xml:1024 37.9327 msgid "" 37.9328 "It is possible that this other bug completely <quote>masks</quote> yours, " 37.9329 "which is to say that it occurs before your bug has a chance to manifest " 37.9330 @@ -10163,7 +9246,7 @@ 37.9331 msgstr "" 37.9332 37.9333 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9334 -#: ../en/ch09-undo.xml:1034 37.9335 +#: ../en/ch08-undo.xml:1034 37.9336 msgid "" 37.9337 "A different problem could arise if your test for a bug's presence is not " 37.9338 "specific enough. If you check for <quote>my program crashes</quote>, then " 37.9339 @@ -10172,7 +9255,7 @@ 37.9340 msgstr "" 37.9341 37.9342 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9343 -#: ../en/ch09-undo.xml:1041 37.9344 +#: ../en/ch08-undo.xml:1041 37.9345 msgid "" 37.9346 "Another useful situation in which to use <command role=\"hg-cmd\">hg bisect --" 37.9347 "skip</command> is if you can't test a revision because your project was in a " 37.9348 @@ -10181,12 +9264,12 @@ 37.9349 msgstr "" 37.9350 37.9351 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9352 -#: ../en/ch09-undo.xml:1050 37.9353 +#: ../en/ch08-undo.xml:1050 37.9354 msgid "Bracket your search lazily" 37.9355 msgstr "减少你的查找工作" 37.9356 37.9357 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9358 -#: ../en/ch09-undo.xml:1052 37.9359 +#: ../en/ch08-undo.xml:1052 37.9360 msgid "" 37.9361 "Choosing the first <quote>good</quote> and <quote>bad</quote> changesets that " 37.9362 "will mark the end points of your search is often easy, but it bears a little " 37.9363 @@ -10196,7 +9279,7 @@ 37.9364 msgstr "" 37.9365 37.9366 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9367 -#: ../en/ch09-undo.xml:1060 37.9368 +#: ../en/ch08-undo.xml:1060 37.9369 msgid "" 37.9370 "If you're having trouble remembering when a suitable <quote>good</quote> " 37.9371 "change was, so that you can tell <command role=\"hg-cmd\">hg bisect</" 37.9372 @@ -10207,7 +9290,7 @@ 37.9373 msgstr "" 37.9374 37.9375 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9376 -#: ../en/ch09-undo.xml:1069 37.9377 +#: ../en/ch08-undo.xml:1069 37.9378 msgid "" 37.9379 "Even if you end up <quote>early</quote> by thousands of changesets or months " 37.9380 "of history, you will only add a handful of tests to the total number that " 37.9381 @@ -10216,12 +9299,12 @@ 37.9382 msgstr "" 37.9383 37.9384 #. type: Content of: <book><chapter><title> 37.9385 -#: ../en/ch10-hook.xml:5 37.9386 +#: ../en/ch09-hook.xml:5 37.9387 msgid "Handling repository events with hooks" 37.9388 msgstr "使用钩子处理版本库事件" 37.9389 37.9390 #. type: Content of: <book><chapter><para> 37.9391 -#: ../en/ch10-hook.xml:7 37.9392 +#: ../en/ch09-hook.xml:7 37.9393 msgid "" 37.9394 "Mercurial offers a powerful mechanism to let you perform automated actions in " 37.9395 "response to events that occur in a repository. In some cases, you can even " 37.9396 @@ -10229,7 +9312,7 @@ 37.9397 msgstr "" 37.9398 37.9399 #. type: Content of: <book><chapter><para> 37.9400 -#: ../en/ch10-hook.xml:12 37.9401 +#: ../en/ch09-hook.xml:12 37.9402 msgid "" 37.9403 "The name Mercurial uses for one of these actions is a <emphasis>hook</" 37.9404 "emphasis>. Hooks are called <quote>triggers</quote> in some revision control " 37.9405 @@ -10237,12 +9320,12 @@ 37.9406 msgstr "" 37.9407 37.9408 #. type: Content of: <book><chapter><sect1><title> 37.9409 -#: ../en/ch10-hook.xml:18 37.9410 +#: ../en/ch09-hook.xml:18 37.9411 msgid "An overview of hooks in Mercurial" 37.9412 msgstr "Mercurial 钩子概述" 37.9413 37.9414 #. type: Content of: <book><chapter><sect1><para> 37.9415 -#: ../en/ch10-hook.xml:20 37.9416 +#: ../en/ch09-hook.xml:20 37.9417 msgid "" 37.9418 "Here is a brief list of the hooks that Mercurial supports. We will revisit " 37.9419 "each of these hooks in more detail later, in section <xref linkend=\"sec.hook." 37.9420 @@ -10250,21 +9333,21 @@ 37.9421 msgstr "" 37.9422 37.9423 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9424 -#: ../en/ch10-hook.xml:25 37.9425 +#: ../en/ch09-hook.xml:25 37.9426 msgid "" 37.9427 "<literal role=\"hook\">changegroup</literal>: This is run after a group of " 37.9428 "changesets has been brought into the repository from elsewhere." 37.9429 msgstr "" 37.9430 37.9431 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9432 -#: ../en/ch10-hook.xml:29 37.9433 +#: ../en/ch09-hook.xml:29 37.9434 msgid "" 37.9435 "<literal role=\"hook\">commit</literal>: This is run after a new changeset " 37.9436 "has been created in the local repository." 37.9437 msgstr "" 37.9438 37.9439 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9440 -#: ../en/ch10-hook.xml:33 37.9441 +#: ../en/ch09-hook.xml:33 37.9442 msgid "" 37.9443 "<literal role=\"hook\">incoming</literal>: This is run once for each new " 37.9444 "changeset that is brought into the repository from elsewhere. Notice the " 37.9445 @@ -10273,42 +9356,42 @@ 37.9446 msgstr "" 37.9447 37.9448 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9449 -#: ../en/ch10-hook.xml:40 37.9450 +#: ../en/ch09-hook.xml:40 37.9451 msgid "" 37.9452 "<literal role=\"hook\">outgoing</literal>: This is run after a group of " 37.9453 "changesets has been transmitted from this repository." 37.9454 msgstr "" 37.9455 37.9456 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9457 -#: ../en/ch10-hook.xml:44 37.9458 +#: ../en/ch09-hook.xml:44 37.9459 msgid "" 37.9460 "<literal role=\"hook\">prechangegroup</literal>: This is run before starting " 37.9461 "to bring a group of changesets into the repository." 37.9462 msgstr "" 37.9463 37.9464 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9465 -#: ../en/ch10-hook.xml:49 37.9466 +#: ../en/ch09-hook.xml:49 37.9467 msgid "" 37.9468 "<literal role=\"hook\">precommit</literal>: Controlling. This is run before " 37.9469 "starting a commit." 37.9470 msgstr "" 37.9471 37.9472 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9473 -#: ../en/ch10-hook.xml:53 37.9474 +#: ../en/ch09-hook.xml:53 37.9475 msgid "" 37.9476 "<literal role=\"hook\">preoutgoing</literal>: Controlling. This is run before " 37.9477 "starting to transmit a group of changesets from this repository." 37.9478 msgstr "" 37.9479 37.9480 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9481 -#: ../en/ch10-hook.xml:58 37.9482 +#: ../en/ch09-hook.xml:58 37.9483 msgid "" 37.9484 "<literal role=\"hook\">pretag</literal>: Controlling. This is run before " 37.9485 "creating a tag." 37.9486 msgstr "" 37.9487 37.9488 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9489 -#: ../en/ch10-hook.xml:62 37.9490 +#: ../en/ch09-hook.xml:62 37.9491 msgid "" 37.9492 "<literal role=\"hook\">pretxnchangegroup</literal>: Controlling. This is run " 37.9493 "after a group of changesets has been brought into the local repository from " 37.9494 @@ -10317,7 +9400,7 @@ 37.9495 msgstr "" 37.9496 37.9497 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9498 -#: ../en/ch10-hook.xml:70 37.9499 +#: ../en/ch09-hook.xml:70 37.9500 msgid "" 37.9501 "<literal role=\"hook\">pretxncommit</literal>: Controlling. This is run after " 37.9502 "a new changeset has been created in the local repository, but before the " 37.9503 @@ -10325,27 +9408,27 @@ 37.9504 msgstr "" 37.9505 37.9506 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9507 -#: ../en/ch10-hook.xml:76 37.9508 +#: ../en/ch09-hook.xml:76 37.9509 msgid "" 37.9510 "<literal role=\"hook\">preupdate</literal>: Controlling. This is run before " 37.9511 "starting an update or merge of the working directory." 37.9512 msgstr "" 37.9513 37.9514 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9515 -#: ../en/ch10-hook.xml:81 37.9516 +#: ../en/ch09-hook.xml:81 37.9517 msgid "" 37.9518 "<literal role=\"hook\">tag</literal>: This is run after a tag is created." 37.9519 msgstr "" 37.9520 37.9521 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.9522 -#: ../en/ch10-hook.xml:85 37.9523 +#: ../en/ch09-hook.xml:85 37.9524 msgid "" 37.9525 "<literal role=\"hook\">update</literal>: This is run after an update or merge " 37.9526 "of the working directory has finished." 37.9527 msgstr "" 37.9528 37.9529 #. type: Content of: <book><chapter><sect1><para> 37.9530 -#: ../en/ch10-hook.xml:90 37.9531 +#: ../en/ch09-hook.xml:90 37.9532 msgid "" 37.9533 "Each of the hooks whose description begins with the word <quote>Controlling</" 37.9534 "quote> has the ability to determine whether an activity can proceed. If the " 37.9535 @@ -10354,17 +9437,17 @@ 37.9536 msgstr "" 37.9537 37.9538 #. type: Content of: <book><chapter><sect1><title> 37.9539 -#: ../en/ch10-hook.xml:99 37.9540 +#: ../en/ch09-hook.xml:99 37.9541 msgid "Hooks and security" 37.9542 msgstr "钩子与安全性" 37.9543 37.9544 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9545 -#: ../en/ch10-hook.xml:102 37.9546 +#: ../en/ch09-hook.xml:102 37.9547 msgid "Hooks are run with your privileges" 37.9548 msgstr "钩子以你的特权执行" 37.9549 37.9550 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9551 -#: ../en/ch10-hook.xml:104 37.9552 +#: ../en/ch09-hook.xml:104 37.9553 msgid "" 37.9554 "When you run a Mercurial command in a repository, and the command causes a " 37.9555 "hook to run, that hook runs on <emphasis>your</emphasis> system, under " 37.9556 @@ -10375,16 +9458,16 @@ 37.9557 msgstr "" 37.9558 37.9559 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9560 -#: ../en/ch10-hook.xml:115 37.9561 +#: ../en/ch09-hook.xml:115 37.9562 msgid "" 37.9563 "In some cases, you may be exposed to hooks that you did not install " 37.9564 "yourself. If you work with Mercurial on an unfamiliar system, Mercurial will " 37.9565 -"run hooks defined in that system's global <filename role=\"special\"> /.hgrc</" 37.9566 -"filename>\\ file." 37.9567 -msgstr "" 37.9568 - 37.9569 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.9570 -#: ../en/ch10-hook.xml:122 37.9571 +"run hooks defined in that system's global <filename role=\"special\">~/.hgrc</" 37.9572 +"filename> file." 37.9573 +msgstr "" 37.9574 + 37.9575 +#. type: Content of: <book><chapter><sect1><sect2><para> 37.9576 +#: ../en/ch09-hook.xml:122 37.9577 msgid "" 37.9578 "If you are working with a repository owned by another user, Mercurial can run " 37.9579 "hooks defined in that user's repository, but it will still run them as " 37.9580 @@ -10396,7 +9479,7 @@ 37.9581 msgstr "" 37.9582 37.9583 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.9584 -#: ../en/ch10-hook.xml:134 37.9585 +#: ../en/ch09-hook.xml:134 37.9586 msgid "" 37.9587 "This only applies if you are pulling from a repository on a local or network " 37.9588 "filesystem. If you're pulling over http or ssh, any <literal role=\"hook" 37.9589 @@ -10405,7 +9488,7 @@ 37.9590 msgstr "" 37.9591 37.9592 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9593 -#: ../en/ch10-hook.xml:142 37.9594 +#: ../en/ch09-hook.xml:142 37.9595 msgid "" 37.9596 "XXX To see what hooks are defined in a repository, use the <command role=\"hg-" 37.9597 "cmd\">hg config hooks</command> command. If you are working in one " 37.9598 @@ -10416,12 +9499,12 @@ 37.9599 msgstr "" 37.9600 37.9601 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9602 -#: ../en/ch10-hook.xml:153 37.9603 +#: ../en/ch09-hook.xml:153 37.9604 msgid "Hooks do not propagate" 37.9605 msgstr "钩子不会传播" 37.9606 37.9607 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9608 -#: ../en/ch10-hook.xml:155 37.9609 +#: ../en/ch09-hook.xml:155 37.9610 msgid "" 37.9611 "In Mercurial, hooks are not revision controlled, and do not propagate when " 37.9612 "you clone, or pull from, a repository. The reason for this is simple: a hook " 37.9613 @@ -10430,7 +9513,7 @@ 37.9614 msgstr "" 37.9615 37.9616 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9617 -#: ../en/ch10-hook.xml:162 37.9618 +#: ../en/ch09-hook.xml:162 37.9619 msgid "" 37.9620 "It would be extremely reckless for any distributed revision control system to " 37.9621 "implement revision-controlled hooks, as this would offer an easily " 37.9622 @@ -10439,7 +9522,7 @@ 37.9623 msgstr "" 37.9624 37.9625 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9626 -#: ../en/ch10-hook.xml:168 37.9627 +#: ../en/ch09-hook.xml:168 37.9628 msgid "" 37.9629 "Since Mercurial does not propagate hooks, if you are collaborating with other " 37.9630 "people on a common project, you should not assume that they are using the " 37.9631 @@ -10448,22 +9531,22 @@ 37.9632 msgstr "" 37.9633 37.9634 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9635 -#: ../en/ch10-hook.xml:175 37.9636 +#: ../en/ch09-hook.xml:175 37.9637 msgid "" 37.9638 "In a corporate intranet, this is somewhat easier to control, as you can for " 37.9639 "example provide a <quote>standard</quote> installation of Mercurial on an NFS " 37.9640 -"filesystem, and use a site-wide <filename role=\"special\"> /.hgrc</filename>" 37.9641 -"\\ file to define hooks that all users will see. However, this too has its " 37.9642 +"filesystem, and use a site-wide <filename role=\"special\">~/.hgrc</filename> " 37.9643 +"file to define hooks that all users will see. However, this too has its " 37.9644 "limits; see below." 37.9645 msgstr "" 37.9646 37.9647 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9648 -#: ../en/ch10-hook.xml:185 37.9649 +#: ../en/ch09-hook.xml:184 37.9650 msgid "Hooks can be overridden" 37.9651 msgstr "钩子可以被覆盖" 37.9652 37.9653 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9654 -#: ../en/ch10-hook.xml:187 37.9655 +#: ../en/ch09-hook.xml:186 37.9656 msgid "" 37.9657 "Mercurial allows you to override a hook definition by redefining the hook. " 37.9658 "You can disable it by setting its value to the empty string, or change its " 37.9659 @@ -10471,31 +9554,31 @@ 37.9660 msgstr "" 37.9661 37.9662 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9663 -#: ../en/ch10-hook.xml:192 37.9664 -msgid "" 37.9665 -"If you deploy a system- or site-wide <filename role=\"special\"> /.hgrc</" 37.9666 -"filename>\\ file that defines some hooks, you should thus understand that " 37.9667 -"your users can disable or override those hooks." 37.9668 -msgstr "" 37.9669 - 37.9670 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.9671 -#: ../en/ch10-hook.xml:200 37.9672 +#: ../en/ch09-hook.xml:191 37.9673 +msgid "" 37.9674 +"If you deploy a system- or site-wide <filename role=\"special\">~/.hgrc</" 37.9675 +"filename> file that defines some hooks, you should thus understand that your " 37.9676 +"users can disable or override those hooks." 37.9677 +msgstr "" 37.9678 + 37.9679 +#. type: Content of: <book><chapter><sect1><sect2><title> 37.9680 +#: ../en/ch09-hook.xml:199 37.9681 msgid "Ensuring that critical hooks are run" 37.9682 msgstr "确保关键钩子的执行" 37.9683 37.9684 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9685 -#: ../en/ch10-hook.xml:202 37.9686 +#: ../en/ch09-hook.xml:201 37.9687 msgid "" 37.9688 "Sometimes you may want to enforce a policy that you do not want others to be " 37.9689 "able to work around. For example, you may have a requirement that every " 37.9690 "changeset must pass a rigorous set of tests. Defining this requirement via a " 37.9691 -"hook in a site-wide <filename role=\"special\"> /.hgrc</filename>\\ won't " 37.9692 -"work for remote users on laptops, and of course local users can subvert it at " 37.9693 -"will by overriding the hook." 37.9694 -msgstr "" 37.9695 - 37.9696 -#. type: Content of: <book><chapter><sect1><sect2><para> 37.9697 -#: ../en/ch10-hook.xml:211 37.9698 +"hook in a site-wide <filename role=\"special\">~/.hgrc</filename> won't work " 37.9699 +"for remote users on laptops, and of course local users can subvert it at will " 37.9700 +"by overriding the hook." 37.9701 +msgstr "" 37.9702 + 37.9703 +#. type: Content of: <book><chapter><sect1><sect2><para> 37.9704 +#: ../en/ch09-hook.xml:210 37.9705 msgid "" 37.9706 "Instead, you can set up your policies for use of Mercurial so that people are " 37.9707 "expected to propagate changes through a well-known <quote>canonical</quote> " 37.9708 @@ -10503,7 +9586,7 @@ 37.9709 msgstr "" 37.9710 37.9711 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9712 -#: ../en/ch10-hook.xml:217 37.9713 +#: ../en/ch09-hook.xml:216 37.9714 msgid "" 37.9715 "One way to do this is via a combination of social engineering and " 37.9716 "technology. Set up a restricted-access account; users can push changes over " 37.9717 @@ -10513,7 +9596,7 @@ 37.9718 msgstr "" 37.9719 37.9720 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9721 -#: ../en/ch10-hook.xml:226 37.9722 +#: ../en/ch09-hook.xml:225 37.9723 msgid "" 37.9724 "When someone pushes a changeset to the server that everyone pulls from, the " 37.9725 "server will test the changeset before it accepts it as permanent, and reject " 37.9726 @@ -10523,12 +9606,12 @@ 37.9727 msgstr "" 37.9728 37.9729 #. type: Content of: <book><chapter><sect1><title> 37.9730 -#: ../en/ch10-hook.xml:237 37.9731 +#: ../en/ch09-hook.xml:236 37.9732 msgid "Care with <literal>pretxn</literal> hooks in a shared-access repository" 37.9733 msgstr "在共享版本库中注意 <literal>pretxn</literal> 钩子" 37.9734 37.9735 #. type: Content of: <book><chapter><sect1><para> 37.9736 -#: ../en/ch10-hook.xml:240 37.9737 +#: ../en/ch09-hook.xml:239 37.9738 msgid "" 37.9739 "If you want to use hooks to do some automated work in a repository that a " 37.9740 "number of people have shared access to, you need to be careful in how you do " 37.9741 @@ -10536,7 +9619,7 @@ 37.9742 msgstr "" 37.9743 37.9744 #. type: Content of: <book><chapter><sect1><para> 37.9745 -#: ../en/ch10-hook.xml:245 37.9746 +#: ../en/ch09-hook.xml:244 37.9747 msgid "" 37.9748 "Mercurial only locks a repository when it is writing to the repository, and " 37.9749 "only the parts of Mercurial that write to the repository pay attention to " 37.9750 @@ -10545,7 +9628,7 @@ 37.9751 msgstr "" 37.9752 37.9753 #. type: Content of: <book><chapter><sect1><para> 37.9754 -#: ../en/ch10-hook.xml:252 37.9755 +#: ../en/ch09-hook.xml:251 37.9756 msgid "" 37.9757 "Because Mercurial is careful with the order in which it reads and writes " 37.9758 "data, it does not need to acquire a lock when it wants to read data from the " 37.9759 @@ -10555,7 +9638,7 @@ 37.9760 msgstr "" 37.9761 37.9762 #. type: Content of: <book><chapter><sect1><para> 37.9763 -#: ../en/ch10-hook.xml:260 37.9764 +#: ../en/ch09-hook.xml:259 37.9765 msgid "" 37.9766 "With great performance comes a trade-off, though, one which has the potential " 37.9767 "to cause you trouble unless you're aware of it. To describe this requires a " 37.9768 @@ -10564,7 +9647,7 @@ 37.9769 msgstr "" 37.9770 37.9771 #. type: Content of: <book><chapter><sect1><para> 37.9772 -#: ../en/ch10-hook.xml:267 37.9773 +#: ../en/ch09-hook.xml:266 37.9774 msgid "" 37.9775 "When Mercurial <emphasis>writes</emphasis> metadata, it writes it straight " 37.9776 "into the destination file. It writes file data first, then manifest data " 37.9777 @@ -10576,7 +9659,7 @@ 37.9778 msgstr "" 37.9779 37.9780 #. type: Content of: <book><chapter><sect1><para> 37.9781 -#: ../en/ch10-hook.xml:278 37.9782 +#: ../en/ch09-hook.xml:277 37.9783 msgid "" 37.9784 "When Mercurial <emphasis>reads</emphasis> metadata, it reads the changelog " 37.9785 "first, then everything else. Since a reader will only access parts of the " 37.9786 @@ -10585,7 +9668,7 @@ 37.9787 msgstr "" 37.9788 37.9789 #. type: Content of: <book><chapter><sect1><para> 37.9790 -#: ../en/ch10-hook.xml:284 37.9791 +#: ../en/ch09-hook.xml:283 37.9792 msgid "" 37.9793 "Some controlling hooks (<literal role=\"hook\">pretxncommit</literal> and " 37.9794 "<literal role=\"hook\">pretxnchangegroup</literal>) run when a transaction is " 37.9795 @@ -10594,7 +9677,7 @@ 37.9796 msgstr "" 37.9797 37.9798 #. type: Content of: <book><chapter><sect1><para> 37.9799 -#: ../en/ch10-hook.xml:292 37.9800 +#: ../en/ch09-hook.xml:291 37.9801 msgid "" 37.9802 "If one of these hooks runs for long, it opens a window of time during which a " 37.9803 "reader can see the metadata for changesets that are not yet permanent, and " 37.9804 @@ -10603,12 +9686,12 @@ 37.9805 msgstr "" 37.9806 37.9807 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9808 -#: ../en/ch10-hook.xml:300 37.9809 +#: ../en/ch09-hook.xml:299 37.9810 msgid "The problem illustrated" 37.9811 msgstr "问题的演示" 37.9812 37.9813 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9814 -#: ../en/ch10-hook.xml:302 37.9815 +#: ../en/ch09-hook.xml:301 37.9816 msgid "" 37.9817 "In principle, a good use for the <literal role=\"hook\">pretxnchangegroup</" 37.9818 "literal> hook would be to automatically build and test incoming changes " 37.9819 @@ -10620,7 +9703,7 @@ 37.9820 msgstr "" 37.9821 37.9822 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9823 -#: ../en/ch10-hook.xml:313 37.9824 +#: ../en/ch09-hook.xml:312 37.9825 msgid "" 37.9826 "The safest technological answer to this challenge is to set up such a " 37.9827 "<quote>gatekeeper</quote> repository as <emphasis>unidirectional</emphasis>. " 37.9828 @@ -10633,7 +9716,7 @@ 37.9829 msgstr "" 37.9830 37.9831 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9832 -#: ../en/ch10-hook.xml:325 37.9833 +#: ../en/ch09-hook.xml:324 37.9834 msgid "" 37.9835 "In practice, putting a centralised bottleneck like this in place is not often " 37.9836 "a good idea, and transaction visibility has nothing to do with the problem. " 37.9837 @@ -10645,7 +9728,7 @@ 37.9838 msgstr "" 37.9839 37.9840 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9841 -#: ../en/ch10-hook.xml:336 37.9842 +#: ../en/ch09-hook.xml:335 37.9843 msgid "" 37.9844 "An approach that scales better is to get people to build and test before they " 37.9845 "push, then run automated builds and tests centrally <emphasis>after</" 37.9846 @@ -10655,12 +9738,12 @@ 37.9847 msgstr "" 37.9848 37.9849 #. type: Content of: <book><chapter><sect1><title> 37.9850 -#: ../en/ch10-hook.xml:347 37.9851 +#: ../en/ch09-hook.xml:346 37.9852 msgid "A short tutorial on using hooks" 37.9853 msgstr "使用钩子的简短指南" 37.9854 37.9855 #. type: Content of: <book><chapter><sect1><para> 37.9856 -#: ../en/ch10-hook.xml:349 37.9857 +#: ../en/ch09-hook.xml:348 37.9858 msgid "" 37.9859 "It is easy to write a Mercurial hook. Let's start with a hook that runs when " 37.9860 "you finish a <command role=\"hg-cmd\">hg commit</command>, and simply prints " 37.9861 @@ -10669,15 +9752,15 @@ 37.9862 msgstr "" 37.9863 37.9864 #. type: Content of: <book><chapter><sect1><para> 37.9865 -#: ../en/ch10-hook.xml:356 37.9866 +#: ../en/ch09-hook.xml:355 37.9867 msgid "All hooks follow the pattern in this example." 37.9868 msgstr "" 37.9869 37.9870 #. type: Content of: <book><chapter><sect1><para> 37.9871 -#: ../en/ch10-hook.xml:360 37.9872 +#: ../en/ch09-hook.xml:359 37.9873 msgid "" 37.9874 "You add an entry to the <literal role=\"rc-hooks\">hooks</literal> section of " 37.9875 -"your <filename role=\"special\"> /.hgrc</filename>. On the left is the name " 37.9876 +"your <filename role=\"special\">~/.hgrc</filename>. On the left is the name " 37.9877 "of the event to trigger on; on the right is the action to take. As you can " 37.9878 "see, you can run an arbitrary shell command in a hook. Mercurial passes " 37.9879 "extra information to the hook using environment variables (look for " 37.9880 @@ -10685,19 +9768,19 @@ 37.9881 msgstr "" 37.9882 37.9883 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9884 -#: ../en/ch10-hook.xml:370 37.9885 +#: ../en/ch09-hook.xml:369 37.9886 msgid "Performing multiple actions per event" 37.9887 msgstr "每个事件执行多个操作" 37.9888 37.9889 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9890 -#: ../en/ch10-hook.xml:372 37.9891 +#: ../en/ch09-hook.xml:371 37.9892 msgid "" 37.9893 "Quite often, you will want to define more than one hook for a particular kind " 37.9894 "of event, as shown below." 37.9895 msgstr "" 37.9896 37.9897 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9898 -#: ../en/ch10-hook.xml:377 37.9899 +#: ../en/ch09-hook.xml:376 37.9900 msgid "" 37.9901 "Mercurial lets you do this by adding an <emphasis>extension</emphasis> to the " 37.9902 "end of a hook's name. You extend a hook's name by giving the name of the " 37.9903 @@ -10708,7 +9791,7 @@ 37.9904 msgstr "" 37.9905 37.9906 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9907 -#: ../en/ch10-hook.xml:388 37.9908 +#: ../en/ch09-hook.xml:387 37.9909 msgid "" 37.9910 "To give a well-defined order of execution when there are multiple hooks " 37.9911 "defined for an event, Mercurial sorts hooks by extension, and executes the " 37.9912 @@ -10718,7 +9801,7 @@ 37.9913 msgstr "" 37.9914 37.9915 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9916 -#: ../en/ch10-hook.xml:397 37.9917 +#: ../en/ch09-hook.xml:396 37.9918 msgid "" 37.9919 "It is a good idea to use a somewhat descriptive extension when you define a " 37.9920 "new hook. This will help you to remember what the hook was for. If the hook " 37.9921 @@ -10729,12 +9812,12 @@ 37.9922 msgstr "" 37.9923 37.9924 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9925 -#: ../en/ch10-hook.xml:408 37.9926 +#: ../en/ch09-hook.xml:407 37.9927 msgid "Controlling whether an activity can proceed" 37.9928 msgstr "控制处理的活动" 37.9929 37.9930 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9931 -#: ../en/ch10-hook.xml:410 37.9932 +#: ../en/ch09-hook.xml:409 37.9933 msgid "" 37.9934 "In our earlier examples, we used the <literal role=\"hook\">commit</literal> " 37.9935 "hook, which is run after a commit has completed. This is one of several " 37.9936 @@ -10743,7 +9826,7 @@ 37.9937 msgstr "" 37.9938 37.9939 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9940 -#: ../en/ch10-hook.xml:417 37.9941 +#: ../en/ch09-hook.xml:416 37.9942 msgid "" 37.9943 "Mercurial defines a number of events that occur before an activity starts; or " 37.9944 "after it starts, but before it finishes. Hooks that trigger on these events " 37.9945 @@ -10752,7 +9835,7 @@ 37.9946 msgstr "" 37.9947 37.9948 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9949 -#: ../en/ch10-hook.xml:423 37.9950 +#: ../en/ch09-hook.xml:422 37.9951 msgid "" 37.9952 "The <literal role=\"hook\">pretxncommit</literal> hook runs after a commit " 37.9953 "has all but completed. In other words, the metadata representing the " 37.9954 @@ -10763,7 +9846,7 @@ 37.9955 msgstr "" 37.9956 37.9957 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9958 -#: ../en/ch10-hook.xml:432 37.9959 +#: ../en/ch09-hook.xml:431 37.9960 msgid "" 37.9961 "If the <literal role=\"hook\">pretxncommit</literal> hook exits with a status " 37.9962 "code of zero, the transaction is allowed to complete; the commit finishes; " 37.9963 @@ -10774,19 +9857,19 @@ 37.9964 msgstr "" 37.9965 37.9966 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9967 -#: ../en/ch10-hook.xml:444 37.9968 +#: ../en/ch09-hook.xml:443 37.9969 msgid "" 37.9970 "The hook in the example above checks that a commit comment contains a bug " 37.9971 "ID. If it does, the commit can complete. If not, the commit is rolled back." 37.9972 msgstr "" 37.9973 37.9974 #. type: Content of: <book><chapter><sect1><title> 37.9975 -#: ../en/ch10-hook.xml:452 37.9976 +#: ../en/ch09-hook.xml:451 37.9977 msgid "Writing your own hooks" 37.9978 msgstr "编写钩子" 37.9979 37.9980 #. type: Content of: <book><chapter><sect1><para> 37.9981 -#: ../en/ch10-hook.xml:454 37.9982 +#: ../en/ch09-hook.xml:453 37.9983 msgid "" 37.9984 "When you are writing a hook, you might find it useful to run Mercurial either " 37.9985 "with the <option role=\"hg-opt-global\">-v</option> option, or the <envar " 37.9986 @@ -10795,12 +9878,12 @@ 37.9987 msgstr "" 37.9988 37.9989 #. type: Content of: <book><chapter><sect1><sect2><title> 37.9990 -#: ../en/ch10-hook.xml:463 37.9991 +#: ../en/ch09-hook.xml:462 37.9992 msgid "Choosing how your hook should run" 37.9993 msgstr "选择钩子的执行方式" 37.9994 37.9995 #. type: Content of: <book><chapter><sect1><sect2><para> 37.9996 -#: ../en/ch10-hook.xml:465 37.9997 +#: ../en/ch09-hook.xml:464 37.9998 msgid "" 37.9999 "You can write a hook either as a normal program&emdash;typically a shell " 37.10000 "script&emdash;or as a Python function that is executed within the Mercurial " 37.10001 @@ -10808,7 +9891,7 @@ 37.10002 msgstr "" 37.10003 37.10004 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10005 -#: ../en/ch10-hook.xml:470 37.10006 +#: ../en/ch09-hook.xml:469 37.10007 msgid "" 37.10008 "Writing a hook as an external program has the advantage that it requires no " 37.10009 "knowledge of Mercurial's internals. You can call normal Mercurial commands " 37.10010 @@ -10817,7 +9900,7 @@ 37.10011 msgstr "" 37.10012 37.10013 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10014 -#: ../en/ch10-hook.xml:477 37.10015 +#: ../en/ch09-hook.xml:476 37.10016 msgid "" 37.10017 "An in-process Python hook has complete access to the Mercurial API, and does " 37.10018 "not <quote>shell out</quote> to another process, so it is inherently faster " 37.10019 @@ -10827,7 +9910,7 @@ 37.10020 msgstr "" 37.10021 37.10022 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10023 -#: ../en/ch10-hook.xml:485 37.10024 +#: ../en/ch09-hook.xml:484 37.10025 msgid "" 37.10026 "If you are comfortable with Python, or require high performance, writing your " 37.10027 "hooks in Python may be a good choice. However, when you have a " 37.10028 @@ -10836,12 +9919,12 @@ 37.10029 msgstr "" 37.10030 37.10031 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10032 -#: ../en/ch10-hook.xml:494 37.10033 +#: ../en/ch09-hook.xml:493 37.10034 msgid "Hook parameters" 37.10035 msgstr "钩子的参数" 37.10036 37.10037 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10038 -#: ../en/ch10-hook.xml:496 37.10039 +#: ../en/ch09-hook.xml:495 37.10040 msgid "" 37.10041 "Mercurial calls each hook with a set of well-defined parameters. In Python, " 37.10042 "a parameter is passed as a keyword argument to your hook function. For an " 37.10043 @@ -10849,7 +9932,7 @@ 37.10044 msgstr "" 37.10045 37.10046 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10047 -#: ../en/ch10-hook.xml:502 37.10048 +#: ../en/ch09-hook.xml:501 37.10049 msgid "" 37.10050 "Whether your hook is written in Python or as a shell script, the hook-" 37.10051 "specific parameter names and values will be the same. A boolean parameter " 37.10052 @@ -10862,12 +9945,12 @@ 37.10053 msgstr "" 37.10054 37.10055 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10056 -#: ../en/ch10-hook.xml:516 37.10057 +#: ../en/ch09-hook.xml:515 37.10058 msgid "Hook return values and activity control" 37.10059 msgstr "钩子的返回值与活动控制" 37.10060 37.10061 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10062 -#: ../en/ch10-hook.xml:518 37.10063 +#: ../en/ch09-hook.xml:517 37.10064 msgid "" 37.10065 "A hook that executes successfully must exit with a status of zero if " 37.10066 "external, or return boolean <quote>false</quote> if in-process. Failure is " 37.10067 @@ -10877,35 +9960,35 @@ 37.10068 msgstr "" 37.10069 37.10070 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10071 -#: ../en/ch10-hook.xml:526 37.10072 +#: ../en/ch09-hook.xml:525 37.10073 msgid "" 37.10074 "For a hook that controls whether an activity can proceed, zero/false means " 37.10075 "<quote>allow</quote>, while non-zero/true/exception means <quote>deny</quote>." 37.10076 msgstr "" 37.10077 37.10078 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10079 -#: ../en/ch10-hook.xml:533 37.10080 +#: ../en/ch09-hook.xml:532 37.10081 msgid "Writing an external hook" 37.10082 msgstr "编写外部钩子" 37.10083 37.10084 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10085 -#: ../en/ch10-hook.xml:535 37.10086 -msgid "" 37.10087 -"When you define an external hook in your <filename role=\"special\"> /.hgrc</" 37.10088 -"filename>\\ and the hook is run, its value is passed to your shell, which " 37.10089 +#: ../en/ch09-hook.xml:534 37.10090 +msgid "" 37.10091 +"When you define an external hook in your <filename role=\"special\">~/.hgrc</" 37.10092 +"filename> and the hook is run, its value is passed to your shell, which " 37.10093 "interprets it. This means that you can use normal shell constructs in the " 37.10094 "body of the hook." 37.10095 msgstr "" 37.10096 37.10097 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10098 -#: ../en/ch10-hook.xml:542 37.10099 +#: ../en/ch09-hook.xml:541 37.10100 msgid "" 37.10101 "An executable hook is always run with its current directory set to a " 37.10102 "repository's root directory." 37.10103 msgstr "" 37.10104 37.10105 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10106 -#: ../en/ch10-hook.xml:546 37.10107 +#: ../en/ch09-hook.xml:545 37.10108 msgid "" 37.10109 "Each hook parameter is passed in as an environment variable; the name is " 37.10110 "upper-cased, and prefixed with the string <quote><literal>HG_</literal></" 37.10111 @@ -10913,7 +9996,7 @@ 37.10112 msgstr "" 37.10113 37.10114 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10115 -#: ../en/ch10-hook.xml:551 37.10116 +#: ../en/ch09-hook.xml:550 37.10117 msgid "" 37.10118 "With the exception of hook parameters, Mercurial does not set or modify any " 37.10119 "environment variables when running a hook. This is useful to remember if you " 37.10120 @@ -10924,14 +10007,14 @@ 37.10121 msgstr "" 37.10122 37.10123 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10124 -#: ../en/ch10-hook.xml:562 37.10125 +#: ../en/ch09-hook.xml:561 37.10126 msgid "Telling Mercurial to use an in-process hook" 37.10127 msgstr "让 Mercurial 使用进程内钩子" 37.10128 37.10129 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10130 -#: ../en/ch10-hook.xml:564 37.10131 -msgid "" 37.10132 -"The <filename role=\"special\"> /.hgrc</filename>\\ syntax for defining an in-" 37.10133 +#: ../en/ch09-hook.xml:563 37.10134 +msgid "" 37.10135 +"The <filename role=\"special\">~/.hgrc</filename> syntax for defining an in-" 37.10136 "process hook is slightly different than for an executable hook. The value of " 37.10137 "the hook must start with the text <quote><literal>python:</literal></quote>, " 37.10138 "and continue with the fully-qualified name of a callable object to use as the " 37.10139 @@ -10939,7 +10022,7 @@ 37.10140 msgstr "" 37.10141 37.10142 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10143 -#: ../en/ch10-hook.xml:572 37.10144 +#: ../en/ch09-hook.xml:571 37.10145 msgid "" 37.10146 "The module in which a hook lives is automatically imported when a hook is " 37.10147 "run. So long as you have the module name and <envar>PYTHONPATH</envar> " 37.10148 @@ -10947,14 +10030,14 @@ 37.10149 msgstr "" 37.10150 37.10151 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10152 -#: ../en/ch10-hook.xml:578 37.10153 -msgid "" 37.10154 -"The following <filename role=\"special\"> /.hgrc</filename>\\ example snippet " 37.10155 +#: ../en/ch09-hook.xml:577 37.10156 +msgid "" 37.10157 +"The following <filename role=\"special\">~/.hgrc</filename> example snippet " 37.10158 "illustrates the syntax and meaning of the notions we just described." 37.10159 msgstr "" 37.10160 37.10161 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10162 -#: ../en/ch10-hook.xml:584 37.10163 +#: ../en/ch09-hook.xml:583 37.10164 msgid "" 37.10165 "When Mercurial runs the <literal>commit.example</literal> hook, it imports " 37.10166 "<literal>mymodule.submodule</literal>, looks for the callable object named " 37.10167 @@ -10962,19 +10045,19 @@ 37.10168 msgstr "" 37.10169 37.10170 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10171 -#: ../en/ch10-hook.xml:592 37.10172 +#: ../en/ch09-hook.xml:591 37.10173 msgid "Writing an in-process hook" 37.10174 msgstr "编写进程内钩子" 37.10175 37.10176 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10177 -#: ../en/ch10-hook.xml:594 37.10178 +#: ../en/ch09-hook.xml:593 37.10179 msgid "" 37.10180 "The simplest in-process hook does nothing, but illustrates the basic shape of " 37.10181 "the hook API:" 37.10182 msgstr "" 37.10183 37.10184 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10185 -#: ../en/ch10-hook.xml:599 37.10186 +#: ../en/ch09-hook.xml:598 37.10187 msgid "" 37.10188 "The first argument to a Python hook is always a <literal role=\"py-mod-" 37.10189 "mercurial.ui\">ui</literal> object. The second is a repository object; at " 37.10190 @@ -10986,17 +10069,17 @@ 37.10191 msgstr "" 37.10192 37.10193 #. type: Content of: <book><chapter><sect1><title> 37.10194 -#: ../en/ch10-hook.xml:614 37.10195 +#: ../en/ch09-hook.xml:613 37.10196 msgid "Some hook examples" 37.10197 msgstr "钩子样例" 37.10198 37.10199 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10200 -#: ../en/ch10-hook.xml:617 37.10201 +#: ../en/ch09-hook.xml:616 37.10202 msgid "Writing meaningful commit messages" 37.10203 msgstr "编写有意义的提交日志" 37.10204 37.10205 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10206 -#: ../en/ch10-hook.xml:619 37.10207 +#: ../en/ch09-hook.xml:618 37.10208 msgid "" 37.10209 "It's hard to imagine a useful commit message being very short. The simple " 37.10210 "<literal role=\"hook\">pretxncommit</literal> hook of the example below will " 37.10211 @@ -11005,12 +10088,12 @@ 37.10212 msgstr "" 37.10213 37.10214 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10215 -#: ../en/ch10-hook.xml:629 37.10216 +#: ../en/ch09-hook.xml:628 37.10217 msgid "Checking for trailing whitespace" 37.10218 msgstr "检查行尾空格" 37.10219 37.10220 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10221 -#: ../en/ch10-hook.xml:631 37.10222 +#: ../en/ch09-hook.xml:630 37.10223 msgid "" 37.10224 "An interesting use of a commit-related hook is to help you to write cleaner " 37.10225 "code. A simple example of <quote>cleaner code</quote> is the dictum that a " 37.10226 @@ -11022,7 +10105,7 @@ 37.10227 msgstr "" 37.10228 37.10229 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10230 -#: ../en/ch10-hook.xml:642 37.10231 +#: ../en/ch09-hook.xml:641 37.10232 msgid "" 37.10233 "You can use either the <literal role=\"hook\">precommit</literal> or <literal " 37.10234 "role=\"hook\">pretxncommit</literal> hook to tell whether you have a trailing " 37.10235 @@ -11037,7 +10120,7 @@ 37.10236 msgstr "" 37.10237 37.10238 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10239 -#: ../en/ch10-hook.xml:658 37.10240 +#: ../en/ch09-hook.xml:657 37.10241 msgid "" 37.10242 "Should you choose the <literal role=\"hook\">pretxncommit</literal> hook, the " 37.10243 "check won't occur until just before the transaction for the commit " 37.10244 @@ -11049,7 +10132,7 @@ 37.10245 msgstr "" 37.10246 37.10247 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10248 -#: ../en/ch10-hook.xml:671 37.10249 +#: ../en/ch09-hook.xml:670 37.10250 msgid "" 37.10251 "In this example, we introduce a simple <literal role=\"hook\">pretxncommit</" 37.10252 "literal> hook that checks for trailing whitespace. This hook is short, but " 37.10253 @@ -11061,7 +10144,7 @@ 37.10254 msgstr "" 37.10255 37.10256 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10257 -#: ../en/ch10-hook.xml:682 37.10258 +#: ../en/ch09-hook.xml:681 37.10259 msgid "" 37.10260 "The above version is much more complex, but also more useful. It parses a " 37.10261 "unified diff to see if any lines add trailing whitespace, and prints the name " 37.10262 @@ -11074,7 +10157,7 @@ 37.10263 msgstr "" 37.10264 37.10265 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10266 -#: ../en/ch10-hook.xml:696 37.10267 +#: ../en/ch09-hook.xml:695 37.10268 msgid "" 37.10269 "As a final aside, note in the example above the use of <command>perl</" 37.10270 "command>'s in-place editing feature to get rid of trailing whitespace from a " 37.10271 @@ -11082,12 +10165,12 @@ 37.10272 msgstr "" 37.10273 37.10274 #. type: Content of: <book><chapter><sect1><title> 37.10275 -#: ../en/ch10-hook.xml:706 37.10276 +#: ../en/ch09-hook.xml:705 37.10277 msgid "Bundled hooks" 37.10278 msgstr "内置的钩子" 37.10279 37.10280 #. type: Content of: <book><chapter><sect1><para> 37.10281 -#: ../en/ch10-hook.xml:708 37.10282 +#: ../en/ch09-hook.xml:707 37.10283 msgid "" 37.10284 "Mercurial ships with several bundled hooks. You can find them in the " 37.10285 "<filename class=\"directory\">hgext</filename> directory of a Mercurial " 37.10286 @@ -11097,14 +10180,14 @@ 37.10287 msgstr "" 37.10288 37.10289 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10290 -#: ../en/ch10-hook.xml:717 37.10291 +#: ../en/ch09-hook.xml:716 37.10292 msgid "" 37.10293 "<literal role=\"hg-ext\">acl</literal>&emdash;access control for parts of a " 37.10294 "repository" 37.10295 msgstr "<literal role=\"hg-ext\">acl</literal>&emdash;版本库的访问控制" 37.10296 37.10297 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10298 -#: ../en/ch10-hook.xml:720 37.10299 +#: ../en/ch09-hook.xml:719 37.10300 msgid "" 37.10301 "The <literal role=\"hg-ext\">acl</literal> extension lets you control which " 37.10302 "remote users are allowed to push changesets to a networked server. You can " 37.10303 @@ -11114,7 +10197,7 @@ 37.10304 msgstr "" 37.10305 37.10306 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10307 -#: ../en/ch10-hook.xml:728 37.10308 +#: ../en/ch09-hook.xml:727 37.10309 msgid "" 37.10310 "This extension implements access control based on the identity of the user " 37.10311 "performing a push, <emphasis>not</emphasis> on who committed the changesets " 37.10312 @@ -11124,12 +10207,12 @@ 37.10313 msgstr "" 37.10314 37.10315 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10316 -#: ../en/ch10-hook.xml:738 37.10317 +#: ../en/ch09-hook.xml:737 37.10318 msgid "Configuring the <literal role=\"hook\">acl</literal> hook" 37.10319 msgstr "配置 <literal role=\"hook\">acl</literal> 钩子" 37.10320 37.10321 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10322 -#: ../en/ch10-hook.xml:741 37.10323 +#: ../en/ch09-hook.xml:740 37.10324 msgid "" 37.10325 "In order to manage incoming changesets, the <literal role=\"hg-ext\">acl</" 37.10326 "literal> hook must be used as a <literal role=\"hook\">pretxnchangegroup</" 37.10327 @@ -11139,14 +10222,14 @@ 37.10328 msgstr "" 37.10329 37.10330 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10331 -#: ../en/ch10-hook.xml:751 37.10332 +#: ../en/ch09-hook.xml:750 37.10333 msgid "" 37.10334 "The <literal role=\"hg-ext\">acl</literal> extension is configured using " 37.10335 "three sections." 37.10336 msgstr "" 37.10337 37.10338 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10339 -#: ../en/ch10-hook.xml:755 37.10340 +#: ../en/ch09-hook.xml:754 37.10341 msgid "" 37.10342 "The <literal role=\"rc-acl\">acl</literal> section has only one entry, <envar " 37.10343 "role=\"rc-item-acl\">sources</envar>, which lists the sources of incoming " 37.10344 @@ -11155,7 +10238,7 @@ 37.10345 msgstr "" 37.10346 37.10347 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10348 -#: ../en/ch10-hook.xml:762 37.10349 +#: ../en/ch09-hook.xml:761 37.10350 msgid "" 37.10351 "<envar role=\"rc-item-acl\">serve</envar>: Control incoming changesets that " 37.10352 "are arriving from a remote repository over http or ssh. This is the default " 37.10353 @@ -11164,28 +10247,28 @@ 37.10354 msgstr "" 37.10355 37.10356 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10357 -#: ../en/ch10-hook.xml:770 37.10358 +#: ../en/ch09-hook.xml:769 37.10359 msgid "" 37.10360 "<envar role=\"rc-item-acl\">pull</envar>: Control incoming changesets that " 37.10361 "are arriving via a pull from a local repository." 37.10362 msgstr "" 37.10363 37.10364 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10365 -#: ../en/ch10-hook.xml:775 37.10366 +#: ../en/ch09-hook.xml:774 37.10367 msgid "" 37.10368 "<envar role=\"rc-item-acl\">push</envar>: Control incoming changesets that " 37.10369 "are arriving via a push from a local repository." 37.10370 msgstr "" 37.10371 37.10372 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10373 -#: ../en/ch10-hook.xml:780 37.10374 +#: ../en/ch09-hook.xml:779 37.10375 msgid "" 37.10376 "<envar role=\"rc-item-acl\">bundle</envar>: Control incoming changesets that " 37.10377 "are arriving from another repository via a bundle." 37.10378 msgstr "" 37.10379 37.10380 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10381 -#: ../en/ch10-hook.xml:786 37.10382 +#: ../en/ch09-hook.xml:785 37.10383 msgid "" 37.10384 "The <literal role=\"rc-acl.allow\">acl.allow</literal> section controls the " 37.10385 "users that are allowed to add changesets to the repository. If this section " 37.10386 @@ -11195,7 +10278,7 @@ 37.10387 msgstr "" 37.10388 37.10389 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10390 -#: ../en/ch10-hook.xml:795 37.10391 +#: ../en/ch09-hook.xml:794 37.10392 msgid "" 37.10393 "The <literal role=\"rc-acl.deny\">acl.deny</literal> section determines which " 37.10394 "users are denied from adding changesets to the repository. If this section " 37.10395 @@ -11203,7 +10286,7 @@ 37.10396 msgstr "" 37.10397 37.10398 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10399 -#: ../en/ch10-hook.xml:801 37.10400 +#: ../en/ch09-hook.xml:800 37.10401 msgid "" 37.10402 "The syntaxes for the <literal role=\"rc-acl.allow\">acl.allow</literal> and " 37.10403 "<literal role=\"rc-acl.deny\">acl.deny</literal> sections are identical. On " 37.10404 @@ -11212,7 +10295,7 @@ 37.10405 msgstr "" 37.10406 37.10407 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10408 -#: ../en/ch10-hook.xml:809 37.10409 +#: ../en/ch09-hook.xml:808 37.10410 msgid "" 37.10411 "In the following example, the user <literal>docwriter</literal> can only push " 37.10412 "changes to the <filename class=\"directory\">docs</filename> subtree of the " 37.10413 @@ -11221,23 +10304,23 @@ 37.10414 msgstr "" 37.10415 37.10416 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10417 -#: ../en/ch10-hook.xml:821 ../en/ch10-hook.xml:1095 ../en/ch10-hook.xml:1308 37.10418 +#: ../en/ch09-hook.xml:822 ../en/ch09-hook.xml:1089 ../en/ch09-hook.xml:1280 37.10419 msgid "Testing and troubleshooting" 37.10420 msgstr "测试与问题处理" 37.10421 37.10422 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10423 -#: ../en/ch10-hook.xml:823 37.10424 +#: ../en/ch09-hook.xml:824 37.10425 msgid "" 37.10426 "If you want to test the <literal role=\"hg-ext\">acl</literal> hook, run it " 37.10427 "with Mercurial's debugging output enabled. Since you'll probably be running " 37.10428 "it on a server where it's not convenient (or sometimes possible) to pass in " 37.10429 "the <option role=\"hg-opt-global\">--debug</option> option, don't forget that " 37.10430 -"you can enable debugging output in your <filename role=\"special\"> /.hgrc</" 37.10431 +"you can enable debugging output in your <filename role=\"special\">~/.hgrc</" 37.10432 "filename>:" 37.10433 msgstr "" 37.10434 37.10435 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10436 -#: ../en/ch10-hook.xml:833 37.10437 +#: ../en/ch09-hook.xml:835 37.10438 msgid "" 37.10439 "With this enabled, the <literal role=\"hg-ext\">acl</literal> hook will print " 37.10440 "enough information to let you figure out why it is allowing or forbidding " 37.10441 @@ -11245,13 +10328,13 @@ 37.10442 msgstr "" 37.10443 37.10444 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10445 -#: ../en/ch10-hook.xml:842 37.10446 +#: ../en/ch09-hook.xml:844 37.10447 msgid "" 37.10448 "<literal role=\"hg-ext\">bugzilla</literal>&emdash;integration with Bugzilla" 37.10449 msgstr "<literal role=\"hg-ext\">bugzilla</literal>&emdash;与 Bugzilla 的集成" 37.10450 37.10451 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10452 -#: ../en/ch10-hook.xml:846 37.10453 +#: ../en/ch09-hook.xml:848 37.10454 msgid "" 37.10455 "The <literal role=\"hg-ext\">bugzilla</literal> extension adds a comment to a " 37.10456 "Bugzilla bug whenever it finds a reference to that bug ID in a commit " 37.10457 @@ -11260,14 +10343,14 @@ 37.10458 msgstr "" 37.10459 37.10460 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10461 -#: ../en/ch10-hook.xml:853 37.10462 +#: ../en/ch09-hook.xml:855 37.10463 msgid "" 37.10464 "It adds a comment to the bug that looks like this (you can configure the " 37.10465 "contents of the comment&emdash;see below):" 37.10466 msgstr "" 37.10467 37.10468 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10469 -#: ../en/ch10-hook.xml:862 37.10470 +#: ../en/ch09-hook.xml:864 37.10471 msgid "" 37.10472 "The value of this hook is that it automates the process of updating a bug any " 37.10473 "time a changeset refers to it. If you configure the hook properly, it makes " 37.10474 @@ -11276,14 +10359,14 @@ 37.10475 msgstr "" 37.10476 37.10477 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10478 -#: ../en/ch10-hook.xml:869 37.10479 +#: ../en/ch09-hook.xml:871 37.10480 msgid "" 37.10481 "You can use the code in this hook as a starting point for some more exotic " 37.10482 "Bugzilla integration recipes. Here are a few possibilities:" 37.10483 msgstr "" 37.10484 37.10485 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.10486 -#: ../en/ch10-hook.xml:874 37.10487 +#: ../en/ch09-hook.xml:876 37.10488 msgid "" 37.10489 "Require that every changeset pushed to the server have a valid bug ID in its " 37.10490 "commit comment. In this case, you'd want to configure the hook as a <literal " 37.10491 @@ -11292,7 +10375,7 @@ 37.10492 msgstr "" 37.10493 37.10494 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.10495 -#: ../en/ch10-hook.xml:882 37.10496 +#: ../en/ch09-hook.xml:884 37.10497 msgid "" 37.10498 "Allow incoming changesets to automatically modify the <emphasis>state</" 37.10499 "emphasis> of a bug, as well as simply adding a comment. For example, the " 37.10500 @@ -11302,20 +10385,23 @@ 37.10501 msgstr "" 37.10502 37.10503 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10504 -#: ../en/ch10-hook.xml:892 37.10505 +#: ../en/ch09-hook.xml:894 37.10506 msgid "Configuring the <literal role=\"hook\">bugzilla</literal> hook" 37.10507 msgstr "配置 <literal role=\"hook\">bugzilla</literal> 钩子" 37.10508 37.10509 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10510 -#: ../en/ch10-hook.xml:895 37.10511 -msgid "" 37.10512 -"You should configure this hook in your server's <filename role=\"special\"> /." 37.10513 -"hgrc</filename>\\ as an <literal role=\"hook\">incoming</literal> hook, for " 37.10514 +#: ../en/ch09-hook.xml:897 37.10515 +#, fuzzy 37.10516 +msgid "" 37.10517 +"You should configure this hook in your server's <filename role=\"special\">~/." 37.10518 +"hgrc</filename> as an <literal role=\"hook\">incoming</literal> hook, for " 37.10519 "example as follows:" 37.10520 msgstr "" 37.10521 +"选择正确的 <filename role=\"special\"> /.hgrc</filename> 文件增加到 <literal " 37.10522 +"role=\"rc-web\">web</literal> 条目" 37.10523 37.10524 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10525 -#: ../en/ch10-hook.xml:903 37.10526 +#: ../en/ch09-hook.xml:905 37.10527 msgid "" 37.10528 "Because of the specialised nature of this hook, and because Bugzilla was not " 37.10529 "written with this kind of integration in mind, configuring this hook is a " 37.10530 @@ -11323,7 +10409,7 @@ 37.10531 msgstr "" 37.10532 37.10533 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10534 -#: ../en/ch10-hook.xml:909 37.10535 +#: ../en/ch09-hook.xml:911 37.10536 msgid "" 37.10537 "Before you begin, you must install the MySQL bindings for Python on the host" 37.10538 "(s) where you'll be running the hook. If this is not available as a binary " 37.10539 @@ -11332,15 +10418,15 @@ 37.10540 msgstr "" 37.10541 37.10542 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10543 -#: ../en/ch10-hook.xml:916 37.10544 +#: ../en/ch09-hook.xml:918 37.10545 msgid "" 37.10546 "Configuration information for this hook lives in the <literal role=\"rc-" 37.10547 -"bugzilla\">bugzilla</literal> section of your <filename role=\"special\"> /." 37.10548 +"bugzilla\">bugzilla</literal> section of your <filename role=\"special\">~/." 37.10549 "hgrc</filename>." 37.10550 msgstr "" 37.10551 37.10552 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10553 -#: ../en/ch10-hook.xml:921 37.10554 +#: ../en/ch09-hook.xml:923 37.10555 msgid "" 37.10556 "<envar role=\"rc-item-bugzilla\">version</envar>: The version of Bugzilla " 37.10557 "installed on the server. The database schema that Bugzilla uses changes " 37.10558 @@ -11349,7 +10435,7 @@ 37.10559 msgstr "" 37.10560 37.10561 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10562 -#: ../en/ch10-hook.xml:930 37.10563 +#: ../en/ch09-hook.xml:932 37.10564 msgid "" 37.10565 "<envar role=\"rc-item-bugzilla\">host</envar>: The hostname of the MySQL " 37.10566 "server that stores your Bugzilla data. The database must be configured to " 37.10567 @@ -11358,7 +10444,7 @@ 37.10568 msgstr "" 37.10569 37.10570 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10571 -#: ../en/ch10-hook.xml:937 37.10572 +#: ../en/ch09-hook.xml:939 37.10573 msgid "" 37.10574 "<envar role=\"rc-item-bugzilla\">user</envar>: The username with which to " 37.10575 "connect to the MySQL server. The database must be configured to allow this " 37.10576 @@ -11369,16 +10455,16 @@ 37.10577 msgstr "" 37.10578 37.10579 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10580 -#: ../en/ch10-hook.xml:948 37.10581 +#: ../en/ch09-hook.xml:950 37.10582 msgid "" 37.10583 "<envar role=\"rc-item-bugzilla\">password</envar>: The MySQL password for the " 37.10584 "user you configured above. This is stored as plain text, so you should make " 37.10585 -"sure that unauthorised users cannot read the <filename role=\"special\"> /." 37.10586 -"hgrc</filename>\\ file where you store this information." 37.10587 +"sure that unauthorised users cannot read the <filename role=\"special\">~/." 37.10588 +"hgrc</filename> file where you store this information." 37.10589 msgstr "" 37.10590 37.10591 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10592 -#: ../en/ch10-hook.xml:957 37.10593 +#: ../en/ch09-hook.xml:959 37.10594 msgid "" 37.10595 "<envar role=\"rc-item-bugzilla\">db</envar>: The name of the Bugzilla " 37.10596 "database on the MySQL server. The default value of this item is " 37.10597 @@ -11387,7 +10473,7 @@ 37.10598 msgstr "" 37.10599 37.10600 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10601 -#: ../en/ch10-hook.xml:964 37.10602 +#: ../en/ch09-hook.xml:966 37.10603 msgid "" 37.10604 "<envar role=\"rc-item-bugzilla\">notify</envar>: If you want Bugzilla to send " 37.10605 "out a notification email to subscribers after this hook has added a comment " 37.10606 @@ -11398,7 +10484,7 @@ 37.10607 msgstr "" 37.10608 37.10609 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10610 -#: ../en/ch10-hook.xml:977 37.10611 +#: ../en/ch09-hook.xml:979 37.10612 msgid "" 37.10613 "The Bugzilla <literal>processmail</literal> program expects to be given a bug " 37.10614 "ID (the hook replaces <quote><literal>%s</literal></quote> with the bug ID) " 37.10615 @@ -11409,12 +10495,12 @@ 37.10616 msgstr "" 37.10617 37.10618 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10619 -#: ../en/ch10-hook.xml:992 37.10620 +#: ../en/ch09-hook.xml:994 37.10621 msgid "Mapping committer names to Bugzilla user names" 37.10622 msgstr "提交者的名称与 Bugzilla 用户名称的映射" 37.10623 37.10624 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10625 -#: ../en/ch10-hook.xml:994 37.10626 +#: ../en/ch09-hook.xml:996 37.10627 msgid "" 37.10628 "By default, the <literal role=\"hg-ext\">bugzilla</literal> hook tries to use " 37.10629 "the email address of a changeset's committer as the Bugzilla user name with " 37.10630 @@ -11424,14 +10510,14 @@ 37.10631 msgstr "" 37.10632 37.10633 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10634 -#: ../en/ch10-hook.xml:1003 37.10635 +#: ../en/ch09-hook.xml:1005 37.10636 msgid "" 37.10637 "Each item in the <literal role=\"rc-usermap\">usermap</literal> section " 37.10638 "contains an email address on the left, and a Bugzilla user name on the right." 37.10639 msgstr "" 37.10640 37.10641 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10642 -#: ../en/ch10-hook.xml:1010 37.10643 +#: ../en/ch09-hook.xml:1012 37.10644 msgid "" 37.10645 "You can either keep the <literal role=\"rc-usermap\">usermap</literal> data " 37.10646 "in a normal <filename role=\"special\">~/.hgrc</filename>, or tell the " 37.10647 @@ -11440,32 +10526,32 @@ 37.10648 "store <filename>usermap</filename> data by itself in (for example) a user-" 37.10649 "modifiable repository. This makes it possible to let your users maintain " 37.10650 "their own <envar role=\"rc-item-bugzilla\">usermap</envar> entries. The main " 37.10651 -"<filename role=\"special\"> /.hgrc</filename>\\ file might look like this:" 37.10652 +"<filename role=\"special\">~/.hgrc</filename> file might look like this:" 37.10653 msgstr "" 37.10654 37.10655 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10656 -#: ../en/ch10-hook.xml:1026 37.10657 +#: ../en/ch09-hook.xml:1028 37.10658 msgid "" 37.10659 "While the <filename>usermap</filename> file that it refers to might look like " 37.10660 "this:" 37.10661 msgstr "" 37.10662 37.10663 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10664 -#: ../en/ch10-hook.xml:1035 37.10665 +#: ../en/ch09-hook.xml:1036 37.10666 msgid "Configuring the text that gets added to a bug" 37.10667 msgstr "配置增加到问题中的正文" 37.10668 37.10669 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10670 -#: ../en/ch10-hook.xml:1037 37.10671 +#: ../en/ch09-hook.xml:1038 37.10672 msgid "" 37.10673 "You can configure the text that this hook adds as a comment; you specify it " 37.10674 -"in the form of a Mercurial template. Several <filename role=\"special\"> /." 37.10675 -"hgrc</filename>\\ entries (still in the <literal role=\"rc-bugzilla" 37.10676 -"\">bugzilla</literal> section) control this behaviour." 37.10677 +"in the form of a Mercurial template. Several <filename role=\"special\">~/." 37.10678 +"hgrc</filename> entries (still in the <literal role=\"rc-bugzilla\">bugzilla</" 37.10679 +"literal> section) control this behaviour." 37.10680 msgstr "" 37.10681 37.10682 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10683 -#: ../en/ch10-hook.xml:1044 37.10684 +#: ../en/ch09-hook.xml:1045 37.10685 msgid "" 37.10686 "<literal>strip</literal>: The number of leading path elements to strip from a " 37.10687 "repository's path name to construct a partial path for a URL. For example, if " 37.10688 @@ -11479,7 +10565,7 @@ 37.10689 msgstr "" 37.10690 37.10691 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10692 -#: ../en/ch10-hook.xml:1058 37.10693 +#: ../en/ch09-hook.xml:1059 37.10694 msgid "" 37.10695 "<literal>template</literal>: The text of the template to use. In addition to " 37.10696 "the usual changeset-related variables, this template can use <literal>hgweb</" 37.10697 @@ -11489,25 +10575,25 @@ 37.10698 msgstr "" 37.10699 37.10700 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10701 -#: ../en/ch10-hook.xml:1068 37.10702 +#: ../en/ch09-hook.xml:1069 37.10703 msgid "" 37.10704 "In addition, you can add a <envar role=\"rc-item-web\">baseurl</envar> item " 37.10705 "to the <literal role=\"rc-web\">web</literal> section of your <filename role=" 37.10706 -"\"special\"> /.hgrc</filename>. The <literal role=\"hg-ext\">bugzilla</" 37.10707 +"\"special\">~/.hgrc</filename>. The <literal role=\"hg-ext\">bugzilla</" 37.10708 "literal> hook will make this available when expanding a template, as the base " 37.10709 "string to use when constructing a URL that will let users browse from a " 37.10710 "Bugzilla comment to view a changeset. Example:" 37.10711 msgstr "" 37.10712 37.10713 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10714 -#: ../en/ch10-hook.xml:1080 37.10715 +#: ../en/ch09-hook.xml:1081 37.10716 msgid "" 37.10717 "Here is an example set of <literal role=\"hg-ext\">bugzilla</literal> hook " 37.10718 "config information." 37.10719 msgstr "" 37.10720 37.10721 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10722 -#: ../en/ch10-hook.xml:1097 37.10723 +#: ../en/ch09-hook.xml:1091 37.10724 msgid "" 37.10725 "The most common problems with configuring the <literal role=\"hg-ext" 37.10726 "\">bugzilla</literal> hook relate to running Bugzilla's " 37.10727 @@ -11516,7 +10602,7 @@ 37.10728 msgstr "" 37.10729 37.10730 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10731 -#: ../en/ch10-hook.xml:1103 37.10732 +#: ../en/ch09-hook.xml:1097 37.10733 msgid "" 37.10734 "Recall from section <xref linkend=\"sec.hook.bugzilla.config\"/> above that " 37.10735 "the user that runs the Mercurial process on the server is also the one that " 37.10736 @@ -11527,7 +10613,7 @@ 37.10737 msgstr "" 37.10738 37.10739 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10740 -#: ../en/ch10-hook.xml:1114 37.10741 +#: ../en/ch09-hook.xml:1108 37.10742 msgid "" 37.10743 "You can cause <filename>processmail</filename> to be run with the suitable " 37.10744 "user's identity using the <command>sudo</command> command. Here is an " 37.10745 @@ -11535,7 +10621,7 @@ 37.10746 msgstr "" 37.10747 37.10748 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10749 -#: ../en/ch10-hook.xml:1122 37.10750 +#: ../en/ch09-hook.xml:1115 37.10751 msgid "" 37.10752 "This allows the <literal>hg_user</literal> user to run a " 37.10753 "<filename>processmail-wrapper</filename> program under the identity of " 37.10754 @@ -11543,7 +10629,7 @@ 37.10755 msgstr "" 37.10756 37.10757 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10758 -#: ../en/ch10-hook.xml:1127 37.10759 +#: ../en/ch09-hook.xml:1120 37.10760 msgid "" 37.10761 "This indirection through a wrapper script is necessary, because " 37.10762 "<filename>processmail</filename> expects to be run with its current directory " 37.10763 @@ -11553,14 +10639,14 @@ 37.10764 msgstr "" 37.10765 37.10766 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10767 -#: ../en/ch10-hook.xml:1136 37.10768 +#: ../en/ch09-hook.xml:1129 37.10769 msgid "" 37.10770 "It doesn't seem to matter what email address you pass to " 37.10771 "<filename>processmail</filename>." 37.10772 msgstr "" 37.10773 37.10774 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10775 -#: ../en/ch10-hook.xml:1140 37.10776 +#: ../en/ch09-hook.xml:1133 37.10777 msgid "" 37.10778 "If your <literal role=\"rc-usermap\">usermap</literal> is not set up " 37.10779 "correctly, users will see an error message from the <literal role=\"hg-ext" 37.10780 @@ -11569,7 +10655,7 @@ 37.10781 msgstr "" 37.10782 37.10783 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10784 -#: ../en/ch10-hook.xml:1148 37.10785 +#: ../en/ch09-hook.xml:1140 37.10786 msgid "" 37.10787 "What this means is that the committer's address, <literal>john.q." 37.10788 "public@example.com</literal>, is not a valid Bugzilla user name, nor does it " 37.10789 @@ -11578,13 +10664,13 @@ 37.10790 msgstr "" 37.10791 37.10792 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10793 -#: ../en/ch10-hook.xml:1158 37.10794 +#: ../en/ch09-hook.xml:1150 37.10795 msgid "" 37.10796 "<literal role=\"hg-ext\">notify</literal>&emdash;send email notifications" 37.10797 msgstr "<literal role=\"hg-ext\">notify</literal>&emdash;邮件通知" 37.10798 37.10799 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10800 -#: ../en/ch10-hook.xml:1161 37.10801 +#: ../en/ch09-hook.xml:1153 37.10802 msgid "" 37.10803 "Although Mercurial's built-in web server provides RSS feeds of changes in " 37.10804 "every repository, many people prefer to receive change notifications via " 37.10805 @@ -11594,7 +10680,7 @@ 37.10806 msgstr "" 37.10807 37.10808 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10809 -#: ../en/ch10-hook.xml:1169 37.10810 +#: ../en/ch09-hook.xml:1161 37.10811 msgid "" 37.10812 "As with the <literal role=\"hg-ext\">bugzilla</literal> hook, the <literal " 37.10813 "role=\"hg-ext\">notify</literal> hook is template-driven, so you can " 37.10814 @@ -11602,7 +10688,7 @@ 37.10815 msgstr "" 37.10816 37.10817 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10818 -#: ../en/ch10-hook.xml:1175 37.10819 +#: ../en/ch09-hook.xml:1167 37.10820 msgid "" 37.10821 "By default, the <literal role=\"hg-ext\">notify</literal> hook includes a " 37.10822 "diff of every changeset that it sends out; you can limit the size of the " 37.10823 @@ -11611,12 +10697,12 @@ 37.10824 msgstr "" 37.10825 37.10826 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.10827 -#: ../en/ch10-hook.xml:1183 37.10828 +#: ../en/ch09-hook.xml:1175 37.10829 msgid "Configuring the <literal role=\"hg-ext\">notify</literal> hook" 37.10830 msgstr "配置 <literal role=\"hg-ext\">notify</literal> 钩子" 37.10831 37.10832 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10833 -#: ../en/ch10-hook.xml:1186 37.10834 +#: ../en/ch09-hook.xml:1178 37.10835 msgid "" 37.10836 "You can set up the <literal role=\"hg-ext\">notify</literal> hook to send one " 37.10837 "email message per incoming changeset, or one per incoming group of changesets " 37.10838 @@ -11624,15 +10710,15 @@ 37.10839 msgstr "" 37.10840 37.10841 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10842 -#: ../en/ch10-hook.xml:1197 37.10843 +#: ../en/ch09-hook.xml:1190 37.10844 msgid "" 37.10845 "Configuration information for this hook lives in the <literal role=\"rc-notify" 37.10846 -"\">notify</literal> section of a <filename role=\"special\"> /.hgrc</filename>" 37.10847 -"\\ file." 37.10848 +"\">notify</literal> section of a <filename role=\"special\">~/.hgrc</" 37.10849 +"filename> file." 37.10850 msgstr "" 37.10851 37.10852 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10853 -#: ../en/ch10-hook.xml:1202 37.10854 +#: ../en/ch09-hook.xml:1195 37.10855 msgid "" 37.10856 "<envar role=\"rc-item-notify\">test</envar>: By default, this hook does not " 37.10857 "send out email at all; instead, it prints the message that it " 37.10858 @@ -11644,17 +10730,17 @@ 37.10859 msgstr "" 37.10860 37.10861 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10862 -#: ../en/ch10-hook.xml:1214 37.10863 +#: ../en/ch09-hook.xml:1207 37.10864 msgid "" 37.10865 "<envar role=\"rc-item-notify\">config</envar>: The path to a configuration " 37.10866 "file that contains subscription information. This is kept separate from the " 37.10867 -"main <filename role=\"special\"> /.hgrc</filename>\\ so that you can maintain " 37.10868 +"main <filename role=\"special\">~/.hgrc</filename> so that you can maintain " 37.10869 "it in a repository of its own. People can then clone that repository, update " 37.10870 "their subscriptions, and push the changes back to your server." 37.10871 msgstr "" 37.10872 37.10873 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10874 -#: ../en/ch10-hook.xml:1223 37.10875 +#: ../en/ch09-hook.xml:1216 37.10876 msgid "" 37.10877 "<envar role=\"rc-item-notify\">strip</envar>: The number of leading path " 37.10878 "separator characters to strip from a repository's path, when deciding whether " 37.10879 @@ -11669,7 +10755,7 @@ 37.10880 msgstr "" 37.10881 37.10882 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10883 -#: ../en/ch10-hook.xml:1240 37.10884 +#: ../en/ch09-hook.xml:1233 37.10885 msgid "" 37.10886 "<envar role=\"rc-item-notify\">template</envar>: The template text to use " 37.10887 "when sending messages. This specifies both the contents of the message " 37.10888 @@ -11677,7 +10763,7 @@ 37.10889 msgstr "" 37.10890 37.10891 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10892 -#: ../en/ch10-hook.xml:1246 37.10893 +#: ../en/ch09-hook.xml:1239 37.10894 msgid "" 37.10895 "<envar role=\"rc-item-notify\">maxdiff</envar>: The maximum number of lines " 37.10896 "of diff data to append to the end of a message. If a diff is longer than " 37.10897 @@ -11686,7 +10772,7 @@ 37.10898 msgstr "" 37.10899 37.10900 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.10901 -#: ../en/ch10-hook.xml:1255 37.10902 +#: ../en/ch09-hook.xml:1248 37.10903 msgid "" 37.10904 "<envar role=\"rc-item-notify\">sources</envar>: A list of sources of " 37.10905 "changesets to consider. This lets you limit <literal role=\"hg-ext\">notify</" 37.10906 @@ -11696,7 +10782,7 @@ 37.10907 msgstr "" 37.10908 37.10909 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10910 -#: ../en/ch10-hook.xml:1267 37.10911 +#: ../en/ch09-hook.xml:1260 37.10912 msgid "" 37.10913 "If you set the <envar role=\"rc-item-web\">baseurl</envar> item in the " 37.10914 "<literal role=\"rc-web\">web</literal> section, you can use it in a template; " 37.10915 @@ -11704,19 +10790,19 @@ 37.10916 msgstr "" 37.10917 37.10918 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10919 -#: ../en/ch10-hook.xml:1273 37.10920 +#: ../en/ch09-hook.xml:1266 37.10921 msgid "" 37.10922 "Here is an example set of <literal role=\"hg-ext\">notify</literal> " 37.10923 "configuration information." 37.10924 msgstr "" 37.10925 37.10926 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10927 -#: ../en/ch10-hook.xml:1289 37.10928 +#: ../en/ch09-hook.xml:1272 37.10929 msgid "This will produce a message that looks like the following:" 37.10930 msgstr "" 37.10931 37.10932 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.10933 -#: ../en/ch10-hook.xml:1310 37.10934 +#: ../en/ch09-hook.xml:1282 37.10935 msgid "" 37.10936 "Do not forget that by default, the <literal role=\"hg-ext\">notify</literal> " 37.10937 "extension <emphasis>will not send any mail</emphasis> until you explicitly " 37.10938 @@ -11726,22 +10812,22 @@ 37.10939 msgstr "" 37.10940 37.10941 #. type: Content of: <book><chapter><sect1><title> 37.10942 -#: ../en/ch10-hook.xml:1322 37.10943 +#: ../en/ch09-hook.xml:1294 37.10944 msgid "Information for writers of hooks" 37.10945 msgstr "编写钩子的信息" 37.10946 37.10947 #. type: Content of: <book><chapter><sect1><sect2><title> 37.10948 -#: ../en/ch10-hook.xml:1325 37.10949 +#: ../en/ch09-hook.xml:1297 37.10950 msgid "In-process hook execution" 37.10951 msgstr "进程内钩子的执行" 37.10952 37.10953 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10954 -#: ../en/ch10-hook.xml:1327 37.10955 +#: ../en/ch09-hook.xml:1299 37.10956 msgid "An in-process hook is called with arguments of the following form:" 37.10957 msgstr "" 37.10958 37.10959 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10960 -#: ../en/ch10-hook.xml:1333 37.10961 +#: ../en/ch09-hook.xml:1303 37.10962 msgid "" 37.10963 "The <literal>ui</literal> parameter is a <literal role=\"py-mod-mercurial.ui" 37.10964 "\">ui</literal> object. The <literal>repo</literal> parameter is a <literal " 37.10965 @@ -11751,7 +10837,7 @@ 37.10966 msgstr "" 37.10967 37.10968 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.10969 -#: ../en/ch10-hook.xml:1342 37.10970 +#: ../en/ch09-hook.xml:1312 37.10971 msgid "" 37.10972 "If a parameter is named <literal>node</literal> or <literal>parentN</" 37.10973 "literal>, it will contain a hexadecimal changeset ID. The empty string is " 37.10974 @@ -11760,21 +10846,21 @@ 37.10975 msgstr "" 37.10976 37.10977 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.10978 -#: ../en/ch10-hook.xml:1349 37.10979 +#: ../en/ch09-hook.xml:1319 37.10980 msgid "" 37.10981 "If a parameter is named <literal>url</literal>, it will contain the URL of a " 37.10982 "remote repository, if that can be determined." 37.10983 msgstr "" 37.10984 37.10985 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.10986 -#: ../en/ch10-hook.xml:1354 37.10987 +#: ../en/ch09-hook.xml:1324 37.10988 msgid "" 37.10989 "Boolean-valued parameters are represented as Python <literal>bool</literal> " 37.10990 "objects." 37.10991 msgstr "" 37.10992 37.10993 #. type: Content of: <book><chapter><sect1><sect2><para> 37.10994 -#: ../en/ch10-hook.xml:1359 37.10995 +#: ../en/ch09-hook.xml:1329 37.10996 msgid "" 37.10997 "An in-process hook is called without a change to the process's working " 37.10998 "directory (unlike external hooks, which are run in the root of the " 37.10999 @@ -11783,7 +10869,7 @@ 37.11000 msgstr "" 37.11001 37.11002 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11003 -#: ../en/ch10-hook.xml:1366 37.11004 +#: ../en/ch09-hook.xml:1336 37.11005 msgid "" 37.11006 "If a hook returns a boolean <quote>false</quote> value, it is considered to " 37.11007 "have succeeded. If it returns a boolean <quote>true</quote> value or raises " 37.11008 @@ -11792,20 +10878,20 @@ 37.11009 msgstr "" 37.11010 37.11011 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11012 -#: ../en/ch10-hook.xml:1373 37.11013 +#: ../en/ch09-hook.xml:1343 37.11014 msgid "" 37.11015 "Note that changeset IDs are passed into Python hooks as hexadecimal strings, " 37.11016 "not the binary hashes that Mercurial's APIs normally use. To convert a hash " 37.11017 -"from hex to binary, use the \\pymodfunc{mercurial.node}{bin} function." 37.11018 -msgstr "" 37.11019 - 37.11020 -#. type: Content of: <book><chapter><sect1><sect2><title> 37.11021 -#: ../en/ch10-hook.xml:1381 37.11022 +"from hex to binary, use the <literal>bin</literal> function." 37.11023 +msgstr "" 37.11024 + 37.11025 +#. type: Content of: <book><chapter><sect1><sect2><title> 37.11026 +#: ../en/ch09-hook.xml:1351 37.11027 msgid "External hook execution" 37.11028 msgstr "外部钩子的执行" 37.11029 37.11030 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11031 -#: ../en/ch10-hook.xml:1383 37.11032 +#: ../en/ch09-hook.xml:1353 37.11033 msgid "" 37.11034 "An external hook is passed to the shell of the user running Mercurial. " 37.11035 "Features of that shell, such as variable substitution and command " 37.11036 @@ -11815,7 +10901,7 @@ 37.11037 msgstr "" 37.11038 37.11039 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11040 -#: ../en/ch10-hook.xml:1391 37.11041 +#: ../en/ch09-hook.xml:1361 37.11042 msgid "" 37.11043 "Hook parameters are passed to the hook as environment variables. Each " 37.11044 "environment variable's name is converted in upper case and prefixed with the " 37.11045 @@ -11826,7 +10912,7 @@ 37.11046 msgstr "" 37.11047 37.11048 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11049 -#: ../en/ch10-hook.xml:1400 37.11050 +#: ../en/ch09-hook.xml:1370 37.11051 msgid "" 37.11052 "A boolean parameter is represented as the string <quote><literal>1</literal></" 37.11053 "quote> for <quote>true</quote>, <quote><literal>0</literal></quote> for " 37.11054 @@ -11839,19 +10925,19 @@ 37.11055 msgstr "" 37.11056 37.11057 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11058 -#: ../en/ch10-hook.xml:1412 37.11059 +#: ../en/ch09-hook.xml:1382 37.11060 msgid "" 37.11061 "If a hook exits with a status of zero, it is considered to have succeeded. " 37.11062 "If it exits with a non-zero status, it is considered to have failed." 37.11063 msgstr "" 37.11064 37.11065 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11066 -#: ../en/ch10-hook.xml:1419 37.11067 +#: ../en/ch09-hook.xml:1389 37.11068 msgid "Finding out where changesets come from" 37.11069 msgstr "检查修改集来自何处" 37.11070 37.11071 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11072 -#: ../en/ch10-hook.xml:1421 37.11073 +#: ../en/ch09-hook.xml:1391 37.11074 msgid "" 37.11075 "A hook that involves the transfer of changesets between a local repository " 37.11076 "and another may be able to find out information about the <quote>far side</" 37.11077 @@ -11861,12 +10947,12 @@ 37.11078 msgstr "" 37.11079 37.11080 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.11081 -#: ../en/ch10-hook.xml:1430 37.11082 +#: ../en/ch09-hook.xml:1400 37.11083 msgid "Sources of changesets" 37.11084 msgstr "修改集的来源" 37.11085 37.11086 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.11087 -#: ../en/ch10-hook.xml:1432 37.11088 +#: ../en/ch09-hook.xml:1402 37.11089 msgid "" 37.11090 "Mercurial will tell a hook what means are, or were, used to transfer " 37.11091 "changesets between repositories. This is provided by Mercurial in a Python " 37.11092 @@ -11875,40 +10961,40 @@ 37.11093 msgstr "" 37.11094 37.11095 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11096 -#: ../en/ch10-hook.xml:1440 37.11097 +#: ../en/ch09-hook.xml:1410 37.11098 msgid "" 37.11099 "<literal>serve</literal>: Changesets are transferred to or from a remote " 37.11100 "repository over http or ssh." 37.11101 msgstr "" 37.11102 37.11103 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11104 -#: ../en/ch10-hook.xml:1445 37.11105 +#: ../en/ch09-hook.xml:1415 37.11106 msgid "" 37.11107 "<literal>pull</literal>: Changesets are being transferred via a pull from one " 37.11108 "repository into another." 37.11109 msgstr "" 37.11110 37.11111 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11112 -#: ../en/ch10-hook.xml:1450 37.11113 +#: ../en/ch09-hook.xml:1420 37.11114 msgid "" 37.11115 "<literal>push</literal>: Changesets are being transferred via a push from one " 37.11116 "repository into another." 37.11117 msgstr "" 37.11118 37.11119 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11120 -#: ../en/ch10-hook.xml:1455 37.11121 +#: ../en/ch09-hook.xml:1425 37.11122 msgid "" 37.11123 "<literal>bundle</literal>: Changesets are being transferred to or from a " 37.11124 "bundle." 37.11125 msgstr "" 37.11126 37.11127 #. type: Content of: <book><chapter><sect1><sect2><sect3><title> 37.11128 -#: ../en/ch10-hook.xml:1462 37.11129 +#: ../en/ch09-hook.xml:1432 37.11130 msgid "Where changes are going&emdash;remote repository URLs" 37.11131 msgstr "修改集要到哪里&emdash;远程版本库的地址" 37.11132 37.11133 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.11134 -#: ../en/ch10-hook.xml:1465 37.11135 +#: ../en/ch09-hook.xml:1435 37.11136 msgid "" 37.11137 "When possible, Mercurial will tell a hook the location of the <quote>far " 37.11138 "side</quote> of an activity that transfers changeset data between " 37.11139 @@ -11918,7 +11004,7 @@ 37.11140 msgstr "" 37.11141 37.11142 #. type: Content of: <book><chapter><sect1><sect2><sect3><para> 37.11143 -#: ../en/ch10-hook.xml:1473 37.11144 +#: ../en/ch09-hook.xml:1443 37.11145 msgid "" 37.11146 "This information is not always known. If a hook is invoked in a repository " 37.11147 "that is being served via http or ssh, Mercurial cannot tell where the remote " 37.11148 @@ -11927,14 +11013,14 @@ 37.11149 msgstr "" 37.11150 37.11151 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11152 -#: ../en/ch10-hook.xml:1480 37.11153 +#: ../en/ch09-hook.xml:1450 37.11154 msgid "" 37.11155 "<literal>remote:ssh:1.2.3.4</literal>&emdash;remote ssh client, at the IP " 37.11156 "address <literal>1.2.3.4</literal>." 37.11157 msgstr "" 37.11158 37.11159 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11160 -#: ../en/ch10-hook.xml:1485 37.11161 +#: ../en/ch09-hook.xml:1455 37.11162 msgid "" 37.11163 "<literal>remote:http:1.2.3.4</literal>&emdash;remote http client, at the IP " 37.11164 "address <literal>1.2.3.4</literal>. If the client is using SSL, this will be " 37.11165 @@ -11942,24 +11028,24 @@ 37.11166 msgstr "" 37.11167 37.11168 #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> 37.11169 -#: ../en/ch10-hook.xml:1492 37.11170 +#: ../en/ch09-hook.xml:1462 37.11171 msgid "Empty&emdash;no information could be discovered about the remote client." 37.11172 msgstr "" 37.11173 37.11174 #. type: Content of: <book><chapter><sect1><title> 37.11175 -#: ../en/ch10-hook.xml:1501 37.11176 +#: ../en/ch09-hook.xml:1471 37.11177 msgid "Hook reference" 37.11178 msgstr "钩子参考" 37.11179 37.11180 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11181 -#: ../en/ch10-hook.xml:1504 37.11182 +#: ../en/ch09-hook.xml:1474 37.11183 msgid "" 37.11184 "<literal role=\"hook\">changegroup</literal>&emdash;after remote changesets " 37.11185 "added" 37.11186 msgstr "<literal role=\"hook\">changegroup</literal>&emdash;增加远程修改集之后" 37.11187 37.11188 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11189 -#: ../en/ch10-hook.xml:1507 37.11190 +#: ../en/ch09-hook.xml:1477 37.11191 msgid "" 37.11192 "This hook is run after a group of pre-existing changesets has been added to " 37.11193 "the repository, for example via a <command role=\"hg-cmd\">hg pull</command> " 37.11194 @@ -11970,7 +11056,7 @@ 37.11195 msgstr "" 37.11196 37.11197 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11198 -#: ../en/ch10-hook.xml:1517 37.11199 +#: ../en/ch09-hook.xml:1487 37.11200 msgid "" 37.11201 "Some possible uses for this hook include kicking off an automated build or " 37.11202 "test of the added changesets, updating a bug database, or notifying " 37.11203 @@ -11978,42 +11064,41 @@ 37.11204 msgstr "" 37.11205 37.11206 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11207 -#: ../en/ch10-hook.xml:1523 ../en/ch10-hook.xml:1564 ../en/ch10-hook.xml:1607 37.11208 -#: ../en/ch10-hook.xml:1649 ../en/ch10-hook.xml:1704 ../en/ch10-hook.xml:1744 37.11209 -#: ../en/ch10-hook.xml:1780 ../en/ch10-hook.xml:1815 ../en/ch10-hook.xml:1877 37.11210 -#: ../en/ch10-hook.xml:1935 ../en/ch10-hook.xml:1969 ../en/ch10-hook.xml:1997 37.11211 +#: ../en/ch09-hook.xml:1493 ../en/ch09-hook.xml:1533 ../en/ch09-hook.xml:1576 37.11212 +#: ../en/ch09-hook.xml:1618 ../en/ch09-hook.xml:1673 ../en/ch09-hook.xml:1713 37.11213 +#: ../en/ch09-hook.xml:1749 ../en/ch09-hook.xml:1784 ../en/ch09-hook.xml:1846 37.11214 +#: ../en/ch09-hook.xml:1904 ../en/ch09-hook.xml:1938 ../en/ch09-hook.xml:1966 37.11215 msgid "Parameters to this hook:" 37.11216 msgstr "" 37.11217 37.11218 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11219 -#: ../en/ch10-hook.xml:1526 ../en/ch10-hook.xml:1880 37.11220 +#: ../en/ch09-hook.xml:1496 ../en/ch09-hook.xml:1849 37.11221 msgid "" 37.11222 "<literal>node</literal>: A changeset ID. The changeset ID of the first " 37.11223 "changeset in the group that was added. All changesets between this and " 37.11224 -"\\index{tags!<literal>tip</literal>}<literal>tip</literal>, inclusive, were " 37.11225 -"added by a single <command role=\"hg-cmd\">hg pull</command>, <command role=" 37.11226 -"\"hg-cmd\">hg push</command> or <command role=\"hg-cmd\">hg unbundle</" 37.11227 -"command>." 37.11228 +"<literal role=\"tag\">tip</literal>, inclusive, were added by a single " 37.11229 +"<command role=\"hg-cmd\">hg pull</command>, <command role=\"hg-cmd\">hg push</" 37.11230 +"command> or <command role=\"hg-cmd\">hg unbundle</command>." 37.11231 msgstr "" 37.11232 37.11233 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11234 -#: ../en/ch10-hook.xml:1536 ../en/ch10-hook.xml:1614 ../en/ch10-hook.xml:1707 37.11235 -#: ../en/ch10-hook.xml:1890 37.11236 +#: ../en/ch09-hook.xml:1505 ../en/ch09-hook.xml:1583 ../en/ch09-hook.xml:1676 37.11237 +#: ../en/ch09-hook.xml:1859 37.11238 msgid "" 37.11239 "<literal>source</literal>: A string. The source of these changes. See " 37.11240 "section <xref linkend=\"sec.hook.sources\"/> for details." 37.11241 msgstr "" 37.11242 37.11243 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11244 -#: ../en/ch10-hook.xml:1541 ../en/ch10-hook.xml:1619 ../en/ch10-hook.xml:1670 37.11245 -#: ../en/ch10-hook.xml:1712 ../en/ch10-hook.xml:1794 ../en/ch10-hook.xml:1895 37.11246 +#: ../en/ch09-hook.xml:1510 ../en/ch09-hook.xml:1588 ../en/ch09-hook.xml:1639 37.11247 +#: ../en/ch09-hook.xml:1681 ../en/ch09-hook.xml:1763 ../en/ch09-hook.xml:1864 37.11248 msgid "" 37.11249 "<literal>url</literal>: A URL. The location of the remote repository, if " 37.11250 "known. See section <xref linkend=\"sec.hook.url\"/> for more information." 37.11251 msgstr "" 37.11252 37.11253 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11254 -#: ../en/ch10-hook.xml:1548 37.11255 +#: ../en/ch09-hook.xml:1517 37.11256 msgid "" 37.11257 "See also: <literal role=\"hook\">incoming</literal> (section <xref linkend=" 37.11258 "\"sec.hook.incoming\"/>), <literal role=\"hook\">prechangegroup</literal> " 37.11259 @@ -12023,40 +11108,40 @@ 37.11260 msgstr "" 37.11261 37.11262 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11263 -#: ../en/ch10-hook.xml:1558 37.11264 +#: ../en/ch09-hook.xml:1527 37.11265 msgid "" 37.11266 "<literal role=\"hook\">commit</literal>&emdash;after a new changeset is " 37.11267 "created" 37.11268 msgstr "<literal role=\"hook\">commit</literal>&emdash;创建新修改集之后" 37.11269 37.11270 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11271 -#: ../en/ch10-hook.xml:1561 37.11272 +#: ../en/ch09-hook.xml:1530 37.11273 msgid "This hook is run after a new changeset has been created." 37.11274 msgstr "" 37.11275 37.11276 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11277 -#: ../en/ch10-hook.xml:1567 ../en/ch10-hook.xml:1938 37.11278 +#: ../en/ch09-hook.xml:1536 ../en/ch09-hook.xml:1907 37.11279 msgid "" 37.11280 "<literal>node</literal>: A changeset ID. The changeset ID of the newly " 37.11281 "committed changeset." 37.11282 msgstr "" 37.11283 37.11284 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11285 -#: ../en/ch10-hook.xml:1571 ../en/ch10-hook.xml:1942 37.11286 +#: ../en/ch09-hook.xml:1540 ../en/ch09-hook.xml:1911 37.11287 msgid "" 37.11288 "<literal>parent1</literal>: A changeset ID. The changeset ID of the first " 37.11289 "parent of the newly committed changeset." 37.11290 msgstr "" 37.11291 37.11292 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11293 -#: ../en/ch10-hook.xml:1576 ../en/ch10-hook.xml:1947 37.11294 +#: ../en/ch09-hook.xml:1545 ../en/ch09-hook.xml:1916 37.11295 msgid "" 37.11296 "<literal>parent2</literal>: A changeset ID. The changeset ID of the second " 37.11297 "parent of the newly committed changeset." 37.11298 msgstr "" 37.11299 37.11300 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11301 -#: ../en/ch10-hook.xml:1582 37.11302 +#: ../en/ch09-hook.xml:1551 37.11303 msgid "" 37.11304 "See also: <literal role=\"hook\">precommit</literal> (section <xref linkend=" 37.11305 "\"sec.hook.precommit\"/>), <literal role=\"hook\">pretxncommit</literal> " 37.11306 @@ -12064,14 +11149,14 @@ 37.11307 msgstr "" 37.11308 37.11309 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11310 -#: ../en/ch10-hook.xml:1590 37.11311 +#: ../en/ch09-hook.xml:1559 37.11312 msgid "" 37.11313 "<literal role=\"hook\">incoming</literal>&emdash;after one remote changeset " 37.11314 "is added" 37.11315 msgstr "<literal role=\"hook\">incoming</literal>&emdash;增加远程修改集之后" 37.11316 37.11317 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11318 -#: ../en/ch10-hook.xml:1593 37.11319 +#: ../en/ch09-hook.xml:1562 37.11320 msgid "" 37.11321 "This hook is run after a pre-existing changeset has been added to the " 37.11322 "repository, for example via a <command role=\"hg-cmd\">hg push</command>. If " 37.11323 @@ -12080,7 +11165,7 @@ 37.11324 msgstr "" 37.11325 37.11326 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11327 -#: ../en/ch10-hook.xml:1600 37.11328 +#: ../en/ch09-hook.xml:1569 37.11329 msgid "" 37.11330 "You can use this hook for the same purposes as the <literal role=\"hook" 37.11331 "\">changegroup</literal> hook (section <xref linkend=\"sec.hook.changegroup\"/" 37.11332 @@ -12089,13 +11174,13 @@ 37.11333 msgstr "" 37.11334 37.11335 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11336 -#: ../en/ch10-hook.xml:1610 37.11337 +#: ../en/ch09-hook.xml:1579 37.11338 msgid "" 37.11339 "<literal>node</literal>: A changeset ID. The ID of the newly added changeset." 37.11340 msgstr "" 37.11341 37.11342 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11343 -#: ../en/ch10-hook.xml:1626 37.11344 +#: ../en/ch09-hook.xml:1595 37.11345 msgid "" 37.11346 "See also: <literal role=\"hook\">changegroup</literal> (section <xref linkend=" 37.11347 "\"sec.hook.changegroup\"/>) <literal role=\"hook\">prechangegroup</literal> " 37.11348 @@ -12105,14 +11190,14 @@ 37.11349 msgstr "" 37.11350 37.11351 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11352 -#: ../en/ch10-hook.xml:1636 37.11353 +#: ../en/ch09-hook.xml:1605 37.11354 msgid "" 37.11355 "<literal role=\"hook\">outgoing</literal>&emdash;after changesets are " 37.11356 "propagated" 37.11357 msgstr "<literal role=\"hook\">outgoing</literal>&emdash;传播修改集之后" 37.11358 37.11359 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11360 -#: ../en/ch10-hook.xml:1639 37.11361 +#: ../en/ch09-hook.xml:1608 37.11362 msgid "" 37.11363 "This hook is run after a group of changesets has been propagated out of this " 37.11364 "repository, for example by a <command role=\"hg-cmd\">hg push</command> or " 37.11365 @@ -12120,21 +11205,21 @@ 37.11366 msgstr "" 37.11367 37.11368 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11369 -#: ../en/ch10-hook.xml:1645 37.11370 +#: ../en/ch09-hook.xml:1614 37.11371 msgid "" 37.11372 "One possible use for this hook is to notify administrators that changes have " 37.11373 "been pulled." 37.11374 msgstr "" 37.11375 37.11376 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11377 -#: ../en/ch10-hook.xml:1652 37.11378 +#: ../en/ch09-hook.xml:1621 37.11379 msgid "" 37.11380 "<literal>node</literal>: A changeset ID. The changeset ID of the first " 37.11381 "changeset of the group that was sent." 37.11382 msgstr "" 37.11383 37.11384 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11385 -#: ../en/ch10-hook.xml:1657 37.11386 +#: ../en/ch09-hook.xml:1626 37.11387 msgid "" 37.11388 "<literal>source</literal>: A string. The source of the of the operation (see " 37.11389 "section <xref linkend=\"sec.hook.sources\"/>). If a remote client pulled " 37.11390 @@ -12146,14 +11231,14 @@ 37.11391 msgstr "" 37.11392 37.11393 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11394 -#: ../en/ch10-hook.xml:1677 37.11395 +#: ../en/ch09-hook.xml:1646 37.11396 msgid "" 37.11397 "See also: <literal role=\"hook\">preoutgoing</literal> (section <xref linkend=" 37.11398 "\"sec.hook.preoutgoing\"/>)" 37.11399 msgstr "" 37.11400 37.11401 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11402 -#: ../en/ch10-hook.xml:1683 37.11403 +#: ../en/ch09-hook.xml:1652 37.11404 msgid "" 37.11405 "<literal role=\"hook\">prechangegroup</literal>&emdash;before starting to add " 37.11406 "remote changesets" 37.11407 @@ -12161,14 +11246,14 @@ 37.11408 "<literal role=\"hook\">prechangegroup</literal>&emdash;增加远程修改集之前" 37.11409 37.11410 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11411 -#: ../en/ch10-hook.xml:1687 37.11412 +#: ../en/ch09-hook.xml:1656 37.11413 msgid "" 37.11414 "This controlling hook is run before Mercurial begins to add a group of " 37.11415 "changesets from another repository." 37.11416 msgstr "" 37.11417 37.11418 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11419 -#: ../en/ch10-hook.xml:1691 37.11420 +#: ../en/ch09-hook.xml:1660 37.11421 msgid "" 37.11422 "This hook does not have any information about the changesets to be added, " 37.11423 "because it is run before transmission of those changesets is allowed to " 37.11424 @@ -12176,7 +11261,7 @@ 37.11425 msgstr "" 37.11426 37.11427 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11428 -#: ../en/ch10-hook.xml:1697 37.11429 +#: ../en/ch09-hook.xml:1666 37.11430 msgid "" 37.11431 "One use for this hook is to prevent external changes from being added to a " 37.11432 "repository. For example, you could use this to <quote>freeze</quote> a " 37.11433 @@ -12185,7 +11270,7 @@ 37.11434 msgstr "" 37.11435 37.11436 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11437 -#: ../en/ch10-hook.xml:1719 37.11438 +#: ../en/ch09-hook.xml:1688 37.11439 msgid "" 37.11440 "See also: <literal role=\"hook\">changegroup</literal> (section <xref linkend=" 37.11441 "\"sec.hook.changegroup\"/>), <literal role=\"hook\">incoming</literal> " 37.11442 @@ -12195,14 +11280,14 @@ 37.11443 msgstr "" 37.11444 37.11445 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11446 -#: ../en/ch10-hook.xml:1729 37.11447 +#: ../en/ch09-hook.xml:1698 37.11448 msgid "" 37.11449 "<literal role=\"hook\">precommit</literal>&emdash;before starting to commit a " 37.11450 "changeset" 37.11451 msgstr "<literal role=\"hook\">precommit</literal>&emdash;提交修改集之前" 37.11452 37.11453 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11454 -#: ../en/ch10-hook.xml:1732 37.11455 +#: ../en/ch09-hook.xml:1701 37.11456 msgid "" 37.11457 "This hook is run before Mercurial begins to commit a new changeset. It is run " 37.11458 "before Mercurial has any of the metadata for the commit, such as the files to " 37.11459 @@ -12210,7 +11295,7 @@ 37.11460 msgstr "" 37.11461 37.11462 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11463 -#: ../en/ch10-hook.xml:1738 37.11464 +#: ../en/ch09-hook.xml:1707 37.11465 msgid "" 37.11466 "One use for this hook is to disable the ability to commit new changesets, " 37.11467 "while still allowing incoming changesets. Another is to run a build or test, " 37.11468 @@ -12218,28 +11303,28 @@ 37.11469 msgstr "" 37.11470 37.11471 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11472 -#: ../en/ch10-hook.xml:1747 37.11473 +#: ../en/ch09-hook.xml:1716 37.11474 msgid "" 37.11475 "<literal>parent1</literal>: A changeset ID. The changeset ID of the first " 37.11476 "parent of the working directory." 37.11477 msgstr "" 37.11478 37.11479 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11480 -#: ../en/ch10-hook.xml:1752 37.11481 +#: ../en/ch09-hook.xml:1721 37.11482 msgid "" 37.11483 "<literal>parent2</literal>: A changeset ID. The changeset ID of the second " 37.11484 "parent of the working directory." 37.11485 msgstr "" 37.11486 37.11487 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11488 -#: ../en/ch10-hook.xml:1757 37.11489 +#: ../en/ch09-hook.xml:1726 37.11490 msgid "" 37.11491 "If the commit proceeds, the parents of the working directory will become the " 37.11492 "parents of the new changeset." 37.11493 msgstr "" 37.11494 37.11495 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11496 -#: ../en/ch10-hook.xml:1761 37.11497 +#: ../en/ch09-hook.xml:1730 37.11498 msgid "" 37.11499 "See also: <literal role=\"hook\">commit</literal> (section <xref linkend=" 37.11500 "\"sec.hook.commit\"/>), <literal role=\"hook\">pretxncommit</literal> " 37.11501 @@ -12247,28 +11332,28 @@ 37.11502 msgstr "" 37.11503 37.11504 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11505 -#: ../en/ch10-hook.xml:1769 37.11506 +#: ../en/ch09-hook.xml:1738 37.11507 msgid "" 37.11508 "<literal role=\"hook\">preoutgoing</literal>&emdash;before starting to " 37.11509 "propagate changesets" 37.11510 msgstr "<literal role=\"hook\">preoutgoing</literal>&emdash;传播修改集之前" 37.11511 37.11512 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11513 -#: ../en/ch10-hook.xml:1772 37.11514 +#: ../en/ch09-hook.xml:1741 37.11515 msgid "" 37.11516 "This hook is invoked before Mercurial knows the identities of the changesets " 37.11517 "to be transmitted." 37.11518 msgstr "" 37.11519 37.11520 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11521 -#: ../en/ch10-hook.xml:1776 37.11522 +#: ../en/ch09-hook.xml:1745 37.11523 msgid "" 37.11524 "One use for this hook is to prevent changes from being transmitted to another " 37.11525 "repository." 37.11526 msgstr "" 37.11527 37.11528 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11529 -#: ../en/ch10-hook.xml:1783 37.11530 +#: ../en/ch09-hook.xml:1752 37.11531 msgid "" 37.11532 "<literal>source</literal>: A string. The source of the operation that is " 37.11533 "attempting to obtain changes from this repository (see section <xref linkend=" 37.11534 @@ -12279,27 +11364,27 @@ 37.11535 msgstr "" 37.11536 37.11537 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11538 -#: ../en/ch10-hook.xml:1801 37.11539 +#: ../en/ch09-hook.xml:1770 37.11540 msgid "" 37.11541 "See also: <literal role=\"hook\">outgoing</literal> (section <xref linkend=" 37.11542 "\"sec.hook.outgoing\"/>)" 37.11543 msgstr "" 37.11544 37.11545 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11546 -#: ../en/ch10-hook.xml:1807 37.11547 +#: ../en/ch09-hook.xml:1776 37.11548 msgid "" 37.11549 "<literal role=\"hook\">pretag</literal>&emdash;before tagging a changeset" 37.11550 msgstr "<literal role=\"hook\">pretag</literal>&emdash;创建标签之前" 37.11551 37.11552 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11553 -#: ../en/ch10-hook.xml:1810 37.11554 +#: ../en/ch09-hook.xml:1779 37.11555 msgid "" 37.11556 "This controlling hook is run before a tag is created. If the hook succeeds, " 37.11557 "creation of the tag proceeds. If the hook fails, the tag is not created." 37.11558 msgstr "" 37.11559 37.11560 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11561 -#: ../en/ch10-hook.xml:1818 37.11562 +#: ../en/ch09-hook.xml:1787 37.11563 msgid "" 37.11564 "<literal>local</literal>: A boolean. Whether the tag is local to this " 37.11565 "repository instance (i.e. stored in <filename role=\"special\">.hg/localtags</" 37.11566 @@ -12308,19 +11393,19 @@ 37.11567 msgstr "" 37.11568 37.11569 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11570 -#: ../en/ch10-hook.xml:1825 37.11571 +#: ../en/ch09-hook.xml:1794 37.11572 msgid "" 37.11573 "<literal>node</literal>: A changeset ID. The ID of the changeset to be " 37.11574 "tagged." 37.11575 msgstr "" 37.11576 37.11577 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11578 -#: ../en/ch10-hook.xml:1829 37.11579 +#: ../en/ch09-hook.xml:1798 37.11580 msgid "<literal>tag</literal>: A string. The name of the tag to be created." 37.11581 msgstr "" 37.11582 37.11583 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11584 -#: ../en/ch10-hook.xml:1834 37.11585 +#: ../en/ch09-hook.xml:1803 37.11586 msgid "" 37.11587 "If the tag to be created is revision-controlled, the <literal role=\"hook" 37.11588 "\">precommit</literal> and <literal role=\"hook\">pretxncommit</literal> " 37.11589 @@ -12329,14 +11414,14 @@ 37.11590 msgstr "" 37.11591 37.11592 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11593 -#: ../en/ch10-hook.xml:1841 37.11594 +#: ../en/ch09-hook.xml:1810 37.11595 msgid "" 37.11596 "See also: <literal role=\"hook\">tag</literal> (section <xref linkend=\"sec." 37.11597 "hook.tag\"/>)" 37.11598 msgstr "" 37.11599 37.11600 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11601 -#: ../en/ch10-hook.xml:1846 37.11602 +#: ../en/ch09-hook.xml:1815 37.11603 msgid "" 37.11604 "<literal role=\"hook\">pretxnchangegroup</literal>&emdash;before completing " 37.11605 "addition of remote changesets" 37.11606 @@ -12345,7 +11430,7 @@ 37.11607 "前" 37.11608 37.11609 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11610 -#: ../en/ch10-hook.xml:1850 37.11611 +#: ../en/ch09-hook.xml:1819 37.11612 msgid "" 37.11613 "This controlling hook is run before a transaction&emdash;that manages the " 37.11614 "addition of a group of new changesets from outside the repository&emdash;" 37.11615 @@ -12355,7 +11440,7 @@ 37.11616 msgstr "" 37.11617 37.11618 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11619 -#: ../en/ch10-hook.xml:1859 37.11620 +#: ../en/ch09-hook.xml:1828 37.11621 msgid "" 37.11622 "This hook can access the metadata associated with the almost-added " 37.11623 "changesets, but it should not do anything permanent with this data. It must " 37.11624 @@ -12363,7 +11448,7 @@ 37.11625 msgstr "" 37.11626 37.11627 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11628 -#: ../en/ch10-hook.xml:1865 37.11629 +#: ../en/ch09-hook.xml:1834 37.11630 msgid "" 37.11631 "While this hook is running, if other Mercurial processes access this " 37.11632 "repository, they will be able to see the almost-added changesets as if they " 37.11633 @@ -12372,7 +11457,7 @@ 37.11634 msgstr "" 37.11635 37.11636 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11637 -#: ../en/ch10-hook.xml:1872 37.11638 +#: ../en/ch09-hook.xml:1841 37.11639 msgid "" 37.11640 "This hook can be used to automatically vet a group of changesets. If the " 37.11641 "hook fails, all of the changesets are <quote>rejected</quote> when the " 37.11642 @@ -12380,7 +11465,7 @@ 37.11643 msgstr "" 37.11644 37.11645 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11646 -#: ../en/ch10-hook.xml:1902 37.11647 +#: ../en/ch09-hook.xml:1871 37.11648 msgid "" 37.11649 "See also: <literal role=\"hook\">changegroup</literal> (section <xref linkend=" 37.11650 "\"sec.hook.changegroup\"/>), <literal role=\"hook\">incoming</literal> " 37.11651 @@ -12390,14 +11475,14 @@ 37.11652 msgstr "" 37.11653 37.11654 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11655 -#: ../en/ch10-hook.xml:1912 37.11656 +#: ../en/ch09-hook.xml:1881 37.11657 msgid "" 37.11658 "<literal role=\"hook\">pretxncommit</literal>&emdash;before completing commit " 37.11659 "of new changeset" 37.11660 msgstr "<literal role=\"hook\">pretxncommit</literal>&emdash;完成提交之前" 37.11661 37.11662 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11663 -#: ../en/ch10-hook.xml:1915 37.11664 +#: ../en/ch09-hook.xml:1884 37.11665 msgid "" 37.11666 "This controlling hook is run before a transaction&emdash;that manages a new " 37.11667 "commit&emdash;completes. If the hook succeeds, the transaction completes and " 37.11668 @@ -12406,7 +11491,7 @@ 37.11669 msgstr "" 37.11670 37.11671 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11672 -#: ../en/ch10-hook.xml:1923 37.11673 +#: ../en/ch09-hook.xml:1892 37.11674 msgid "" 37.11675 "This hook can access the metadata associated with the almost-new changeset, " 37.11676 "but it should not do anything permanent with this data. It must also not " 37.11677 @@ -12414,7 +11499,7 @@ 37.11678 msgstr "" 37.11679 37.11680 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11681 -#: ../en/ch10-hook.xml:1929 37.11682 +#: ../en/ch09-hook.xml:1898 37.11683 msgid "" 37.11684 "While this hook is running, if other Mercurial processes access this " 37.11685 "repository, they will be able to see the almost-new changeset as if it is " 37.11686 @@ -12423,14 +11508,14 @@ 37.11687 msgstr "" 37.11688 37.11689 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11690 -#: ../en/ch10-hook.xml:1953 37.11691 +#: ../en/ch09-hook.xml:1922 37.11692 msgid "" 37.11693 "See also: <literal role=\"hook\">precommit</literal> (section <xref linkend=" 37.11694 "\"sec.hook.precommit\"/>)" 37.11695 msgstr "" 37.11696 37.11697 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11698 -#: ../en/ch10-hook.xml:1959 37.11699 +#: ../en/ch09-hook.xml:1928 37.11700 msgid "" 37.11701 "<literal role=\"hook\">preupdate</literal>&emdash;before updating or merging " 37.11702 "working directory" 37.11703 @@ -12438,7 +11523,7 @@ 37.11704 "<literal role=\"hook\">preupdate</literal>&emdash;更新或合并工作目录之前" 37.11705 37.11706 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11707 -#: ../en/ch10-hook.xml:1962 37.11708 +#: ../en/ch09-hook.xml:1931 37.11709 msgid "" 37.11710 "This controlling hook is run before an update or merge of the working " 37.11711 "directory begins. It is run only if Mercurial's normal pre-update checks " 37.11712 @@ -12447,7 +11532,7 @@ 37.11713 msgstr "" 37.11714 37.11715 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11716 -#: ../en/ch10-hook.xml:1972 37.11717 +#: ../en/ch09-hook.xml:1941 37.11718 msgid "" 37.11719 "<literal>parent1</literal>: A changeset ID. The ID of the parent that the " 37.11720 "working directory is to be updated to. If the working directory is being " 37.11721 @@ -12455,7 +11540,7 @@ 37.11722 msgstr "" 37.11723 37.11724 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11725 -#: ../en/ch10-hook.xml:1978 37.11726 +#: ../en/ch09-hook.xml:1947 37.11727 msgid "" 37.11728 "<literal>parent2</literal>: A changeset ID. Only set if the working " 37.11729 "directory is being merged. The ID of the revision that the working directory " 37.11730 @@ -12463,24 +11548,24 @@ 37.11731 msgstr "" 37.11732 37.11733 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11734 -#: ../en/ch10-hook.xml:1985 37.11735 +#: ../en/ch09-hook.xml:1954 37.11736 msgid "" 37.11737 "See also: <literal role=\"hook\">update</literal> (section <xref linkend=" 37.11738 "\"sec.hook.update\"/>)" 37.11739 msgstr "" 37.11740 37.11741 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11742 -#: ../en/ch10-hook.xml:1991 37.11743 +#: ../en/ch09-hook.xml:1960 37.11744 msgid "<literal role=\"hook\">tag</literal>&emdash;after tagging a changeset" 37.11745 msgstr "<literal role=\"hook\">tag</literal>&emdash;创建标签之后" 37.11746 37.11747 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11748 -#: ../en/ch10-hook.xml:1994 37.11749 +#: ../en/ch09-hook.xml:1963 37.11750 msgid "This hook is run after a tag has been created." 37.11751 msgstr "" 37.11752 37.11753 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11754 -#: ../en/ch10-hook.xml:2000 37.11755 +#: ../en/ch09-hook.xml:1969 37.11756 msgid "" 37.11757 "<literal>local</literal>: A boolean. Whether the new tag is local to this " 37.11758 "repository instance (i.e. stored in <filename role=\"special\">.hg/" 37.11759 @@ -12489,19 +11574,19 @@ 37.11760 msgstr "" 37.11761 37.11762 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11763 -#: ../en/ch10-hook.xml:2008 37.11764 +#: ../en/ch09-hook.xml:1977 37.11765 msgid "" 37.11766 "<literal>node</literal>: A changeset ID. The ID of the changeset that was " 37.11767 "tagged." 37.11768 msgstr "" 37.11769 37.11770 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11771 -#: ../en/ch10-hook.xml:2012 37.11772 +#: ../en/ch09-hook.xml:1981 37.11773 msgid "<literal>tag</literal>: A string. The name of the tag that was created." 37.11774 msgstr "" 37.11775 37.11776 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11777 -#: ../en/ch10-hook.xml:2017 37.11778 +#: ../en/ch09-hook.xml:1986 37.11779 msgid "" 37.11780 "If the created tag is revision-controlled, the <literal role=\"hook\">commit</" 37.11781 "literal> hook (section <xref linkend=\"sec.hook.commit\"/>) is run before " 37.11782 @@ -12509,21 +11594,21 @@ 37.11783 msgstr "" 37.11784 37.11785 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11786 -#: ../en/ch10-hook.xml:2022 37.11787 +#: ../en/ch09-hook.xml:1991 37.11788 msgid "" 37.11789 "See also: <literal role=\"hook\">pretag</literal> (section <xref linkend=" 37.11790 "\"sec.hook.pretag\"/>)" 37.11791 msgstr "" 37.11792 37.11793 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11794 -#: ../en/ch10-hook.xml:2028 37.11795 +#: ../en/ch09-hook.xml:1997 37.11796 msgid "" 37.11797 "<literal role=\"hook\">update</literal>&emdash;after updating or merging " 37.11798 "working directory" 37.11799 msgstr "<literal role=\"hook\">update</literal>&emdash;更新或合并工作目录之后" 37.11800 37.11801 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11802 -#: ../en/ch10-hook.xml:2031 37.11803 +#: ../en/ch09-hook.xml:2000 37.11804 msgid "" 37.11805 "This hook is run after an update or merge of the working directory " 37.11806 "completes. Since a merge can fail (if the external <command>hgmerge</" 37.11807 @@ -12532,14 +11617,14 @@ 37.11808 msgstr "" 37.11809 37.11810 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11811 -#: ../en/ch10-hook.xml:2039 37.11812 +#: ../en/ch09-hook.xml:2008 37.11813 msgid "" 37.11814 "<literal>error</literal>: A boolean. Indicates whether the update or merge " 37.11815 "completed successfully." 37.11816 msgstr "" 37.11817 37.11818 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11819 -#: ../en/ch10-hook.xml:2044 37.11820 +#: ../en/ch09-hook.xml:2013 37.11821 msgid "" 37.11822 "<literal>parent1</literal>: A changeset ID. The ID of the parent that the " 37.11823 "working directory was updated to. If the working directory was merged, it " 37.11824 @@ -12547,7 +11632,7 @@ 37.11825 msgstr "" 37.11826 37.11827 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.11828 -#: ../en/ch10-hook.xml:2050 37.11829 +#: ../en/ch09-hook.xml:2019 37.11830 msgid "" 37.11831 "<literal>parent2</literal>: A changeset ID. Only set if the working " 37.11832 "directory was merged. The ID of the revision that the working directory was " 37.11833 @@ -12555,19 +11640,19 @@ 37.11834 msgstr "" 37.11835 37.11836 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11837 -#: ../en/ch10-hook.xml:2056 37.11838 +#: ../en/ch09-hook.xml:2025 37.11839 msgid "" 37.11840 "See also: <literal role=\"hook\">preupdate</literal> (section <xref linkend=" 37.11841 "\"sec.hook.preupdate\"/>)" 37.11842 msgstr "" 37.11843 37.11844 #. type: Content of: <book><chapter><title> 37.11845 -#: ../en/ch11-template.xml:5 37.11846 +#: ../en/ch10-template.xml:5 37.11847 msgid "Customising the output of Mercurial" 37.11848 msgstr "定制 Mercurial 的输出" 37.11849 37.11850 #. type: Content of: <book><chapter><para> 37.11851 -#: ../en/ch11-template.xml:7 37.11852 +#: ../en/ch10-template.xml:7 37.11853 msgid "" 37.11854 "Mercurial provides a powerful mechanism to let you control how it displays " 37.11855 "information. The mechanism is based on templates. You can use templates to " 37.11856 @@ -12576,12 +11661,12 @@ 37.11857 msgstr "" 37.11858 37.11859 #. type: Content of: <book><chapter><sect1><title> 37.11860 -#: ../en/ch11-template.xml:14 37.11861 +#: ../en/ch10-template.xml:14 37.11862 msgid "Using precanned output styles" 37.11863 msgstr "使用预定义的输出样式" 37.11864 37.11865 #. type: Content of: <book><chapter><sect1><para> 37.11866 -#: ../en/ch11-template.xml:16 37.11867 +#: ../en/ch10-template.xml:16 37.11868 msgid "" 37.11869 "Packaged with Mercurial are some output styles that you can use immediately. " 37.11870 "A style is simply a precanned template that someone wrote and installed " 37.11871 @@ -12589,14 +11674,14 @@ 37.11872 msgstr "" 37.11873 37.11874 #. type: Content of: <book><chapter><sect1><para> 37.11875 -#: ../en/ch11-template.xml:21 37.11876 +#: ../en/ch10-template.xml:21 37.11877 msgid "" 37.11878 "Before we take a look at Mercurial's bundled styles, let's review its normal " 37.11879 "output." 37.11880 msgstr "" 37.11881 37.11882 #. type: Content of: <book><chapter><sect1><para> 37.11883 -#: ../en/ch11-template.xml:26 37.11884 +#: ../en/ch10-template.xml:26 37.11885 msgid "" 37.11886 "This is somewhat informative, but it takes up a lot of space&emdash;five " 37.11887 "lines of output per changeset. The <literal>compact</literal> style reduces " 37.11888 @@ -12604,7 +11689,7 @@ 37.11889 msgstr "" 37.11890 37.11891 #. type: Content of: <book><chapter><sect1><para> 37.11892 -#: ../en/ch11-template.xml:33 37.11893 +#: ../en/ch10-template.xml:33 37.11894 msgid "" 37.11895 "The <literal>changelog</literal> style hints at the expressive power of " 37.11896 "Mercurial's templating engine. This style attempts to follow the GNU " 37.11897 @@ -12612,27 +11697,27 @@ 37.11898 msgstr "" 37.11899 37.11900 #. type: Content of: <book><chapter><sect1><para> 37.11901 -#: ../en/ch11-template.xml:40 37.11902 +#: ../en/ch10-template.xml:40 37.11903 msgid "" 37.11904 "You will not be shocked to learn that Mercurial's default output style is " 37.11905 "named <literal>default</literal>." 37.11906 msgstr "" 37.11907 37.11908 #. type: Content of: <book><chapter><sect1><sect2><title> 37.11909 -#: ../en/ch11-template.xml:44 37.11910 +#: ../en/ch10-template.xml:44 37.11911 msgid "Setting a default style" 37.11912 msgstr "设置默认样式" 37.11913 37.11914 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11915 -#: ../en/ch11-template.xml:46 37.11916 +#: ../en/ch10-template.xml:46 37.11917 msgid "" 37.11918 "You can modify the output style that Mercurial will use for every command by " 37.11919 -"editing your <filename role=\"special\"> /.hgrc</filename>\\ file, naming the " 37.11920 +"editing your <filename role=\"special\">~/.hgrc</filename> file, naming the " 37.11921 "style you would prefer to use." 37.11922 msgstr "" 37.11923 37.11924 #. type: Content of: <book><chapter><sect1><sect2><para> 37.11925 -#: ../en/ch11-template.xml:53 37.11926 +#: ../en/ch10-template.xml:54 37.11927 msgid "" 37.11928 "If you write a style of your own, you can use it by either providing the path " 37.11929 "to your style file, or copying your style file into a location where " 37.11930 @@ -12641,12 +11726,12 @@ 37.11931 msgstr "" 37.11932 37.11933 #. type: Content of: <book><chapter><sect1><title> 37.11934 -#: ../en/ch11-template.xml:62 37.11935 +#: ../en/ch10-template.xml:63 37.11936 msgid "Commands that support styles and templates" 37.11937 msgstr "支持样式和模版的命令" 37.11938 37.11939 #. type: Content of: <book><chapter><sect1><para> 37.11940 -#: ../en/ch11-template.xml:64 37.11941 +#: ../en/ch10-template.xml:65 37.11942 msgid "" 37.11943 "All of Mercurial's <quote><literal>log</literal>-like</quote> commands let " 37.11944 "you use styles and templates: <command role=\"hg-cmd\">hg incoming</command>, " 37.11945 @@ -12655,7 +11740,7 @@ 37.11946 msgstr "" 37.11947 37.11948 #. type: Content of: <book><chapter><sect1><para> 37.11949 -#: ../en/ch11-template.xml:71 37.11950 +#: ../en/ch10-template.xml:72 37.11951 msgid "" 37.11952 "As I write this manual, these are so far the only commands that support " 37.11953 "styles and templates. Since these are the most important commands that need " 37.11954 @@ -12664,12 +11749,12 @@ 37.11955 msgstr "" 37.11956 37.11957 #. type: Content of: <book><chapter><sect1><title> 37.11958 -#: ../en/ch11-template.xml:79 37.11959 +#: ../en/ch10-template.xml:80 37.11960 msgid "The basics of templating" 37.11961 msgstr "模版基础" 37.11962 37.11963 #. type: Content of: <book><chapter><sect1><para> 37.11964 -#: ../en/ch11-template.xml:81 37.11965 +#: ../en/ch10-template.xml:82 37.11966 msgid "" 37.11967 "At its simplest, a Mercurial template is a piece of text. Some of the text " 37.11968 "never changes, while other parts are <emphasis>expanded</emphasis>, or " 37.11969 @@ -12677,20 +11762,20 @@ 37.11970 msgstr "" 37.11971 37.11972 #. type: Content of: <book><chapter><sect1><para> 37.11973 -#: ../en/ch11-template.xml:86 37.11974 +#: ../en/ch10-template.xml:87 37.11975 msgid "" 37.11976 "Before we continue, let's look again at a simple example of Mercurial's " 37.11977 "normal output." 37.11978 msgstr "" 37.11979 37.11980 #. type: Content of: <book><chapter><sect1><para> 37.11981 -#: ../en/ch11-template.xml:91 37.11982 +#: ../en/ch10-template.xml:92 37.11983 msgid "" 37.11984 "Now, let's run the same command, but using a template to change its output." 37.11985 msgstr "" 37.11986 37.11987 #. type: Content of: <book><chapter><sect1><para> 37.11988 -#: ../en/ch11-template.xml:96 37.11989 +#: ../en/ch10-template.xml:97 37.11990 msgid "" 37.11991 "The example above illustrates the simplest possible template; it's just a " 37.11992 "piece of static text, printed once for each changeset. The <option role=\"hg-" 37.11993 @@ -12700,7 +11785,7 @@ 37.11994 msgstr "" 37.11995 37.11996 #. type: Content of: <book><chapter><sect1><para> 37.11997 -#: ../en/ch11-template.xml:104 37.11998 +#: ../en/ch10-template.xml:105 37.11999 msgid "" 37.12000 "Notice that the template string above ends with the text <quote><literal>\\n</" 37.12001 "literal></quote>. This is an <emphasis>escape sequence</emphasis>, telling " 37.12002 @@ -12710,14 +11795,14 @@ 37.12003 msgstr "" 37.12004 37.12005 #. type: Content of: <book><chapter><sect1><para> 37.12006 -#: ../en/ch11-template.xml:112 37.12007 +#: ../en/ch10-template.xml:113 37.12008 msgid "" 37.12009 "A template that prints a fixed string of text all the time isn't very useful; " 37.12010 "let's try something a bit more complex." 37.12011 msgstr "" 37.12012 37.12013 #. type: Content of: <book><chapter><sect1><para> 37.12014 -#: ../en/ch11-template.xml:118 37.12015 +#: ../en/ch10-template.xml:119 37.12016 msgid "" 37.12017 "As you can see, the string <quote><literal>{desc}</literal></quote> in the " 37.12018 "template has been replaced in the output with the description of each " 37.12019 @@ -12729,25 +11814,25 @@ 37.12020 msgstr "" 37.12021 37.12022 #. type: Content of: <book><chapter><sect1><title> 37.12023 -#: ../en/ch11-template.xml:131 37.12024 +#: ../en/ch10-template.xml:132 37.12025 msgid "Common template keywords" 37.12026 msgstr "模版关键字" 37.12027 37.12028 #. type: Content of: <book><chapter><sect1><para> 37.12029 -#: ../en/ch11-template.xml:133 37.12030 +#: ../en/ch10-template.xml:134 37.12031 msgid "" 37.12032 "You can start writing simple templates immediately using the keywords below." 37.12033 msgstr "" 37.12034 37.12035 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12036 -#: ../en/ch11-template.xml:137 37.12037 +#: ../en/ch10-template.xml:138 37.12038 msgid "" 37.12039 "<literal role=\"template-keyword\">author</literal>: String. The unmodified " 37.12040 "author of the changeset." 37.12041 msgstr "" 37.12042 37.12043 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12044 -#: ../en/ch11-template.xml:141 37.12045 +#: ../en/ch10-template.xml:142 37.12046 msgid "" 37.12047 "<literal role=\"template-keyword\">branches</literal>: String. The name of " 37.12048 "the branch on which the changeset was committed. Will be empty if the branch " 37.12049 @@ -12755,7 +11840,7 @@ 37.12050 msgstr "" 37.12051 37.12052 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12053 -#: ../en/ch11-template.xml:147 37.12054 +#: ../en/ch10-template.xml:148 37.12055 msgid "" 37.12056 "<literal role=\"template-keyword\">date</literal>: Date information. The " 37.12057 "date when the changeset was committed. This is <emphasis>not</emphasis> " 37.12058 @@ -12767,70 +11852,70 @@ 37.12059 msgstr "" 37.12060 37.12061 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12062 -#: ../en/ch11-template.xml:158 37.12063 +#: ../en/ch10-template.xml:159 37.12064 msgid "" 37.12065 "<literal role=\"template-keyword\">desc</literal>: String. The text of the " 37.12066 "changeset description." 37.12067 msgstr "" 37.12068 37.12069 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12070 -#: ../en/ch11-template.xml:161 37.12071 +#: ../en/ch10-template.xml:162 37.12072 msgid "" 37.12073 "<literal role=\"template-keyword\">files</literal>: List of strings. All " 37.12074 "files modified, added, or removed by this changeset." 37.12075 msgstr "" 37.12076 37.12077 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12078 -#: ../en/ch11-template.xml:166 37.12079 +#: ../en/ch10-template.xml:167 37.12080 msgid "" 37.12081 "<literal role=\"template-keyword\">file_adds</literal>: List of strings. " 37.12082 "Files added by this changeset." 37.12083 msgstr "" 37.12084 37.12085 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12086 -#: ../en/ch11-template.xml:170 37.12087 +#: ../en/ch10-template.xml:171 37.12088 msgid "" 37.12089 "<literal role=\"template-keyword\">file_dels</literal>: List of strings. " 37.12090 "Files removed by this changeset." 37.12091 msgstr "" 37.12092 37.12093 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12094 -#: ../en/ch11-template.xml:174 37.12095 +#: ../en/ch10-template.xml:175 37.12096 msgid "" 37.12097 "<literal role=\"template-keyword\">node</literal>: String. The changeset " 37.12098 "identification hash, as a 40-character hexadecimal string." 37.12099 msgstr "" 37.12100 37.12101 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12102 -#: ../en/ch11-template.xml:178 37.12103 +#: ../en/ch10-template.xml:179 37.12104 msgid "" 37.12105 "<literal role=\"template-keyword\">parents</literal>: List of strings. The " 37.12106 "parents of the changeset." 37.12107 msgstr "" 37.12108 37.12109 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12110 -#: ../en/ch11-template.xml:182 37.12111 +#: ../en/ch10-template.xml:183 37.12112 msgid "" 37.12113 "<literal role=\"template-keyword\">rev</literal>: Integer. The repository-" 37.12114 "local changeset revision number." 37.12115 msgstr "" 37.12116 37.12117 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12118 -#: ../en/ch11-template.xml:186 37.12119 +#: ../en/ch10-template.xml:187 37.12120 msgid "" 37.12121 "<literal role=\"template-keyword\">tags</literal>: List of strings. Any tags " 37.12122 "associated with the changeset." 37.12123 msgstr "" 37.12124 37.12125 #. type: Content of: <book><chapter><sect1><para> 37.12126 -#: ../en/ch11-template.xml:191 37.12127 +#: ../en/ch10-template.xml:192 37.12128 msgid "" 37.12129 "A few simple experiments will show us what to expect when we use these " 37.12130 "keywords; you can see the results below." 37.12131 msgstr "" 37.12132 37.12133 #. type: Content of: <book><chapter><sect1><para> 37.12134 -#: ../en/ch11-template.xml:196 37.12135 +#: ../en/ch10-template.xml:197 37.12136 msgid "" 37.12137 "As we noted above, the date keyword does not produce human-readable output, " 37.12138 "so we must treat it specially. This involves using a <emphasis>filter</" 37.12139 @@ -12839,12 +11924,12 @@ 37.12140 msgstr "" 37.12141 37.12142 #. type: Content of: <book><chapter><sect1><title> 37.12143 -#: ../en/ch11-template.xml:206 37.12144 +#: ../en/ch10-template.xml:207 37.12145 msgid "Escape sequences" 37.12146 msgstr "转义序列" 37.12147 37.12148 #. type: Content of: <book><chapter><sect1><para> 37.12149 -#: ../en/ch11-template.xml:208 37.12150 +#: ../en/ch10-template.xml:209 37.12151 msgid "" 37.12152 "Mercurial's templating engine recognises the most commonly used escape " 37.12153 "sequences in strings. When it sees a backslash (<quote><literal>\\</" 37.12154 @@ -12853,48 +11938,48 @@ 37.12155 msgstr "" 37.12156 37.12157 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12158 -#: ../en/ch11-template.xml:215 37.12159 -msgid "" 37.12160 -"<literal>\\textbackslash\\textbackslash</literal>: Backslash, <quote><literal>" 37.12161 -"\\</literal></quote>, ASCII 134." 37.12162 +#: ../en/ch10-template.xml:216 37.12163 +msgid "" 37.12164 +"<literal>\\</literal>: Backslash, <quote><literal>\\</literal></quote>, ASCII " 37.12165 +"134." 37.12166 msgstr "" 37.12167 37.12168 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12169 -#: ../en/ch11-template.xml:219 37.12170 -msgid "<literal>\\textbackslash n</literal>: Newline, ASCII 12." 37.12171 +#: ../en/ch10-template.xml:220 37.12172 +msgid "<literal>\\n</literal>: Newline, ASCII 12." 37.12173 msgstr "" 37.12174 37.12175 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12176 -#: ../en/ch11-template.xml:222 37.12177 -msgid "<literal>\\textbackslash r</literal>: Carriage return, ASCII 15." 37.12178 +#: ../en/ch10-template.xml:223 37.12179 +msgid "<literal>\\r</literal>: Carriage return, ASCII 15." 37.12180 msgstr "" 37.12181 37.12182 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12183 -#: ../en/ch11-template.xml:225 37.12184 -msgid "<literal>\\textbackslash t</literal>: Tab, ASCII 11." 37.12185 +#: ../en/ch10-template.xml:226 37.12186 +msgid "<literal>\\t</literal>: Tab, ASCII 11." 37.12187 msgstr "" 37.12188 37.12189 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12190 -#: ../en/ch11-template.xml:228 37.12191 -msgid "<literal>\\textbackslash v</literal>: Vertical tab, ASCII 13." 37.12192 +#: ../en/ch10-template.xml:229 37.12193 +msgid "<literal>\\v</literal>: Vertical tab, ASCII 13." 37.12194 msgstr "" 37.12195 37.12196 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12197 -#: ../en/ch11-template.xml:231 37.12198 -msgid "" 37.12199 -"<literal>\\textbackslash {</literal>: Open curly brace, <quote><literal>{</" 37.12200 -"literal></quote>, ASCII 173." 37.12201 +#: ../en/ch10-template.xml:232 37.12202 +msgid "" 37.12203 +"<literal>{</literal>: Open curly brace, <quote><literal>{</literal></quote>, " 37.12204 +"ASCII 173." 37.12205 msgstr "" 37.12206 37.12207 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12208 -#: ../en/ch11-template.xml:235 37.12209 -msgid "" 37.12210 -"<literal>\\textbackslash }</literal>: Close curly brace, <quote><literal>}</" 37.12211 -"literal></quote>, ASCII 175." 37.12212 -msgstr "" 37.12213 - 37.12214 -#. type: Content of: <book><chapter><sect1><para> 37.12215 -#: ../en/ch11-template.xml:240 37.12216 +#: ../en/ch10-template.xml:236 37.12217 +msgid "" 37.12218 +"<literal>}</literal>: Close curly brace, <quote><literal>}</literal></quote>, " 37.12219 +"ASCII 175." 37.12220 +msgstr "" 37.12221 + 37.12222 +#. type: Content of: <book><chapter><sect1><para> 37.12223 +#: ../en/ch10-template.xml:241 37.12224 msgid "" 37.12225 "As indicated above, if you want the expansion of a template to contain a " 37.12226 "literal <quote><literal>\\</literal></quote>, <quote><literal>{</literal></" 37.12227 @@ -12902,12 +11987,12 @@ 37.12228 msgstr "" 37.12229 37.12230 #. type: Content of: <book><chapter><sect1><title> 37.12231 -#: ../en/ch11-template.xml:248 37.12232 +#: ../en/ch10-template.xml:249 37.12233 msgid "Filtering keywords to change their results" 37.12234 msgstr "通过过滤关键字来修改输出结果" 37.12235 37.12236 #. type: Content of: <book><chapter><sect1><para> 37.12237 -#: ../en/ch11-template.xml:250 37.12238 +#: ../en/ch10-template.xml:251 37.12239 msgid "" 37.12240 "Some of the results of template expansion are not immediately easy to use. " 37.12241 "Mercurial lets you specify an optional chain of <emphasis>filters</emphasis> " 37.12242 @@ -12917,7 +12002,7 @@ 37.12243 msgstr "" 37.12244 37.12245 #. type: Content of: <book><chapter><sect1><para> 37.12246 -#: ../en/ch11-template.xml:257 37.12247 +#: ../en/ch10-template.xml:258 37.12248 msgid "" 37.12249 "Below is a list of the most commonly used filters that Mercurial supports. " 37.12250 "While some filters can be applied to any text, others can only be used in " 37.12251 @@ -12926,7 +12011,7 @@ 37.12252 msgstr "" 37.12253 37.12254 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12255 -#: ../en/ch11-template.xml:264 37.12256 +#: ../en/ch10-template.xml:265 37.12257 msgid "" 37.12258 "<literal role=\"template-filter\">addbreaks</literal>: Any text. Add an XHTML " 37.12259 "<quote><literal><br/></literal></quote> tag before the end of every " 37.12260 @@ -12935,7 +12020,7 @@ 37.12261 msgstr "" 37.12262 37.12263 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12264 -#: ../en/ch11-template.xml:271 37.12265 +#: ../en/ch10-template.xml:272 37.12266 msgid "" 37.12267 "<literal role=\"template-kw-filt-date\">age</literal>: <literal role=" 37.12268 "\"template-keyword\">date</literal> keyword. Render the age of the date, " 37.12269 @@ -12944,7 +12029,7 @@ 37.12270 msgstr "" 37.12271 37.12272 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12273 -#: ../en/ch11-template.xml:278 37.12274 +#: ../en/ch10-template.xml:279 37.12275 msgid "" 37.12276 "<literal role=\"template-filter\">basename</literal>: Any text, but most " 37.12277 "useful for the <literal role=\"template-keyword\">files</literal> keyword and " 37.12278 @@ -12954,7 +12039,7 @@ 37.12279 msgstr "" 37.12280 37.12281 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12282 -#: ../en/ch11-template.xml:287 37.12283 +#: ../en/ch10-template.xml:288 37.12284 msgid "" 37.12285 "<literal role=\"template-kw-filt-date\">date</literal>: <literal role=" 37.12286 "\"template-keyword\">date</literal> keyword. Render a date in a similar " 37.12287 @@ -12964,7 +12049,7 @@ 37.12288 msgstr "" 37.12289 37.12290 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12291 -#: ../en/ch11-template.xml:295 37.12292 +#: ../en/ch10-template.xml:296 37.12293 msgid "" 37.12294 "<literal role=\"template-kw-filt-author\">domain</literal>: Any text, but " 37.12295 "most useful for the <literal role=\"template-keyword\">author</literal> " 37.12296 @@ -12975,7 +12060,7 @@ 37.12297 msgstr "" 37.12298 37.12299 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12300 -#: ../en/ch11-template.xml:305 37.12301 +#: ../en/ch10-template.xml:306 37.12302 msgid "" 37.12303 "<literal role=\"template-kw-filt-author\">email</literal>: Any text, but most " 37.12304 "useful for the <literal role=\"template-keyword\">author</literal> keyword. " 37.12305 @@ -12985,7 +12070,7 @@ 37.12306 msgstr "" 37.12307 37.12308 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12309 -#: ../en/ch11-template.xml:314 37.12310 +#: ../en/ch10-template.xml:315 37.12311 msgid "" 37.12312 "<literal role=\"template-filter\">escape</literal>: Any text. Replace the " 37.12313 "special XML/XHTML characters <quote><literal>&</literal></quote>, " 37.12314 @@ -12994,7 +12079,7 @@ 37.12315 msgstr "" 37.12316 37.12317 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12318 -#: ../en/ch11-template.xml:322 37.12319 +#: ../en/ch10-template.xml:323 37.12320 msgid "" 37.12321 "<literal role=\"template-filter\">fill68</literal>: Any text. Wrap the text " 37.12322 "to fit in 68 columns. This is useful before you pass text through the " 37.12323 @@ -13003,21 +12088,21 @@ 37.12324 msgstr "" 37.12325 37.12326 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12327 -#: ../en/ch11-template.xml:330 37.12328 +#: ../en/ch10-template.xml:331 37.12329 msgid "" 37.12330 "<literal role=\"template-filter\">fill76</literal>: Any text. Wrap the text " 37.12331 "to fit in 76 columns." 37.12332 msgstr "" 37.12333 37.12334 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12335 -#: ../en/ch11-template.xml:334 37.12336 +#: ../en/ch10-template.xml:335 37.12337 msgid "" 37.12338 "<literal role=\"template-filter\">firstline</literal>: Any text. Yield the " 37.12339 "first line of text, without any trailing newlines." 37.12340 msgstr "" 37.12341 37.12342 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12343 -#: ../en/ch11-template.xml:339 37.12344 +#: ../en/ch10-template.xml:340 37.12345 msgid "" 37.12346 "<literal role=\"template-kw-filt-date\">hgdate</literal>: <literal role=" 37.12347 "\"template-keyword\">date</literal> keyword. Render the date as a pair of " 37.12348 @@ -13026,7 +12111,7 @@ 37.12349 msgstr "" 37.12350 37.12351 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12352 -#: ../en/ch11-template.xml:346 37.12353 +#: ../en/ch10-template.xml:347 37.12354 msgid "" 37.12355 "<literal role=\"template-kw-filt-date\">isodate</literal>: <literal role=" 37.12356 "\"template-keyword\">date</literal> keyword. Render the date as a text " 37.12357 @@ -13035,7 +12120,7 @@ 37.12358 msgstr "" 37.12359 37.12360 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12361 -#: ../en/ch11-template.xml:353 37.12362 +#: ../en/ch10-template.xml:354 37.12363 msgid "" 37.12364 "<literal role=\"template-filter\">obfuscate</literal>: Any text, but most " 37.12365 "useful for the <literal role=\"template-keyword\">author</literal> keyword. " 37.12366 @@ -13044,7 +12129,7 @@ 37.12367 msgstr "" 37.12368 37.12369 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12370 -#: ../en/ch11-template.xml:361 37.12371 +#: ../en/ch10-template.xml:362 37.12372 msgid "" 37.12373 "<literal role=\"template-kw-filt-author\">person</literal>: Any text, but " 37.12374 "most useful for the <literal role=\"template-keyword\">author</literal> " 37.12375 @@ -13054,7 +12139,7 @@ 37.12376 msgstr "" 37.12377 37.12378 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12379 -#: ../en/ch11-template.xml:370 37.12380 +#: ../en/ch10-template.xml:371 37.12381 msgid "" 37.12382 "<literal role=\"template-kw-filt-date\">rfc822date</literal>: <literal role=" 37.12383 "\"template-keyword\">date</literal> keyword. Render a date using the same " 37.12384 @@ -13063,7 +12148,7 @@ 37.12385 msgstr "" 37.12386 37.12387 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12388 -#: ../en/ch11-template.xml:377 37.12389 +#: ../en/ch10-template.xml:378 37.12390 msgid "" 37.12391 "<literal role=\"template-kw-filt-node\">short</literal>: Changeset hash. " 37.12392 "Yield the short form of a changeset hash, i.e. a 12-character hexadecimal " 37.12393 @@ -13071,7 +12156,7 @@ 37.12394 msgstr "" 37.12395 37.12396 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12397 -#: ../en/ch11-template.xml:382 37.12398 +#: ../en/ch10-template.xml:383 37.12399 msgid "" 37.12400 "<literal role=\"template-kw-filt-date\">shortdate</literal>: <literal role=" 37.12401 "\"template-keyword\">date</literal> keyword. Render the year, month, and day " 37.12402 @@ -13080,21 +12165,21 @@ 37.12403 msgstr "" 37.12404 37.12405 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12406 -#: ../en/ch11-template.xml:388 37.12407 +#: ../en/ch10-template.xml:389 37.12408 msgid "" 37.12409 "<literal role=\"template-filter\">strip</literal>: Any text. Strip all " 37.12410 "leading and trailing whitespace from the string." 37.12411 msgstr "" 37.12412 37.12413 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12414 -#: ../en/ch11-template.xml:392 37.12415 +#: ../en/ch10-template.xml:393 37.12416 msgid "" 37.12417 "<literal role=\"template-filter\">tabindent</literal>: Any text. Yield the " 37.12418 "text, with every line except the first starting with a tab character." 37.12419 msgstr "" 37.12420 37.12421 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12422 -#: ../en/ch11-template.xml:397 37.12423 +#: ../en/ch10-template.xml:398 37.12424 msgid "" 37.12425 "<literal role=\"template-filter\">urlescape</literal>: Any text. Escape all " 37.12426 "characters that are considered <quote>special</quote> by URL parsers. For " 37.12427 @@ -13102,7 +12187,7 @@ 37.12428 msgstr "" 37.12429 37.12430 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.12431 -#: ../en/ch11-template.xml:404 37.12432 +#: ../en/ch10-template.xml:405 37.12433 msgid "" 37.12434 "<literal role=\"template-kw-filt-author\">user</literal>: Any text, but most " 37.12435 "useful for the <literal role=\"template-keyword\">author</literal> keyword. " 37.12436 @@ -13112,7 +12197,7 @@ 37.12437 msgstr "" 37.12438 37.12439 #. type: Content of: <book><chapter><sect1><note><para> 37.12440 -#: ../en/ch11-template.xml:417 37.12441 +#: ../en/ch10-template.xml:418 37.12442 msgid "" 37.12443 "If you try to apply a filter to a piece of data that it cannot process, " 37.12444 "Mercurial will fail and print a Python exception. For example, trying to run " 37.12445 @@ -13122,12 +12207,12 @@ 37.12446 msgstr "" 37.12447 37.12448 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12449 -#: ../en/ch11-template.xml:426 37.12450 +#: ../en/ch10-template.xml:427 37.12451 msgid "Combining filters" 37.12452 msgstr "组合过滤器" 37.12453 37.12454 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12455 -#: ../en/ch11-template.xml:428 37.12456 +#: ../en/ch10-template.xml:429 37.12457 msgid "" 37.12458 "It is easy to combine filters to yield output in the form you would like. " 37.12459 "The following chain of filters tidies up a description, then makes sure that " 37.12460 @@ -13137,7 +12222,7 @@ 37.12461 msgstr "" 37.12462 37.12463 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12464 -#: ../en/ch11-template.xml:437 37.12465 +#: ../en/ch10-template.xml:438 37.12466 msgid "" 37.12467 "Note the use of <quote><literal>\\t</literal></quote> (a tab character) in " 37.12468 "the template to force the first line to be indented; this is necessary since " 37.12469 @@ -13146,7 +12231,7 @@ 37.12470 msgstr "" 37.12471 37.12472 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12473 -#: ../en/ch11-template.xml:443 37.12474 +#: ../en/ch10-template.xml:444 37.12475 msgid "" 37.12476 "Keep in mind that the order of filters in a chain is significant. The first " 37.12477 "filter is applied to the result of the keyword; the second to the result of " 37.12478 @@ -13156,12 +12241,12 @@ 37.12479 msgstr "" 37.12480 37.12481 #. type: Content of: <book><chapter><sect1><title> 37.12482 -#: ../en/ch11-template.xml:454 37.12483 +#: ../en/ch10-template.xml:455 37.12484 msgid "From templates to styles" 37.12485 msgstr "从模版到样式" 37.12486 37.12487 #. type: Content of: <book><chapter><sect1><para> 37.12488 -#: ../en/ch11-template.xml:456 37.12489 +#: ../en/ch10-template.xml:457 37.12490 msgid "" 37.12491 "A command line template provides a quick and simple way to format some " 37.12492 "output. Templates can become verbose, though, and it's useful to be able to " 37.12493 @@ -13170,7 +12255,7 @@ 37.12494 msgstr "" 37.12495 37.12496 #. type: Content of: <book><chapter><sect1><para> 37.12497 -#: ../en/ch11-template.xml:461 37.12498 +#: ../en/ch10-template.xml:462 37.12499 msgid "" 37.12500 "More than that, using a style file unlocks the power of Mercurial's " 37.12501 "templating engine in ways that are not possible using the command line " 37.12502 @@ -13178,49 +12263,49 @@ 37.12503 msgstr "" 37.12504 37.12505 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12506 -#: ../en/ch11-template.xml:467 37.12507 +#: ../en/ch10-template.xml:468 37.12508 msgid "The simplest of style files" 37.12509 msgstr "最简单的样式文件" 37.12510 37.12511 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12512 -#: ../en/ch11-template.xml:469 37.12513 +#: ../en/ch10-template.xml:470 37.12514 msgid "Our simple style file contains just one line:" 37.12515 msgstr "" 37.12516 37.12517 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12518 -#: ../en/ch11-template.xml:473 37.12519 +#: ../en/ch10-template.xml:474 37.12520 msgid "" 37.12521 "This tells Mercurial, <quote>if you're printing a changeset, use the text on " 37.12522 "the right as the template</quote>." 37.12523 msgstr "" 37.12524 37.12525 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12526 -#: ../en/ch11-template.xml:479 37.12527 +#: ../en/ch10-template.xml:480 37.12528 msgid "Style file syntax" 37.12529 msgstr "样式文件语法" 37.12530 37.12531 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12532 -#: ../en/ch11-template.xml:481 37.12533 +#: ../en/ch10-template.xml:482 37.12534 msgid "The syntax rules for a style file are simple." 37.12535 msgstr "" 37.12536 37.12537 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12538 -#: ../en/ch11-template.xml:484 37.12539 +#: ../en/ch10-template.xml:485 37.12540 msgid "The file is processed one line at a time." 37.12541 msgstr "" 37.12542 37.12543 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12544 -#: ../en/ch11-template.xml:487 37.12545 +#: ../en/ch10-template.xml:488 37.12546 msgid "Leading and trailing white space are ignored." 37.12547 msgstr "" 37.12548 37.12549 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12550 -#: ../en/ch11-template.xml:490 37.12551 +#: ../en/ch10-template.xml:491 37.12552 msgid "Empty lines are skipped." 37.12553 msgstr "" 37.12554 37.12555 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12556 -#: ../en/ch11-template.xml:492 37.12557 +#: ../en/ch10-template.xml:493 37.12558 msgid "" 37.12559 "If a line starts with either of the characters <quote><literal>#</literal></" 37.12560 "quote> or <quote><literal>;</literal></quote>, the entire line is treated as " 37.12561 @@ -13228,7 +12313,7 @@ 37.12562 msgstr "" 37.12563 37.12564 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12565 -#: ../en/ch11-template.xml:497 37.12566 +#: ../en/ch10-template.xml:498 37.12567 msgid "" 37.12568 "A line starts with a keyword. This must start with an alphabetic character " 37.12569 "or underscore, and can subsequently contain any alphanumeric character or " 37.12570 @@ -13237,21 +12322,21 @@ 37.12571 msgstr "" 37.12572 37.12573 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12574 -#: ../en/ch11-template.xml:503 37.12575 +#: ../en/ch10-template.xml:504 37.12576 msgid "" 37.12577 "The next element must be an <quote><literal>=</literal></quote> character, " 37.12578 "which can be preceded or followed by an arbitrary amount of white space." 37.12579 msgstr "" 37.12580 37.12581 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12582 -#: ../en/ch11-template.xml:508 37.12583 +#: ../en/ch10-template.xml:509 37.12584 msgid "" 37.12585 "If the rest of the line starts and ends with matching quote characters " 37.12586 "(either single or double quote), it is treated as a template body." 37.12587 msgstr "" 37.12588 37.12589 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12590 -#: ../en/ch11-template.xml:512 37.12591 +#: ../en/ch10-template.xml:513 37.12592 msgid "" 37.12593 "If the rest of the line <emphasis>does not</emphasis> start with a quote " 37.12594 "character, it is treated as the name of a file; the contents of this file " 37.12595 @@ -13259,12 +12344,12 @@ 37.12596 msgstr "" 37.12597 37.12598 #. type: Content of: <book><chapter><sect1><title> 37.12599 -#: ../en/ch11-template.xml:521 37.12600 +#: ../en/ch10-template.xml:522 37.12601 msgid "Style files by example" 37.12602 msgstr "样式文件例子" 37.12603 37.12604 #. type: Content of: <book><chapter><sect1><para> 37.12605 -#: ../en/ch11-template.xml:523 37.12606 +#: ../en/ch10-template.xml:524 37.12607 msgid "" 37.12608 "To illustrate how to write a style file, we will construct a few by example. " 37.12609 "Rather than provide a complete style file and walk through it, we'll mirror " 37.12610 @@ -13273,12 +12358,12 @@ 37.12611 msgstr "" 37.12612 37.12613 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12614 -#: ../en/ch11-template.xml:530 37.12615 +#: ../en/ch10-template.xml:531 37.12616 msgid "Identifying mistakes in style files" 37.12617 msgstr "在样式文件中定位错误" 37.12618 37.12619 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12620 -#: ../en/ch11-template.xml:532 37.12621 +#: ../en/ch10-template.xml:533 37.12622 msgid "" 37.12623 "If Mercurial encounters a problem in a style file you are working on, it " 37.12624 "prints a terse error message that, once you figure out what it means, is " 37.12625 @@ -13286,7 +12371,7 @@ 37.12626 msgstr "" 37.12627 37.12628 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12629 -#: ../en/ch11-template.xml:538 37.12630 +#: ../en/ch10-template.xml:539 37.12631 msgid "" 37.12632 "Notice that <filename>broken.style</filename> attempts to define a " 37.12633 "<literal>changeset</literal> keyword, but forgets to give any content for it. " 37.12634 @@ -13294,35 +12379,35 @@ 37.12635 msgstr "" 37.12636 37.12637 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12638 -#: ../en/ch11-template.xml:545 37.12639 +#: ../en/ch10-template.xml:546 37.12640 msgid "This error message looks intimidating, but it is not too hard to follow." 37.12641 msgstr "" 37.12642 37.12643 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12644 -#: ../en/ch11-template.xml:549 37.12645 +#: ../en/ch10-template.xml:550 37.12646 msgid "" 37.12647 "The first component is simply Mercurial's way of saying <quote>I am giving " 37.12648 "up</quote>." 37.12649 msgstr "" 37.12650 37.12651 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12652 -#: ../en/ch11-template.xml:554 37.12653 +#: ../en/ch10-template.xml:554 37.12654 msgid "Next comes the name of the style file that contains the error." 37.12655 msgstr "" 37.12656 37.12657 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12658 -#: ../en/ch11-template.xml:560 37.12659 +#: ../en/ch10-template.xml:558 37.12660 msgid "" 37.12661 "Following the file name is the line number where the error was encountered." 37.12662 msgstr "" 37.12663 37.12664 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12665 -#: ../en/ch11-template.xml:565 37.12666 +#: ../en/ch10-template.xml:562 37.12667 msgid "Finally, a description of what went wrong." 37.12668 msgstr "" 37.12669 37.12670 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12671 -#: ../en/ch11-template.xml:570 37.12672 +#: ../en/ch10-template.xml:566 37.12673 msgid "" 37.12674 "The description of the problem is not always clear (as in this case), but " 37.12675 "even when it is cryptic, it is almost always trivial to visually inspect the " 37.12676 @@ -13330,12 +12415,12 @@ 37.12677 msgstr "" 37.12678 37.12679 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12680 -#: ../en/ch11-template.xml:578 37.12681 +#: ../en/ch10-template.xml:574 37.12682 msgid "Uniquely identifying a repository" 37.12683 msgstr "版本库的唯一标识" 37.12684 37.12685 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12686 -#: ../en/ch11-template.xml:580 37.12687 +#: ../en/ch10-template.xml:576 37.12688 msgid "" 37.12689 "If you would like to be able to identify a Mercurial repository <quote>fairly " 37.12690 "uniquely</quote> using a short string as an identifier, you can use the first " 37.12691 @@ -13343,21 +12428,21 @@ 37.12692 msgstr "" 37.12693 37.12694 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12695 -#: ../en/ch11-template.xml:587 37.12696 +#: ../en/ch10-template.xml:583 37.12697 msgid "" 37.12698 "This is not guaranteed to be unique, but it is nevertheless useful in many " 37.12699 "cases." 37.12700 msgstr "" 37.12701 37.12702 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12703 -#: ../en/ch11-template.xml:590 37.12704 +#: ../en/ch10-template.xml:586 37.12705 msgid "" 37.12706 "It will not work in a completely empty repository, because such a repository " 37.12707 "does not have a revision zero." 37.12708 msgstr "" 37.12709 37.12710 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12711 -#: ../en/ch11-template.xml:594 37.12712 +#: ../en/ch10-template.xml:590 37.12713 msgid "" 37.12714 "Neither will it work in the (extremely rare) case where a repository is a " 37.12715 "merge of two or more formerly independent repositories, and you still have " 37.12716 @@ -13365,18 +12450,18 @@ 37.12717 msgstr "" 37.12718 37.12719 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12720 -#: ../en/ch11-template.xml:599 37.12721 +#: ../en/ch10-template.xml:595 37.12722 msgid "Here are some uses to which you could put this identifier:" 37.12723 msgstr "" 37.12724 37.12725 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12726 -#: ../en/ch11-template.xml:602 37.12727 +#: ../en/ch10-template.xml:598 37.12728 msgid "" 37.12729 "As a key into a table for a database that manages repositories on a server." 37.12730 msgstr "" 37.12731 37.12732 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12733 -#: ../en/ch11-template.xml:605 37.12734 +#: ../en/ch10-template.xml:601 37.12735 msgid "" 37.12736 "As half of a {<emphasis>repository ID</emphasis>, <emphasis>revision ID</" 37.12737 "emphasis>} tuple. Save this information away when you run an automated build " 37.12738 @@ -13385,13 +12470,13 @@ 37.12739 msgstr "" 37.12740 37.12741 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12742 -#: ../en/ch11-template.xml:614 37.12743 +#: ../en/ch10-template.xml:610 37.12744 msgid "Mimicking Subversion's output" 37.12745 msgstr "模仿 Subversion 的输出" 37.12746 37.12747 # 37.12748 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12749 -#: ../en/ch11-template.xml:616 37.12750 +#: ../en/ch10-template.xml:612 37.12751 msgid "" 37.12752 "Let's try to emulate the default output format used by another revision " 37.12753 "control tool, Subversion." 37.12754 @@ -13399,7 +12484,7 @@ 37.12755 37.12756 # 37.12757 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12758 -#: ../en/ch11-template.xml:621 37.12759 +#: ../en/ch10-template.xml:617 37.12760 msgid "" 37.12761 "Since Subversion's output style is fairly simple, it is easy to copy-and-" 37.12762 "paste a hunk of its output into a file, and replace the text produced above " 37.12763 @@ -13407,14 +12492,14 @@ 37.12764 msgstr "" 37.12765 37.12766 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12767 -#: ../en/ch11-template.xml:628 37.12768 +#: ../en/ch10-template.xml:624 37.12769 msgid "" 37.12770 "There are a few small ways in which this template deviates from the output " 37.12771 "produced by Subversion." 37.12772 msgstr "" 37.12773 37.12774 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12775 -#: ../en/ch11-template.xml:631 37.12776 +#: ../en/ch10-template.xml:627 37.12777 msgid "" 37.12778 "Subversion prints a <quote>readable</quote> date (the <quote><literal>Wed, 27 " 37.12779 "Sep 2006</literal></quote> in the example output above) in parentheses. " 37.12780 @@ -13423,7 +12508,7 @@ 37.12781 msgstr "" 37.12782 37.12783 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12784 -#: ../en/ch11-template.xml:638 37.12785 +#: ../en/ch10-template.xml:634 37.12786 msgid "" 37.12787 "We emulate Subversion's printing of <quote>separator</quote> lines full of " 37.12788 "<quote><literal>-</literal></quote> characters by ending the template with " 37.12789 @@ -13433,7 +12518,7 @@ 37.12790 msgstr "" 37.12791 37.12792 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.12793 -#: ../en/ch11-template.xml:647 37.12794 +#: ../en/ch10-template.xml:643 37.12795 msgid "" 37.12796 "Subversion's output includes a count in the header of the number of lines in " 37.12797 "the commit message. We cannot replicate this in Mercurial; the templating " 37.12798 @@ -13443,7 +12528,7 @@ 37.12799 37.12800 # 37.12801 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12802 -#: ../en/ch11-template.xml:653 37.12803 +#: ../en/ch10-template.xml:649 37.12804 msgid "" 37.12805 "It took me no more than a minute or two of work to replace literal text from " 37.12806 "an example of Subversion's output with some keywords and filters to give the " 37.12807 @@ -13451,7 +12536,7 @@ 37.12808 msgstr "" 37.12809 37.12810 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12811 -#: ../en/ch11-template.xml:660 37.12812 +#: ../en/ch10-template.xml:656 37.12813 msgid "" 37.12814 "We could have included the text of the template file directly in the style " 37.12815 "file by enclosing it in quotes and replacing the newlines with " 37.12816 @@ -13464,17 +12549,17 @@ 37.12817 msgstr "" 37.12818 37.12819 #. type: Content of: <book><chapter><title> 37.12820 -#: ../en/ch12-mq.xml:5 37.12821 +#: ../en/ch11-mq.xml:5 37.12822 msgid "Managing change with Mercurial Queues" 37.12823 msgstr "使用 MQ 管理修改" 37.12824 37.12825 #. type: Content of: <book><chapter><sect1><title> 37.12826 -#: ../en/ch12-mq.xml:8 37.12827 +#: ../en/ch11-mq.xml:8 37.12828 msgid "The patch management problem" 37.12829 msgstr "补丁的管理问题" 37.12830 37.12831 #. type: Content of: <book><chapter><sect1><para> 37.12832 -#: ../en/ch12-mq.xml:10 37.12833 +#: ../en/ch11-mq.xml:10 37.12834 msgid "" 37.12835 "Here is a common scenario: you need to install a software package from " 37.12836 "source, but you find a bug that you must fix in the source before you can " 37.12837 @@ -13486,7 +12571,7 @@ 37.12838 msgstr "" 37.12839 37.12840 #. type: Content of: <book><chapter><sect1><para> 37.12841 -#: ../en/ch12-mq.xml:20 37.12842 +#: ../en/ch11-mq.xml:20 37.12843 msgid "" 37.12844 "This is a simple case of the <quote>patch management</quote> problem. You " 37.12845 "have an <quote>upstream</quote> source tree that you can't change; you need " 37.12846 @@ -13496,7 +12581,7 @@ 37.12847 msgstr "" 37.12848 37.12849 #. type: Content of: <book><chapter><sect1><para> 37.12850 -#: ../en/ch12-mq.xml:27 37.12851 +#: ../en/ch11-mq.xml:27 37.12852 msgid "" 37.12853 "The patch management problem arises in many situations. Probably the most " 37.12854 "visible is that a user of an open source software project will contribute a " 37.12855 @@ -13504,7 +12589,7 @@ 37.12856 msgstr "" 37.12857 37.12858 #. type: Content of: <book><chapter><sect1><para> 37.12859 -#: ../en/ch12-mq.xml:32 37.12860 +#: ../en/ch11-mq.xml:32 37.12861 msgid "" 37.12862 "Distributors of operating systems that include open source software often " 37.12863 "need to make changes to the packages they distribute so that they will build " 37.12864 @@ -13512,7 +12597,7 @@ 37.12865 msgstr "" 37.12866 37.12867 #. type: Content of: <book><chapter><sect1><para> 37.12868 -#: ../en/ch12-mq.xml:37 37.12869 +#: ../en/ch11-mq.xml:37 37.12870 msgid "" 37.12871 "When you have few changes to maintain, it is easy to manage a single patch " 37.12872 "using the standard <command>diff</command> and <command>patch</command> " 37.12873 @@ -13529,7 +12614,7 @@ 37.12874 msgstr "" 37.12875 37.12876 #. type: Content of: <book><chapter><sect1><para> 37.12877 -#: ../en/ch12-mq.xml:52 37.12878 +#: ../en/ch11-mq.xml:52 37.12879 msgid "" 37.12880 "Maintaining a single patch against an upstream tree is a little tedious and " 37.12881 "error-prone, but not difficult. However, the complexity of the problem grows " 37.12882 @@ -13539,7 +12624,7 @@ 37.12883 msgstr "" 37.12884 37.12885 #. type: Content of: <book><chapter><sect1><para> 37.12886 -#: ../en/ch12-mq.xml:59 37.12887 +#: ../en/ch11-mq.xml:59 37.12888 msgid "" 37.12889 "Fortunately, Mercurial includes a powerful extension, Mercurial Queues (or " 37.12890 "simply <quote>MQ</quote>), that massively simplifies the patch management " 37.12891 @@ -13547,12 +12632,12 @@ 37.12892 msgstr "" 37.12893 37.12894 #. type: Content of: <book><chapter><sect1><title> 37.12895 -#: ../en/ch12-mq.xml:65 37.12896 +#: ../en/ch11-mq.xml:65 37.12897 msgid "The prehistory of Mercurial Queues" 37.12898 msgstr "MQ 的历史" 37.12899 37.12900 #. type: Content of: <book><chapter><sect1><para> 37.12901 -#: ../en/ch12-mq.xml:67 37.12902 +#: ../en/ch11-mq.xml:67 37.12903 msgid "" 37.12904 "During the late 1990s, several Linux kernel developers started to maintain " 37.12905 "<quote>patch series</quote> that modified the behaviour of the Linux kernel. " 37.12906 @@ -13561,7 +12646,7 @@ 37.12907 msgstr "" 37.12908 37.12909 #. type: Content of: <book><chapter><sect1><para> 37.12910 -#: ../en/ch12-mq.xml:73 37.12911 +#: ../en/ch11-mq.xml:73 37.12912 msgid "" 37.12913 "The sizes of these patch series grew rapidly. In 2002, Andrew Morton " 37.12914 "published some shell scripts he had been using to automate the task of " 37.12915 @@ -13570,12 +12655,12 @@ 37.12916 msgstr "" 37.12917 37.12918 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12919 -#: ../en/ch12-mq.xml:80 37.12920 +#: ../en/ch11-mq.xml:80 37.12921 msgid "A patchwork quilt" 37.12922 msgstr "" 37.12923 37.12924 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12925 -#: ../en/ch12-mq.xml:82 37.12926 +#: ../en/ch11-mq.xml:82 37.12927 msgid "" 37.12928 "In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the approach " 37.12929 "of Andrew's scripts and published a tool called <quote>patchwork quilt</" 37.12930 @@ -13586,7 +12671,7 @@ 37.12931 msgstr "" 37.12932 37.12933 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12934 -#: ../en/ch12-mq.xml:91 37.12935 +#: ../en/ch11-mq.xml:91 37.12936 msgid "" 37.12937 "Quilt manages a <emphasis>stack of patches</emphasis> on top of a directory " 37.12938 "tree. To begin, you tell quilt to manage a directory tree, and tell it which " 37.12939 @@ -13596,7 +12681,7 @@ 37.12940 msgstr "" 37.12941 37.12942 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12943 -#: ../en/ch12-mq.xml:99 37.12944 +#: ../en/ch11-mq.xml:99 37.12945 msgid "" 37.12946 "The refresh step causes quilt to scan the directory tree; it updates the " 37.12947 "patch with all of the changes you have made. You can create another patch on " 37.12948 @@ -13606,7 +12691,7 @@ 37.12949 msgstr "" 37.12950 37.12951 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12952 -#: ../en/ch12-mq.xml:106 37.12953 +#: ../en/ch11-mq.xml:106 37.12954 msgid "" 37.12955 "You can <emphasis>change</emphasis> which patches are applied to the tree. " 37.12956 "If you <quote>pop</quote> a patch, the changes made by that patch will vanish " 37.12957 @@ -13620,19 +12705,19 @@ 37.12958 msgstr "" 37.12959 37.12960 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12961 -#: ../en/ch12-mq.xml:118 37.12962 +#: ../en/ch11-mq.xml:118 37.12963 msgid "" 37.12964 "Quilt knows nothing about revision control tools, so it works equally well on " 37.12965 "top of an unpacked tarball or a Subversion working copy." 37.12966 msgstr "" 37.12967 37.12968 #. type: Content of: <book><chapter><sect1><sect2><title> 37.12969 -#: ../en/ch12-mq.xml:124 37.12970 +#: ../en/ch11-mq.xml:124 37.12971 msgid "From patchwork quilt to Mercurial Queues" 37.12972 msgstr "从 patchwork quilt 到 MQ" 37.12973 37.12974 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12975 -#: ../en/ch12-mq.xml:126 37.12976 +#: ../en/ch11-mq.xml:126 37.12977 msgid "" 37.12978 "In mid-2005, Chris Mason took the features of quilt and wrote an extension " 37.12979 "that he called Mercurial Queues, which added quilt-like behaviour to " 37.12980 @@ -13640,7 +12725,7 @@ 37.12981 msgstr "" 37.12982 37.12983 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12984 -#: ../en/ch12-mq.xml:130 37.12985 +#: ../en/ch11-mq.xml:130 37.12986 msgid "" 37.12987 "The key difference between quilt and MQ is that quilt knows nothing about " 37.12988 "revision control systems, while MQ is <emphasis>integrated</emphasis> into " 37.12989 @@ -13649,7 +12734,7 @@ 37.12990 msgstr "" 37.12991 37.12992 #. type: Content of: <book><chapter><sect1><sect2><para> 37.12993 -#: ../en/ch12-mq.xml:136 37.12994 +#: ../en/ch11-mq.xml:136 37.12995 msgid "" 37.12996 "Because quilt does not care about revision control tools, it is still a " 37.12997 "tremendously useful piece of software to know about for situations where you " 37.12998 @@ -13657,19 +12742,19 @@ 37.12999 msgstr "" 37.13000 37.13001 #. type: Content of: <book><chapter><sect1><title> 37.13002 -#: ../en/ch12-mq.xml:144 37.13003 +#: ../en/ch11-mq.xml:144 37.13004 msgid "The huge advantage of MQ" 37.13005 msgstr "MQ 的巨大优势" 37.13006 37.13007 #. type: Content of: <book><chapter><sect1><para> 37.13008 -#: ../en/ch12-mq.xml:146 37.13009 +#: ../en/ch11-mq.xml:146 37.13010 msgid "" 37.13011 "I cannot overstate the value that MQ offers through the unification of " 37.13012 "patches and revision control." 37.13013 msgstr "" 37.13014 37.13015 #. type: Content of: <book><chapter><sect1><para> 37.13016 -#: ../en/ch12-mq.xml:149 37.13017 +#: ../en/ch11-mq.xml:149 37.13018 msgid "" 37.13019 "A major reason that patches have persisted in the free software and open " 37.13020 "source world&emdash;in spite of the availability of increasingly capable " 37.13021 @@ -13678,7 +12763,7 @@ 37.13022 msgstr "" 37.13023 37.13024 #. type: Content of: <book><chapter><sect1><para> 37.13025 -#: ../en/ch12-mq.xml:155 37.13026 +#: ../en/ch11-mq.xml:155 37.13027 msgid "" 37.13028 "Traditional revision control tools make a permanent, irreversible record of " 37.13029 "everything that you do. While this has great value, it's also somewhat " 37.13030 @@ -13689,7 +12774,7 @@ 37.13031 msgstr "" 37.13032 37.13033 #. type: Content of: <book><chapter><sect1><para> 37.13034 -#: ../en/ch12-mq.xml:163 37.13035 +#: ../en/ch11-mq.xml:163 37.13036 msgid "" 37.13037 "By contrast, MQ's marriage of distributed revision control with patches makes " 37.13038 "it much easier to isolate your work. Your patches live on top of normal " 37.13039 @@ -13700,7 +12785,7 @@ 37.13040 msgstr "" 37.13041 37.13042 #. type: Content of: <book><chapter><sect1><para> 37.13043 -#: ../en/ch12-mq.xml:171 37.13044 +#: ../en/ch11-mq.xml:171 37.13045 msgid "" 37.13046 "As an example, the integration of patches with revision control makes " 37.13047 "understanding patches and debugging their effects&emdash;and their interplay " 37.13048 @@ -13715,19 +12800,19 @@ 37.13049 msgstr "" 37.13050 37.13051 #. type: Content of: <book><chapter><sect1><title> 37.13052 -#: ../en/ch12-mq.xml:187 37.13053 +#: ../en/ch11-mq.xml:187 37.13054 msgid "Understanding patches" 37.13055 msgstr "理解补丁" 37.13056 37.13057 #. type: Content of: <book><chapter><sect1><para> 37.13058 -#: ../en/ch12-mq.xml:189 37.13059 +#: ../en/ch11-mq.xml:189 37.13060 msgid "" 37.13061 "Because MQ doesn't hide its patch-oriented nature, it is helpful to " 37.13062 "understand what patches are, and a little about the tools that work with them." 37.13063 msgstr "" 37.13064 37.13065 #. type: Content of: <book><chapter><sect1><para> 37.13066 -#: ../en/ch12-mq.xml:193 37.13067 +#: ../en/ch11-mq.xml:193 37.13068 msgid "" 37.13069 "The traditional Unix <command>diff</command> command compares two files, and " 37.13070 "prints a list of differences between them. The <command>patch</command> " 37.13071 @@ -13737,7 +12822,7 @@ 37.13072 msgstr "" 37.13073 37.13074 #. type: Content of: <book><chapter><sect1><para> 37.13075 -#: ../en/ch12-mq.xml:202 37.13076 +#: ../en/ch11-mq.xml:202 37.13077 msgid "" 37.13078 "The type of file that <command>diff</command> generates (and <command>patch</" 37.13079 "command> takes as input) is called a <quote>patch</quote> or a <quote>diff</" 37.13080 @@ -13746,7 +12831,7 @@ 37.13081 msgstr "" 37.13082 37.13083 #. type: Content of: <book><chapter><sect1><para> 37.13084 -#: ../en/ch12-mq.xml:208 37.13085 +#: ../en/ch11-mq.xml:208 37.13086 msgid "" 37.13087 "A patch file can start with arbitrary text; the <command>patch</command> " 37.13088 "command ignores this text, but MQ uses it as the commit message when creating " 37.13089 @@ -13756,7 +12841,7 @@ 37.13090 msgstr "" 37.13091 37.13092 #. type: Content of: <book><chapter><sect1><para> 37.13093 -#: ../en/ch12-mq.xml:215 37.13094 +#: ../en/ch11-mq.xml:215 37.13095 msgid "" 37.13096 "MQ works with <emphasis>unified</emphasis> diffs (<command>patch</command> " 37.13097 "can accept several other diff formats, but MQ doesn't). A unified diff " 37.13098 @@ -13767,7 +12852,7 @@ 37.13099 msgstr "" 37.13100 37.13101 #. type: Content of: <book><chapter><sect1><para> 37.13102 -#: ../en/ch12-mq.xml:223 37.13103 +#: ../en/ch11-mq.xml:223 37.13104 msgid "" 37.13105 "After the file header comes a series of <emphasis>hunks</emphasis>. Each " 37.13106 "hunk starts with a header; this identifies the range of line numbers within " 37.13107 @@ -13780,7 +12865,7 @@ 37.13108 msgstr "" 37.13109 37.13110 #. type: Content of: <book><chapter><sect1><para> 37.13111 -#: ../en/ch12-mq.xml:235 37.13112 +#: ../en/ch11-mq.xml:235 37.13113 msgid "" 37.13114 "Each line of context begins with a space character. Within the hunk, a line " 37.13115 "that begins with <quote><literal>-</literal></quote> means <quote>remove this " 37.13116 @@ -13790,7 +12875,7 @@ 37.13117 msgstr "" 37.13118 37.13119 #. type: Content of: <book><chapter><sect1><para> 37.13120 -#: ../en/ch12-mq.xml:243 37.13121 +#: ../en/ch11-mq.xml:243 37.13122 msgid "" 37.13123 "We will return to some of the more subtle aspects of patches later (in " 37.13124 "section <xref linkend=\"sec.mq.adv-patch\"/>), but you should have enough " 37.13125 @@ -13798,12 +12883,12 @@ 37.13126 msgstr "" 37.13127 37.13128 #. type: Content of: <book><chapter><sect1><title> 37.13129 -#: ../en/ch12-mq.xml:250 37.13130 +#: ../en/ch11-mq.xml:250 37.13131 msgid "Getting started with Mercurial Queues" 37.13132 msgstr "开始使用 MQ" 37.13133 37.13134 #. type: Content of: <book><chapter><sect1><para> 37.13135 -#: ../en/ch12-mq.xml:252 37.13136 +#: ../en/ch11-mq.xml:252 37.13137 msgid "" 37.13138 "Because MQ is implemented as an extension, you must explicitly enable before " 37.13139 "you can use it. (You don't need to download anything; MQ ships with the " 37.13140 @@ -13812,7 +12897,7 @@ 37.13141 msgstr "" 37.13142 37.13143 #. type: Content of: <book><chapter><sect1><para> 37.13144 -#: ../en/ch12-mq.xml:261 37.13145 +#: ../en/ch11-mq.xml:262 37.13146 msgid "" 37.13147 "Once the extension is enabled, it will make a number of new commands " 37.13148 "available. To verify that the extension is working, you can use <command " 37.13149 @@ -13821,7 +12906,7 @@ 37.13150 msgstr "" 37.13151 37.13152 #. type: Content of: <book><chapter><sect1><para> 37.13153 -#: ../en/ch12-mq.xml:269 37.13154 +#: ../en/ch11-mq.xml:270 37.13155 msgid "" 37.13156 "You can use MQ with <emphasis>any</emphasis> Mercurial repository, and its " 37.13157 "commands only operate within that repository. To get started, simply prepare " 37.13158 @@ -13829,7 +12914,7 @@ 37.13159 msgstr "" 37.13160 37.13161 #. type: Content of: <book><chapter><sect1><para> 37.13162 -#: ../en/ch12-mq.xml:276 37.13163 +#: ../en/ch11-mq.xml:277 37.13164 msgid "" 37.13165 "This command creates an empty directory called <filename role=\"special\" " 37.13166 "class=\"directory\">.hg/patches</filename>, where MQ will keep its metadata. " 37.13167 @@ -13838,12 +12923,12 @@ 37.13168 msgstr "" 37.13169 37.13170 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13171 -#: ../en/ch12-mq.xml:283 37.13172 +#: ../en/ch11-mq.xml:284 37.13173 msgid "Creating a new patch" 37.13174 msgstr "创建新补丁" 37.13175 37.13176 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13177 -#: ../en/ch12-mq.xml:285 37.13178 +#: ../en/ch11-mq.xml:286 37.13179 msgid "" 37.13180 "To begin work on a new patch, use the <command role=\"hg-ext-mq\">qnew</" 37.13181 "command> command. This command takes one argument, the name of the patch to " 37.13182 @@ -13851,14 +12936,14 @@ 37.13183 msgstr "" 37.13184 37.13185 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13186 -#: ../en/ch12-mq.xml:289 37.13187 +#: ../en/ch11-mq.xml:290 37.13188 msgid "" 37.13189 "MQ will use this as the name of an actual file in the <filename role=\"special" 37.13190 "\" class=\"directory\">.hg/patches</filename> directory, as you can see below." 37.13191 msgstr "" 37.13192 37.13193 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13194 -#: ../en/ch12-mq.xml:296 37.13195 +#: ../en/ch11-mq.xml:297 37.13196 msgid "" 37.13197 "Also newly present in the <filename role=\"special\" class=\"directory\">.hg/" 37.13198 "patches</filename> directory are two other files, <filename role=\"special" 37.13199 @@ -13871,7 +12956,7 @@ 37.13200 msgstr "" 37.13201 37.13202 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.13203 -#: ../en/ch12-mq.xml:308 37.13204 +#: ../en/ch11-mq.xml:309 37.13205 msgid "" 37.13206 "You may sometimes want to edit the <filename role=\"special\">series</" 37.13207 "filename> file by hand; for example, to change the sequence in which some " 37.13208 @@ -13881,7 +12966,7 @@ 37.13209 msgstr "" 37.13210 37.13211 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13212 -#: ../en/ch12-mq.xml:317 37.13213 +#: ../en/ch11-mq.xml:318 37.13214 msgid "" 37.13215 "Once you have created your new patch, you can edit files in the working " 37.13216 "directory as you usually would. All of the normal Mercurial commands, such " 37.13217 @@ -13890,12 +12975,12 @@ 37.13218 msgstr "" 37.13219 37.13220 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13221 -#: ../en/ch12-mq.xml:325 37.13222 +#: ../en/ch11-mq.xml:326 37.13223 msgid "Refreshing a patch" 37.13224 msgstr "刷新补丁" 37.13225 37.13226 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13227 -#: ../en/ch12-mq.xml:327 37.13228 +#: ../en/ch11-mq.xml:328 37.13229 msgid "" 37.13230 "When you reach a point where you want to save your work, use the <command " 37.13231 "role=\"hg-ext-mq\">qrefresh</command> command to update the patch you are " 37.13232 @@ -13903,14 +12988,14 @@ 37.13233 msgstr "" 37.13234 37.13235 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13236 -#: ../en/ch12-mq.xml:333 37.13237 +#: ../en/ch11-mq.xml:334 37.13238 msgid "" 37.13239 "This command folds the changes you have made in the working directory into " 37.13240 "your patch, and updates its corresponding changeset to contain those changes." 37.13241 msgstr "" 37.13242 37.13243 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13244 -#: ../en/ch12-mq.xml:337 37.13245 +#: ../en/ch11-mq.xml:338 37.13246 msgid "" 37.13247 "You can run <command role=\"hg-ext-mq\">qrefresh</command> as often as you " 37.13248 "like, so it's a good way to <quote>checkpoint</quote> your work. Refresh " 37.13249 @@ -13920,12 +13005,12 @@ 37.13250 msgstr "" 37.13251 37.13252 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13253 -#: ../en/ch12-mq.xml:348 37.13254 +#: ../en/ch11-mq.xml:349 37.13255 msgid "Stacking and tracking patches" 37.13256 msgstr "堆叠和跟踪补丁" 37.13257 37.13258 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13259 -#: ../en/ch12-mq.xml:350 37.13260 +#: ../en/ch11-mq.xml:351 37.13261 msgid "" 37.13262 "Once you have finished working on a patch, or need to work on another, you " 37.13263 "can use the <command role=\"hg-ext-mq\">qnew</command> command again to " 37.13264 @@ -13934,7 +13019,7 @@ 37.13265 msgstr "" 37.13266 37.13267 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13268 -#: ../en/ch12-mq.xml:357 37.13269 +#: ../en/ch11-mq.xml:358 37.13270 msgid "" 37.13271 "Notice that the patch contains the changes in our prior patch as part of its " 37.13272 "context (you can see this more clearly in the output of <command role=\"hg-cmd" 37.13273 @@ -13942,7 +13027,7 @@ 37.13274 msgstr "" 37.13275 37.13276 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13277 -#: ../en/ch12-mq.xml:362 37.13278 +#: ../en/ch11-mq.xml:363 37.13279 msgid "" 37.13280 "So far, with the exception of <command role=\"hg-ext-mq\">qnew</command> and " 37.13281 "<command role=\"hg-ext-mq\">qrefresh</command>, we've been careful to only " 37.13282 @@ -13951,7 +13036,7 @@ 37.13283 msgstr "" 37.13284 37.13285 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13286 -#: ../en/ch12-mq.xml:372 37.13287 +#: ../en/ch11-mq.xml:373 37.13288 msgid "" 37.13289 "The <command role=\"hg-ext-mq\">qseries</command> command lists every patch " 37.13290 "that MQ knows about in this repository, from oldest to newest (most recently " 37.13291 @@ -13959,7 +13044,7 @@ 37.13292 msgstr "" 37.13293 37.13294 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13295 -#: ../en/ch12-mq.xml:378 37.13296 +#: ../en/ch11-mq.xml:379 37.13297 msgid "" 37.13298 "The <command role=\"hg-ext-mq\">qapplied</command> command lists every patch " 37.13299 "that MQ has <emphasis>applied</emphasis> in this repository, again from " 37.13300 @@ -13967,12 +13052,12 @@ 37.13301 msgstr "" 37.13302 37.13303 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13304 -#: ../en/ch12-mq.xml:387 37.13305 +#: ../en/ch11-mq.xml:388 37.13306 msgid "Manipulating the patch stack" 37.13307 msgstr "操作补丁堆栈" 37.13308 37.13309 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13310 -#: ../en/ch12-mq.xml:389 37.13311 +#: ../en/ch11-mq.xml:390 37.13312 msgid "" 37.13313 "The previous discussion implied that there must be a difference between " 37.13314 "<quote>known</quote> and <quote>applied</quote> patches, and there is. MQ " 37.13315 @@ -13980,7 +13065,7 @@ 37.13316 msgstr "" 37.13317 37.13318 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13319 -#: ../en/ch12-mq.xml:394 37.13320 +#: ../en/ch11-mq.xml:395 37.13321 msgid "" 37.13322 "An <emphasis>applied</emphasis> patch has a corresponding changeset in the " 37.13323 "repository, and the effects of the patch and changeset are visible in the " 37.13324 @@ -13994,17 +13079,17 @@ 37.13325 msgstr "" 37.13326 37.13327 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject> 37.13328 -#: ../en/ch12-mq.xml:408 37.13329 +#: ../en/ch11-mq.xml:409 37.13330 msgid "<imageobject><imagedata fileref=\"images/mq-stack.png\"/></imageobject>" 37.13331 msgstr "" 37.13332 37.13333 #. type: Content of: <book><chapter><sect1><sect2><informalfigure><mediaobject><caption><para> 37.13334 -#: ../en/ch12-mq.xml:410 37.13335 +#: ../en/ch11-mq.xml:411 37.13336 msgid "Applied and unapplied patches in the MQ patch stack" 37.13337 msgstr "" 37.13338 37.13339 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13340 -#: ../en/ch12-mq.xml:415 37.13341 +#: ../en/ch11-mq.xml:416 37.13342 msgid "" 37.13343 "You can reapply an unapplied, or popped, patch using the <command role=\"hg-" 37.13344 "ext-mq\">qpush</command> command. This creates a new changeset to correspond " 37.13345 @@ -14014,7 +13099,7 @@ 37.13346 msgstr "" 37.13347 37.13348 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13349 -#: ../en/ch12-mq.xml:424 37.13350 +#: ../en/ch11-mq.xml:425 37.13351 msgid "" 37.13352 "Notice that once we have popped a patch or two patches, the output of " 37.13353 "<command role=\"hg-ext-mq\">qseries</command> remains the same, while that of " 37.13354 @@ -14022,12 +13107,12 @@ 37.13355 msgstr "" 37.13356 37.13357 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13358 -#: ../en/ch12-mq.xml:432 37.13359 +#: ../en/ch11-mq.xml:433 37.13360 msgid "Pushing and popping many patches" 37.13361 msgstr "压入或弹出多个补丁" 37.13362 37.13363 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13364 -#: ../en/ch12-mq.xml:434 37.13365 +#: ../en/ch11-mq.xml:435 37.13366 msgid "" 37.13367 "While <command role=\"hg-ext-mq\">qpush</command> and <command role=\"hg-ext-" 37.13368 "mq\">qpop</command> each operate on a single patch at a time by default, you " 37.13369 @@ -14040,12 +13125,12 @@ 37.13370 msgstr "" 37.13371 37.13372 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13373 -#: ../en/ch12-mq.xml:451 37.13374 +#: ../en/ch11-mq.xml:452 37.13375 msgid "Safety checks, and overriding them" 37.13376 msgstr "安全的检查,然后覆盖它们" 37.13377 37.13378 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13379 -#: ../en/ch12-mq.xml:453 37.13380 +#: ../en/ch11-mq.xml:454 37.13381 msgid "" 37.13382 "Several MQ commands check the working directory before they do anything, and " 37.13383 "fail if they find any modifications. They do this to ensure that you won't " 37.13384 @@ -14057,7 +13142,7 @@ 37.13385 msgstr "" 37.13386 37.13387 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13388 -#: ../en/ch12-mq.xml:465 37.13389 +#: ../en/ch11-mq.xml:466 37.13390 msgid "" 37.13391 "Commands that check the working directory all take an <quote>I know what I'm " 37.13392 "doing</quote> option, which is always named <option>-f</option>. The exact " 37.13393 @@ -14071,12 +13156,12 @@ 37.13394 msgstr "" 37.13395 37.13396 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13397 -#: ../en/ch12-mq.xml:480 37.13398 +#: ../en/ch11-mq.xml:481 37.13399 msgid "Working on several patches at once" 37.13400 msgstr "同时处理多个补丁" 37.13401 37.13402 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13403 -#: ../en/ch12-mq.xml:482 37.13404 +#: ../en/ch11-mq.xml:483 37.13405 msgid "" 37.13406 "The <command role=\"hg-ext-mq\">qrefresh</command> command always refreshes " 37.13407 "the <emphasis>topmost</emphasis> applied patch. This means that you can " 37.13408 @@ -14085,7 +13170,7 @@ 37.13409 msgstr "" 37.13410 37.13411 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13412 -#: ../en/ch12-mq.xml:489 37.13413 +#: ../en/ch11-mq.xml:490 37.13414 msgid "" 37.13415 "Here's an example that illustrates how you can use this ability. Let's say " 37.13416 "you're developing a new feature as two patches. The first is a change to the " 37.13417 @@ -14101,12 +13186,12 @@ 37.13418 msgstr "" 37.13419 37.13420 #. type: Content of: <book><chapter><sect1><title> 37.13421 -#: ../en/ch12-mq.xml:506 37.13422 +#: ../en/ch11-mq.xml:507 37.13423 msgid "More about patches" 37.13424 msgstr "关于补丁的更多信息" 37.13425 37.13426 #. type: Content of: <book><chapter><sect1><para> 37.13427 -#: ../en/ch12-mq.xml:508 37.13428 +#: ../en/ch11-mq.xml:509 37.13429 msgid "" 37.13430 "MQ uses the GNU <command>patch</command> command to apply patches, so it's " 37.13431 "helpful to know a few more detailed aspects of how <command>patch</command> " 37.13432 @@ -14114,12 +13199,12 @@ 37.13433 msgstr "" 37.13434 37.13435 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13436 -#: ../en/ch12-mq.xml:514 37.13437 +#: ../en/ch11-mq.xml:515 37.13438 msgid "The strip count" 37.13439 msgstr "修剪计数" 37.13440 37.13441 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13442 -#: ../en/ch12-mq.xml:516 37.13443 +#: ../en/ch11-mq.xml:517 37.13444 msgid "" 37.13445 "If you look at the file headers in a patch, you will notice that the " 37.13446 "pathnames usually have an extra component on the front that isn't present in " 37.13447 @@ -14129,7 +13214,7 @@ 37.13448 msgstr "" 37.13449 37.13450 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13451 -#: ../en/ch12-mq.xml:523 37.13452 +#: ../en/ch11-mq.xml:524 37.13453 msgid "" 37.13454 "Alice would unpack a tarball, edit her files, then decide that she wanted to " 37.13455 "create a patch. So she'd rename her working directory, unpack the tarball " 37.13456 @@ -14143,7 +13228,7 @@ 37.13457 msgstr "" 37.13458 37.13459 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13460 -#: ../en/ch12-mq.xml:536 37.13461 +#: ../en/ch11-mq.xml:537 37.13462 msgid "" 37.13463 "Since someone receiving a patch from the Alices of the net would be unlikely " 37.13464 "to have unmodified and modified directories with exactly the same names, the " 37.13465 @@ -14154,7 +13239,7 @@ 37.13466 msgstr "" 37.13467 37.13468 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13469 -#: ../en/ch12-mq.xml:544 37.13470 +#: ../en/ch11-mq.xml:545 37.13471 msgid "" 37.13472 "An option of <quote><literal>-p1</literal></quote> means <quote>use a strip " 37.13473 "count of one</quote>. If <command>patch</command> sees a file name " 37.13474 @@ -14168,7 +13253,7 @@ 37.13475 msgstr "" 37.13476 37.13477 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13478 -#: ../en/ch12-mq.xml:557 37.13479 +#: ../en/ch11-mq.xml:558 37.13480 msgid "" 37.13481 "The <quote>standard</quote> strip count for patches is one; almost all " 37.13482 "patches contain one leading path name component that needs to be stripped. " 37.13483 @@ -14178,7 +13263,7 @@ 37.13484 msgstr "" 37.13485 37.13486 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13487 -#: ../en/ch12-mq.xml:565 37.13488 +#: ../en/ch11-mq.xml:566 37.13489 msgid "" 37.13490 "If you receive a patch from someone that you want to add to your patch queue, " 37.13491 "and the patch needs a strip count other than one, you cannot just <command " 37.13492 @@ -14195,12 +13280,12 @@ 37.13493 msgstr "" 37.13494 37.13495 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13496 -#: ../en/ch12-mq.xml:584 37.13497 +#: ../en/ch11-mq.xml:585 37.13498 msgid "Strategies for applying a patch" 37.13499 msgstr "应用补丁的策略" 37.13500 37.13501 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13502 -#: ../en/ch12-mq.xml:586 37.13503 +#: ../en/ch11-mq.xml:587 37.13504 msgid "" 37.13505 "When <command>patch</command> applies a hunk, it tries a handful of " 37.13506 "successively less accurate strategies to try to make the hunk apply. This " 37.13507 @@ -14210,7 +13295,7 @@ 37.13508 msgstr "" 37.13509 37.13510 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13511 -#: ../en/ch12-mq.xml:593 37.13512 +#: ../en/ch11-mq.xml:594 37.13513 msgid "" 37.13514 "First, <command>patch</command> tries an exact match, where the line numbers, " 37.13515 "the context, and the text to be modified must apply exactly. If it cannot " 37.13516 @@ -14221,7 +13306,7 @@ 37.13517 msgstr "" 37.13518 37.13519 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13520 -#: ../en/ch12-mq.xml:602 37.13521 +#: ../en/ch11-mq.xml:603 37.13522 msgid "" 37.13523 "If a context-only match fails, <command>patch</command> removes the first and " 37.13524 "last lines of the context, and tries a <emphasis>reduced</emphasis> context-" 37.13525 @@ -14232,7 +13317,7 @@ 37.13526 msgstr "" 37.13527 37.13528 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13529 -#: ../en/ch12-mq.xml:611 37.13530 +#: ../en/ch11-mq.xml:612 37.13531 msgid "" 37.13532 "When neither of these techniques works, <command>patch</command> prints a " 37.13533 "message saying that the hunk in question was rejected. It saves rejected " 37.13534 @@ -14249,33 +13334,33 @@ 37.13535 msgstr "" 37.13536 37.13537 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13538 -#: ../en/ch12-mq.xml:629 37.13539 +#: ../en/ch11-mq.xml:630 37.13540 msgid "Some quirks of patch representation" 37.13541 msgstr "补丁的一些特性" 37.13542 37.13543 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13544 -#: ../en/ch12-mq.xml:631 37.13545 +#: ../en/ch11-mq.xml:632 37.13546 msgid "" 37.13547 "There are a few useful things to know about how <command>patch</command> " 37.13548 "works with files." 37.13549 msgstr "" 37.13550 37.13551 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13552 -#: ../en/ch12-mq.xml:634 37.13553 +#: ../en/ch11-mq.xml:635 37.13554 msgid "" 37.13555 "This should already be obvious, but <command>patch</command> cannot handle " 37.13556 "binary files." 37.13557 msgstr "" 37.13558 37.13559 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13560 -#: ../en/ch12-mq.xml:638 37.13561 +#: ../en/ch11-mq.xml:639 37.13562 msgid "" 37.13563 "Neither does it care about the executable bit; it creates new files as " 37.13564 "readable, but not executable." 37.13565 msgstr "" 37.13566 37.13567 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13568 -#: ../en/ch12-mq.xml:642 37.13569 +#: ../en/ch11-mq.xml:643 37.13570 msgid "" 37.13571 "<command>patch</command> treats the removal of a file as a diff between the " 37.13572 "file to be removed and the empty file. So your idea of <quote>I deleted this " 37.13573 @@ -14284,7 +13369,7 @@ 37.13574 msgstr "" 37.13575 37.13576 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13577 -#: ../en/ch12-mq.xml:648 37.13578 +#: ../en/ch11-mq.xml:649 37.13579 msgid "" 37.13580 "It treats the addition of a file as a diff between the empty file and the " 37.13581 "file to be added. So in a patch, your idea of <quote>I added this file</" 37.13582 @@ -14292,7 +13377,7 @@ 37.13583 msgstr "" 37.13584 37.13585 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13586 -#: ../en/ch12-mq.xml:654 37.13587 +#: ../en/ch11-mq.xml:655 37.13588 msgid "" 37.13589 "It treats a renamed file as the removal of the old name, and the addition of " 37.13590 "the new name. This means that renamed files have a big footprint in " 37.13591 @@ -14301,7 +13386,7 @@ 37.13592 msgstr "" 37.13593 37.13594 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13595 -#: ../en/ch12-mq.xml:660 37.13596 +#: ../en/ch11-mq.xml:661 37.13597 msgid "" 37.13598 "<command>patch</command> cannot represent empty files, so you cannot use a " 37.13599 "patch to represent the notion <quote>I added this empty file to the tree</" 37.13600 @@ -14309,12 +13394,12 @@ 37.13601 msgstr "" 37.13602 37.13603 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13604 -#: ../en/ch12-mq.xml:667 37.13605 +#: ../en/ch11-mq.xml:668 37.13606 msgid "Beware the fuzz" 37.13607 msgstr "当心毛刺" 37.13608 37.13609 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13610 -#: ../en/ch12-mq.xml:669 37.13611 +#: ../en/ch11-mq.xml:670 37.13612 msgid "" 37.13613 "While applying a hunk at an offset, or with a fuzz factor, will often be " 37.13614 "completely successful, these inexact techniques naturally leave open the " 37.13615 @@ -14326,7 +13411,7 @@ 37.13616 msgstr "" 37.13617 37.13618 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13619 -#: ../en/ch12-mq.xml:679 37.13620 +#: ../en/ch11-mq.xml:680 37.13621 msgid "" 37.13622 "It's often a good idea to refresh a patch that has applied with an offset or " 37.13623 "fuzz factor; refreshing the patch generates new context information that will " 37.13624 @@ -14339,12 +13424,12 @@ 37.13625 msgstr "" 37.13626 37.13627 #. type: Content of: <book><chapter><sect1><sect2><title> 37.13628 -#: ../en/ch12-mq.xml:692 37.13629 +#: ../en/ch11-mq.xml:693 37.13630 msgid "Handling rejection" 37.13631 msgstr "处理拒绝" 37.13632 37.13633 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13634 -#: ../en/ch12-mq.xml:694 37.13635 +#: ../en/ch11-mq.xml:695 37.13636 msgid "" 37.13637 "If <command role=\"hg-ext-mq\">qpush</command> fails to apply a patch, it " 37.13638 "will print an error message and exit. If it has left <filename role=\"special" 37.13639 @@ -14353,7 +13438,7 @@ 37.13640 msgstr "" 37.13641 37.13642 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13643 -#: ../en/ch12-mq.xml:700 37.13644 +#: ../en/ch11-mq.xml:701 37.13645 msgid "" 37.13646 "If your patch <emphasis>used to</emphasis> apply cleanly, and no longer does " 37.13647 "because you've changed the underlying code that your patches are based on, " 37.13648 @@ -14362,7 +13447,7 @@ 37.13649 msgstr "" 37.13650 37.13651 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13652 -#: ../en/ch12-mq.xml:706 37.13653 +#: ../en/ch11-mq.xml:707 37.13654 msgid "" 37.13655 "Unfortunately, there aren't any great techniques for dealing with rejected " 37.13656 "hunks. Most often, you'll need to view the <filename role=\"special\">.rej</" 37.13657 @@ -14370,7 +13455,7 @@ 37.13658 msgstr "" 37.13659 37.13660 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13661 -#: ../en/ch12-mq.xml:711 37.13662 +#: ../en/ch11-mq.xml:712 37.13663 msgid "" 37.13664 "If you're feeling adventurous, Neil Brown, a Linux kernel hacker, wrote a " 37.13665 "tool called <command>wiggle</command> <citation>web:wiggle</citation>, which " 37.13666 @@ -14379,7 +13464,7 @@ 37.13667 msgstr "" 37.13668 37.13669 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13670 -#: ../en/ch12-mq.xml:717 37.13671 +#: ../en/ch11-mq.xml:718 37.13672 msgid "" 37.13673 "Another Linux kernel hacker, Chris Mason (the author of Mercurial Queues), " 37.13674 "wrote a similar tool called <command>mpatch</command> <citation>web:mpatch</" 37.13675 @@ -14389,31 +13474,31 @@ 37.13676 msgstr "" 37.13677 37.13678 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13679 -#: ../en/ch12-mq.xml:726 37.13680 +#: ../en/ch11-mq.xml:727 37.13681 msgid "The context in the middle of a hunk has changed." 37.13682 msgstr "" 37.13683 37.13684 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13685 -#: ../en/ch12-mq.xml:729 37.13686 +#: ../en/ch11-mq.xml:730 37.13687 msgid "A hunk is missing some context at the beginning or end." 37.13688 msgstr "" 37.13689 37.13690 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13691 -#: ../en/ch12-mq.xml:732 37.13692 +#: ../en/ch11-mq.xml:733 37.13693 msgid "" 37.13694 "A large hunk might apply better&emdash;either entirely or in part&emdash;if " 37.13695 "it was broken up into smaller hunks." 37.13696 msgstr "" 37.13697 37.13698 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.13699 -#: ../en/ch12-mq.xml:736 37.13700 +#: ../en/ch11-mq.xml:737 37.13701 msgid "" 37.13702 "A hunk removes lines with slightly different content than those currently " 37.13703 "present in the file." 37.13704 msgstr "" 37.13705 37.13706 #. type: Content of: <book><chapter><sect1><sect2><para> 37.13707 -#: ../en/ch12-mq.xml:740 37.13708 +#: ../en/ch11-mq.xml:741 37.13709 msgid "" 37.13710 "If you use <command>wiggle</command> or <command>mpatch</command>, you should " 37.13711 "be doubly careful to check your results when you're done. In fact, " 37.13712 @@ -14423,12 +13508,12 @@ 37.13713 msgstr "" 37.13714 37.13715 #. type: Content of: <book><chapter><sect1><title> 37.13716 -#: ../en/ch12-mq.xml:752 37.13717 +#: ../en/ch11-mq.xml:753 37.13718 msgid "Getting the best performance out of MQ" 37.13719 msgstr "MQ 的性能" 37.13720 37.13721 #. type: Content of: <book><chapter><sect1><para> 37.13722 -#: ../en/ch12-mq.xml:754 37.13723 +#: ../en/ch11-mq.xml:755 37.13724 msgid "" 37.13725 "MQ is very efficient at handling a large number of patches. I ran some " 37.13726 "performance experiments in mid-2006 for a talk that I gave at the 2006 " 37.13727 @@ -14439,7 +13524,7 @@ 37.13728 msgstr "" 37.13729 37.13730 #. type: Content of: <book><chapter><sect1><para> 37.13731 -#: ../en/ch12-mq.xml:763 37.13732 +#: ../en/ch11-mq.xml:764 37.13733 msgid "" 37.13734 "On my old, slow laptop, I was able to <command role=\"hg-cmd\">hg qpush " 37.13735 "<option role=\"hg-ext-mq-cmd-qpush-opt\">hg -a</option></command> all 1,738 " 37.13736 @@ -14451,14 +13536,14 @@ 37.13737 msgstr "" 37.13738 37.13739 #. type: Content of: <book><chapter><sect1><para> 37.13740 -#: ../en/ch12-mq.xml:774 37.13741 +#: ../en/ch11-mq.xml:775 37.13742 msgid "" 37.13743 "Clearly, MQ is well suited to working in large trees, but there are a few " 37.13744 "tricks you can use to get the best performance of it." 37.13745 msgstr "" 37.13746 37.13747 #. type: Content of: <book><chapter><sect1><para> 37.13748 -#: ../en/ch12-mq.xml:778 37.13749 +#: ../en/ch11-mq.xml:779 37.13750 msgid "" 37.13751 "First of all, try to <quote>batch</quote> operations together. Every time " 37.13752 "you run <command role=\"hg-ext-mq\">qpush</command> or <command role=\"hg-ext-" 37.13753 @@ -14470,7 +13555,7 @@ 37.13754 msgstr "" 37.13755 37.13756 #. type: Content of: <book><chapter><sect1><para> 37.13757 -#: ../en/ch12-mq.xml:789 37.13758 +#: ../en/ch11-mq.xml:790 37.13759 msgid "" 37.13760 "The <command role=\"hg-ext-mq\">qpush</command> and <command role=\"hg-ext-mq" 37.13761 "\">qpop</command> commands allow you to push and pop multiple patches at a " 37.13762 @@ -14482,7 +13567,7 @@ 37.13763 msgstr "" 37.13764 37.13765 #. type: Content of: <book><chapter><sect1><para> 37.13766 -#: ../en/ch12-mq.xml:799 37.13767 +#: ../en/ch11-mq.xml:800 37.13768 msgid "" 37.13769 "You can identify a destination patch using either the name of the patch, or " 37.13770 "by number. If you use numeric addressing, patches are counted from zero; " 37.13771 @@ -14490,12 +13575,12 @@ 37.13772 msgstr "" 37.13773 37.13774 #. type: Content of: <book><chapter><sect1><title> 37.13775 -#: ../en/ch12-mq.xml:806 37.13776 +#: ../en/ch11-mq.xml:807 37.13777 msgid "Updating your patches when the underlying code changes" 37.13778 msgstr "当基础代码改变时,更新补丁的方法" 37.13779 37.13780 #. type: Content of: <book><chapter><sect1><para> 37.13781 -#: ../en/ch12-mq.xml:809 37.13782 +#: ../en/ch11-mq.xml:810 37.13783 msgid "" 37.13784 "It's common to have a stack of patches on top of an underlying repository " 37.13785 "that you don't modify directly. If you're working on changes to third-party " 37.13786 @@ -14506,7 +13591,7 @@ 37.13787 msgstr "" 37.13788 37.13789 #. type: Content of: <book><chapter><sect1><para> 37.13790 -#: ../en/ch12-mq.xml:818 37.13791 +#: ../en/ch11-mq.xml:819 37.13792 msgid "" 37.13793 "The simplest way to do this is to <command role=\"hg-cmd\">hg qpop <option " 37.13794 "role=\"hg-ext-mq-cmd-qpop-opt\">hg -a</option></command> your patches, then " 37.13795 @@ -14520,7 +13605,7 @@ 37.13796 msgstr "" 37.13797 37.13798 #. type: Content of: <book><chapter><sect1><para> 37.13799 -#: ../en/ch12-mq.xml:830 37.13800 +#: ../en/ch11-mq.xml:831 37.13801 msgid "" 37.13802 "This approach is easy to use and works well if you don't expect changes to " 37.13803 "the underlying code to affect how well your patches apply. If your patch " 37.13804 @@ -14530,7 +13615,7 @@ 37.13805 msgstr "" 37.13806 37.13807 #. type: Content of: <book><chapter><sect1><para> 37.13808 -#: ../en/ch12-mq.xml:837 37.13809 +#: ../en/ch11-mq.xml:838 37.13810 msgid "" 37.13811 "It's possible to partially automate the rebasing process. If your patches " 37.13812 "apply cleanly against some revision of the underlying repo, MQ can use this " 37.13813 @@ -14539,19 +13624,19 @@ 37.13814 msgstr "" 37.13815 37.13816 #. type: Content of: <book><chapter><sect1><para> 37.13817 -#: ../en/ch12-mq.xml:843 37.13818 +#: ../en/ch11-mq.xml:844 37.13819 msgid "The process is a little involved." 37.13820 msgstr "" 37.13821 37.13822 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.13823 -#: ../en/ch12-mq.xml:845 37.13824 +#: ../en/ch11-mq.xml:846 37.13825 msgid "" 37.13826 "To begin, <command role=\"hg-cmd\">hg qpush -a</command> all of your patches " 37.13827 "on top of the revision where you know that they apply cleanly." 37.13828 msgstr "" 37.13829 37.13830 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.13831 -#: ../en/ch12-mq.xml:849 37.13832 +#: ../en/ch11-mq.xml:850 37.13833 msgid "" 37.13834 "Save a backup copy of your patch directory using <command role=\"hg-cmd\">hg " 37.13835 "qsave <option role=\"hg-ext-mq-cmd-qsave-opt\">hg -e</option> <option role=" 37.13836 @@ -14566,7 +13651,7 @@ 37.13837 msgstr "" 37.13838 37.13839 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.13840 -#: ../en/ch12-mq.xml:863 37.13841 +#: ../en/ch11-mq.xml:864 37.13842 msgid "" 37.13843 "Use <command role=\"hg-cmd\">hg pull</command> to bring new changes into the " 37.13844 "underlying repository. (Don't run <command role=\"hg-cmd\">hg pull -u</" 37.13845 @@ -14574,7 +13659,7 @@ 37.13846 msgstr "" 37.13847 37.13848 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.13849 -#: ../en/ch12-mq.xml:868 37.13850 +#: ../en/ch11-mq.xml:869 37.13851 msgid "" 37.13852 "Update to the new tip revision, using <command role=\"hg-cmd\">hg update " 37.13853 "<option role=\"hg-opt-update\">-C</option></command> to override the patches " 37.13854 @@ -14582,17 +13667,16 @@ 37.13855 msgstr "" 37.13856 37.13857 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.13858 -#: ../en/ch12-mq.xml:873 37.13859 -msgid "" 37.13860 -"Merge all patches using \\hgcmdargs{qpush}{<option role=\"hg-ext-mq-cmd-qpush-" 37.13861 -"opt\">hg -m</option> <option role=\"hg-ext-mq-cmd-qpush-opt\">hg -a</" 37.13862 -"option>}. The <option role=\"hg-ext-mq-cmd-qpush-opt\">hg -m</option> option " 37.13863 -"to <command role=\"hg-ext-mq\">qpush</command> tells MQ to perform a three-" 37.13864 -"way merge if the patch fails to apply." 37.13865 -msgstr "" 37.13866 - 37.13867 -#. type: Content of: <book><chapter><sect1><para> 37.13868 -#: ../en/ch12-mq.xml:883 37.13869 +#: ../en/ch11-mq.xml:874 37.13870 +msgid "" 37.13871 +"Merge all patches using <command>hg qpush -m -a</command>. The <option role=" 37.13872 +"\"hg-ext-mq-cmd-qpush-opt\">-m</option> option to <command role=\"hg-ext-mq" 37.13873 +"\">qpush</command> tells MQ to perform a three-way merge if the patch fails " 37.13874 +"to apply." 37.13875 +msgstr "" 37.13876 + 37.13877 +#. type: Content of: <book><chapter><sect1><para> 37.13878 +#: ../en/ch11-mq.xml:882 37.13879 msgid "" 37.13880 "During the <command role=\"hg-cmd\">hg qpush <option role=\"hg-ext-mq-cmd-" 37.13881 "qpush-opt\">hg -m</option></command>, each patch in the <filename role=" 37.13882 @@ -14604,14 +13688,14 @@ 37.13883 msgstr "" 37.13884 37.13885 #. type: Content of: <book><chapter><sect1><para> 37.13886 -#: ../en/ch12-mq.xml:893 37.13887 +#: ../en/ch11-mq.xml:892 37.13888 msgid "" 37.13889 "When you finish resolving the effects of a patch, MQ refreshes your patch " 37.13890 "based on the result of the merge." 37.13891 msgstr "" 37.13892 37.13893 #. type: Content of: <book><chapter><sect1><para> 37.13894 -#: ../en/ch12-mq.xml:896 37.13895 +#: ../en/ch11-mq.xml:895 37.13896 msgid "" 37.13897 "At the end of this process, your repository will have one extra head from the " 37.13898 "old patch queue, and a copy of the old patch queue will be in <filename role=" 37.13899 @@ -14623,12 +13707,12 @@ 37.13900 msgstr "" 37.13901 37.13902 #. type: Content of: <book><chapter><sect1><title> 37.13903 -#: ../en/ch12-mq.xml:908 37.13904 +#: ../en/ch11-mq.xml:907 37.13905 msgid "Identifying patches" 37.13906 msgstr "标识补丁" 37.13907 37.13908 #. type: Content of: <book><chapter><sect1><para> 37.13909 -#: ../en/ch12-mq.xml:910 37.13910 +#: ../en/ch11-mq.xml:909 37.13911 msgid "" 37.13912 "MQ commands that work with patches let you refer to a patch either by using " 37.13913 "its name or by a number. By name is obvious enough; pass the name " 37.13914 @@ -14638,7 +13722,7 @@ 37.13915 msgstr "" 37.13916 37.13917 #. type: Content of: <book><chapter><sect1><para> 37.13918 -#: ../en/ch12-mq.xml:917 37.13919 +#: ../en/ch11-mq.xml:916 37.13920 msgid "" 37.13921 "As a shortcut, you can refer to a patch using both a name and a numeric " 37.13922 "offset; <literal>foo.patch-2</literal> means <quote>two patches before " 37.13923 @@ -14647,7 +13731,7 @@ 37.13924 msgstr "" 37.13925 37.13926 #. type: Content of: <book><chapter><sect1><para> 37.13927 -#: ../en/ch12-mq.xml:923 37.13928 +#: ../en/ch11-mq.xml:922 37.13929 msgid "" 37.13930 "Referring to a patch by index isn't much different. The first patch printed " 37.13931 "in the output of <command role=\"hg-ext-mq\">qseries</command> is patch zero " 37.13932 @@ -14656,51 +13740,45 @@ 37.13933 msgstr "" 37.13934 37.13935 #. type: Content of: <book><chapter><sect1><para> 37.13936 -#: ../en/ch12-mq.xml:929 37.13937 +#: ../en/ch11-mq.xml:928 37.13938 msgid "" 37.13939 "MQ also makes it easy to work with patches when you are using normal " 37.13940 "Mercurial commands. Every command that accepts a changeset ID will also " 37.13941 "accept the name of an applied patch. MQ augments the tags normally in the " 37.13942 "repository with an eponymous one for each applied patch. In addition, the " 37.13943 -"special tags \\index{tags!special tag names!<literal>qbase</literal>}" 37.13944 -"<literal>qbase</literal> and \\index{tags!special tag names!<literal>qtip</" 37.13945 -"literal>}<literal>qtip</literal> identify the <quote>bottom-most</quote> and " 37.13946 -"topmost applied patches, respectively." 37.13947 -msgstr "" 37.13948 - 37.13949 -#. type: Content of: <book><chapter><sect1><para> 37.13950 -#: ../en/ch12-mq.xml:941 37.13951 +"special tags <literal role=\"tag\">qbase</literal> and <literal role=\"tag" 37.13952 +"\">qtip</literal> identify the <quote>bottom-most</quote> and topmost applied " 37.13953 +"patches, respectively." 37.13954 +msgstr "" 37.13955 + 37.13956 +#. type: Content of: <book><chapter><sect1><para> 37.13957 +#: ../en/ch11-mq.xml:938 37.13958 msgid "" 37.13959 "These additions to Mercurial's normal tagging capabilities make dealing with " 37.13960 "patches even more of a breeze." 37.13961 msgstr "" 37.13962 37.13963 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.13964 -#: ../en/ch12-mq.xml:944 37.13965 +#: ../en/ch11-mq.xml:941 37.13966 msgid "Want to patchbomb a mailing list with your latest series of changes?" 37.13967 msgstr "" 37.13968 37.13969 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.13970 -#: ../en/ch12-mq.xml:948 37.13971 +#: ../en/ch11-mq.xml:944 37.13972 msgid "" 37.13973 "(Don't know what <quote>patchbombing</quote> is? See section <xref linkend=" 37.13974 "\"sec.hgext.patchbomb\"/>.)" 37.13975 msgstr "" 37.13976 37.13977 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.13978 -#: ../en/ch12-mq.xml:951 37.13979 +#: ../en/ch11-mq.xml:947 37.13980 msgid "" 37.13981 "Need to see all of the patches since <literal>foo.patch</literal> that have " 37.13982 "touched files in a subdirectory of your tree?" 37.13983 msgstr "" 37.13984 37.13985 -#. type: Content of: <book><chapter><sect1><itemizedlist><listitem><programlisting><emphasis> 37.13986 -#: ../en/ch12-mq.xml:955 37.13987 -msgid "subdir" 37.13988 -msgstr "" 37.13989 - 37.13990 -#. type: Content of: <book><chapter><sect1><para> 37.13991 -#: ../en/ch12-mq.xml:960 37.13992 +#. type: Content of: <book><chapter><sect1><para> 37.13993 +#: ../en/ch11-mq.xml:954 37.13994 msgid "" 37.13995 "Because MQ makes the names of patches available to the rest of Mercurial " 37.13996 "through its normal internal tag machinery, you don't need to type in the " 37.13997 @@ -14708,7 +13786,7 @@ 37.13998 msgstr "" 37.13999 37.14000 #. type: Content of: <book><chapter><sect1><para> 37.14001 -#: ../en/ch12-mq.xml:965 37.14002 +#: ../en/ch11-mq.xml:959 37.14003 msgid "" 37.14004 "Another nice consequence of representing patch names as tags is that when you " 37.14005 "run the <command role=\"hg-cmd\">hg log</command> command, it will display a " 37.14006 @@ -14719,19 +13797,19 @@ 37.14007 msgstr "" 37.14008 37.14009 #. type: Content of: <book><chapter><sect1><title> 37.14010 -#: ../en/ch12-mq.xml:978 37.14011 +#: ../en/ch11-mq.xml:972 37.14012 msgid "Useful things to know about" 37.14013 msgstr "其它需要了解的东西" 37.14014 37.14015 #. type: Content of: <book><chapter><sect1><para> 37.14016 -#: ../en/ch12-mq.xml:980 37.14017 +#: ../en/ch11-mq.xml:974 37.14018 msgid "" 37.14019 "There are a number of aspects of MQ usage that don't fit tidily into sections " 37.14020 "of their own, but that are good to know. Here they are, in one place." 37.14021 msgstr "" 37.14022 37.14023 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14024 -#: ../en/ch12-mq.xml:985 37.14025 +#: ../en/ch11-mq.xml:979 37.14026 msgid "" 37.14027 "Normally, when you <command role=\"hg-ext-mq\">qpop</command> a patch and " 37.14028 "<command role=\"hg-ext-mq\">qpush</command> it again, the changeset that " 37.14029 @@ -14742,7 +13820,7 @@ 37.14030 msgstr "" 37.14031 37.14032 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14033 -#: ../en/ch12-mq.xml:994 37.14034 +#: ../en/ch11-mq.xml:988 37.14035 msgid "" 37.14036 "It's not a good idea to <command role=\"hg-cmd\">hg merge</command> changes " 37.14037 "from another branch with a patch changeset, at least if you want to maintain " 37.14038 @@ -14752,12 +13830,12 @@ 37.14039 msgstr "" 37.14040 37.14041 #. type: Content of: <book><chapter><sect1><title> 37.14042 -#: ../en/ch12-mq.xml:1005 37.14043 +#: ../en/ch11-mq.xml:999 37.14044 msgid "Managing patches in a repository" 37.14045 msgstr "在版本库管理补丁" 37.14046 37.14047 #. type: Content of: <book><chapter><sect1><para> 37.14048 -#: ../en/ch12-mq.xml:1007 37.14049 +#: ../en/ch11-mq.xml:1001 37.14050 msgid "" 37.14051 "Because MQ's <filename role=\"special\" class=\"directory\">.hg/patches</" 37.14052 "filename> directory resides outside a Mercurial repository's working " 37.14053 @@ -14766,7 +13844,7 @@ 37.14054 msgstr "" 37.14055 37.14056 #. type: Content of: <book><chapter><sect1><para> 37.14057 -#: ../en/ch12-mq.xml:1013 37.14058 +#: ../en/ch11-mq.xml:1007 37.14059 msgid "" 37.14060 "This presents the interesting possibility of managing the contents of the " 37.14061 "patch directory as a Mercurial repository in its own right. This can be a " 37.14062 @@ -14777,7 +13855,7 @@ 37.14063 msgstr "" 37.14064 37.14065 #. type: Content of: <book><chapter><sect1><para> 37.14066 -#: ../en/ch12-mq.xml:1022 37.14067 +#: ../en/ch11-mq.xml:1016 37.14068 msgid "" 37.14069 "You can then share different versions of the same patch stack among multiple " 37.14070 "underlying repositories. I use this when I am developing a Linux kernel " 37.14071 @@ -14789,7 +13867,7 @@ 37.14072 msgstr "" 37.14073 37.14074 #. type: Content of: <book><chapter><sect1><para> 37.14075 -#: ../en/ch12-mq.xml:1032 37.14076 +#: ../en/ch11-mq.xml:1026 37.14077 msgid "" 37.14078 "Managing patches in a repository makes it possible for multiple developers to " 37.14079 "work on the same patch series without colliding with each other, all on top " 37.14080 @@ -14797,12 +13875,12 @@ 37.14081 msgstr "" 37.14082 37.14083 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14084 -#: ../en/ch12-mq.xml:1038 37.14085 +#: ../en/ch11-mq.xml:1032 37.14086 msgid "MQ support for patch repositories" 37.14087 msgstr "MQ 支持补丁版本库" 37.14088 37.14089 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14090 -#: ../en/ch12-mq.xml:1040 37.14091 +#: ../en/ch11-mq.xml:1034 37.14092 msgid "" 37.14093 "MQ helps you to work with the <filename role=\"special\" class=\"directory\">." 37.14094 "hg/patches</filename> directory as a repository; when you prepare a " 37.14095 @@ -14813,7 +13891,7 @@ 37.14096 msgstr "" 37.14097 37.14098 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.14099 -#: ../en/ch12-mq.xml:1050 37.14100 +#: ../en/ch11-mq.xml:1044 37.14101 msgid "" 37.14102 "If you forget to use the <option role=\"hg-ext-mq-cmd-qinit-opt\">hg -c</" 37.14103 "option> option, you can simply go into the <filename role=\"special\" class=" 37.14104 @@ -14824,7 +13902,7 @@ 37.14105 msgstr "" 37.14106 37.14107 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.14108 -#: ../en/ch12-mq.xml:1059 37.14109 +#: ../en/ch11-mq.xml:1053 37.14110 msgid "" 37.14111 "(<command role=\"hg-cmd\">hg qinit <option role=\"hg-ext-mq-cmd-qinit-opt" 37.14112 "\">hg -c</option></command> does this for you automatically); you " 37.14113 @@ -14833,7 +13911,7 @@ 37.14114 msgstr "" 37.14115 37.14116 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14117 -#: ../en/ch12-mq.xml:1066 37.14118 +#: ../en/ch11-mq.xml:1060 37.14119 msgid "" 37.14120 "As a convenience, if MQ notices that the <filename class=\"directory\">.hg/" 37.14121 "patches</filename> directory is a repository, it will automatically <command " 37.14122 @@ -14841,7 +13919,7 @@ 37.14123 msgstr "" 37.14124 37.14125 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14126 -#: ../en/ch12-mq.xml:1071 37.14127 +#: ../en/ch11-mq.xml:1065 37.14128 msgid "" 37.14129 "MQ provides a shortcut command, <command role=\"hg-ext-mq\">qcommit</" 37.14130 "command>, that runs <command role=\"hg-cmd\">hg commit</command> in the " 37.14131 @@ -14850,7 +13928,7 @@ 37.14132 msgstr "" 37.14133 37.14134 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14135 -#: ../en/ch12-mq.xml:1077 37.14136 +#: ../en/ch11-mq.xml:1071 37.14137 msgid "" 37.14138 "Finally, as a convenience to manage the patch directory, you can define the " 37.14139 "alias <command>mq</command> on Unix systems. For example, on Linux systems " 37.14140 @@ -14859,26 +13937,26 @@ 37.14141 msgstr "" 37.14142 37.14143 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14144 -#: ../en/ch12-mq.xml:1087 37.14145 +#: ../en/ch11-mq.xml:1080 37.14146 msgid "" 37.14147 "You can then issue commands of the form <command>mq pull</command> from the " 37.14148 "main repository." 37.14149 msgstr "" 37.14150 37.14151 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14152 -#: ../en/ch12-mq.xml:1092 37.14153 +#: ../en/ch11-mq.xml:1085 37.14154 msgid "A few things to watch out for" 37.14155 msgstr "需要注意的事情" 37.14156 37.14157 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14158 -#: ../en/ch12-mq.xml:1094 37.14159 +#: ../en/ch11-mq.xml:1087 37.14160 msgid "" 37.14161 "MQ's support for working with a repository full of patches is limited in a " 37.14162 "few small respects." 37.14163 msgstr "" 37.14164 37.14165 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14166 -#: ../en/ch12-mq.xml:1097 37.14167 +#: ../en/ch11-mq.xml:1090 37.14168 msgid "" 37.14169 "MQ cannot automatically detect changes that you make to the patch directory. " 37.14170 "If you <command role=\"hg-cmd\">hg pull</command>, manually edit, or <command " 37.14171 @@ -14892,12 +13970,12 @@ 37.14172 msgstr "" 37.14173 37.14174 #. type: Content of: <book><chapter><sect1><title> 37.14175 -#: ../en/ch12-mq.xml:1113 37.14176 +#: ../en/ch11-mq.xml:1106 37.14177 msgid "Third party tools for working with patches" 37.14178 msgstr "操作补丁的第三方工具" 37.14179 37.14180 #. type: Content of: <book><chapter><sect1><para> 37.14181 -#: ../en/ch12-mq.xml:1115 37.14182 +#: ../en/ch11-mq.xml:1108 37.14183 msgid "" 37.14184 "Once you've been working with patches for a while, you'll find yourself " 37.14185 "hungry for tools that will help you to understand and manipulate the patches " 37.14186 @@ -14905,7 +13983,7 @@ 37.14187 msgstr "" 37.14188 37.14189 #. type: Content of: <book><chapter><sect1><para> 37.14190 -#: ../en/ch12-mq.xml:1119 37.14191 +#: ../en/ch11-mq.xml:1112 37.14192 msgid "" 37.14193 "The <command>diffstat</command> command <citation>web:diffstat</citation> " 37.14194 "generates a histogram of the modifications made to each file in a patch. It " 37.14195 @@ -14918,7 +13996,7 @@ 37.14196 msgstr "" 37.14197 37.14198 #. type: Content of: <book><chapter><sect1><para> 37.14199 -#: ../en/ch12-mq.xml:1133 37.14200 +#: ../en/ch11-mq.xml:1126 37.14201 msgid "" 37.14202 "The <literal role=\"package\">patchutils</literal> package <citation>web:" 37.14203 "patchutils</citation> is invaluable. It provides a set of small utilities " 37.14204 @@ -14933,12 +14011,12 @@ 37.14205 msgstr "" 37.14206 37.14207 #. type: Content of: <book><chapter><sect1><title> 37.14208 -#: ../en/ch12-mq.xml:1149 37.14209 +#: ../en/ch11-mq.xml:1142 37.14210 msgid "Good ways to work with patches" 37.14211 msgstr "操作补丁的好习惯" 37.14212 37.14213 #. type: Content of: <book><chapter><sect1><para> 37.14214 -#: ../en/ch12-mq.xml:1151 37.14215 +#: ../en/ch11-mq.xml:1144 37.14216 msgid "" 37.14217 "Whether you are working on a patch series to submit to a free software or " 37.14218 "open source project, or a series that you intend to treat as a sequence of " 37.14219 @@ -14947,7 +14025,7 @@ 37.14220 msgstr "" 37.14221 37.14222 #. type: Content of: <book><chapter><sect1><para> 37.14223 -#: ../en/ch12-mq.xml:1157 37.14224 +#: ../en/ch11-mq.xml:1150 37.14225 msgid "" 37.14226 "Give your patches descriptive names. A good name for a patch might be " 37.14227 "<filename>rework-device-alloc.patch</filename>, because it will immediately " 37.14228 @@ -14961,7 +14039,7 @@ 37.14229 msgstr "" 37.14230 37.14231 #. type: Content of: <book><chapter><sect1><para> 37.14232 -#: ../en/ch12-mq.xml:1169 37.14233 +#: ../en/ch11-mq.xml:1162 37.14234 msgid "" 37.14235 "Be aware of what patch you're working on. Use the <command role=\"hg-ext-mq" 37.14236 "\">qtop</command> command and skim over the text of your patches " 37.14237 @@ -14974,7 +14052,7 @@ 37.14238 msgstr "" 37.14239 37.14240 #. type: Content of: <book><chapter><sect1><para> 37.14241 -#: ../en/ch12-mq.xml:1179 37.14242 +#: ../en/ch11-mq.xml:1172 37.14243 msgid "" 37.14244 "For this reason, it is very much worth investing a little time to learn how " 37.14245 "to use some of the third-party tools I described in section <xref linkend=" 37.14246 @@ -14985,17 +14063,17 @@ 37.14247 msgstr "" 37.14248 37.14249 #. type: Content of: <book><chapter><sect1><title> 37.14250 -#: ../en/ch12-mq.xml:1190 37.14251 +#: ../en/ch11-mq.xml:1183 37.14252 msgid "MQ cookbook" 37.14253 msgstr "MQ 手册" 37.14254 37.14255 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14256 -#: ../en/ch12-mq.xml:1193 37.14257 +#: ../en/ch11-mq.xml:1186 37.14258 msgid "Manage <quote>trivial</quote> patches" 37.14259 msgstr "管理<quote>琐碎的</quote>补丁" 37.14260 37.14261 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14262 -#: ../en/ch12-mq.xml:1195 37.14263 +#: ../en/ch11-mq.xml:1188 37.14264 msgid "" 37.14265 "Because the overhead of dropping files into a new Mercurial repository is so " 37.14266 "low, it makes a lot of sense to manage patches this way even if you simply " 37.14267 @@ -15004,26 +14082,26 @@ 37.14268 37.14269 # 37.14270 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14271 -#: ../en/ch12-mq.xml:1200 37.14272 +#: ../en/ch11-mq.xml:1193 37.14273 msgid "" 37.14274 "Begin by downloading and unpacking the source tarball, and turning it into a " 37.14275 "Mercurial repository." 37.14276 msgstr "" 37.14277 37.14278 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14279 -#: ../en/ch12-mq.xml:1205 37.14280 +#: ../en/ch11-mq.xml:1198 37.14281 msgid "Continue by creating a patch stack and making your changes." 37.14282 msgstr "" 37.14283 37.14284 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14285 -#: ../en/ch12-mq.xml:1210 37.14286 +#: ../en/ch11-mq.xml:1203 37.14287 msgid "" 37.14288 "Let's say a few weeks or months pass, and your package author releases a new " 37.14289 "version. First, bring their changes into the repository." 37.14290 msgstr "" 37.14291 37.14292 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14293 -#: ../en/ch12-mq.xml:1216 37.14294 +#: ../en/ch11-mq.xml:1209 37.14295 msgid "" 37.14296 "The pipeline starting with <command role=\"hg-cmd\">hg locate</command> above " 37.14297 "deletes all files in the working directory, so that <command role=\"hg-cmd" 37.14298 @@ -15033,17 +14111,17 @@ 37.14299 msgstr "" 37.14300 37.14301 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14302 -#: ../en/ch12-mq.xml:1224 37.14303 +#: ../en/ch11-mq.xml:1217 37.14304 msgid "Finally, you can apply your patches on top of the new tree." 37.14305 msgstr "" 37.14306 37.14307 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14308 -#: ../en/ch12-mq.xml:1231 37.14309 +#: ../en/ch11-mq.xml:1224 37.14310 msgid "Combining entire patches" 37.14311 msgstr "组合全部的补丁" 37.14312 37.14313 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14314 -#: ../en/ch12-mq.xml:1233 37.14315 +#: ../en/ch11-mq.xml:1226 37.14316 msgid "" 37.14317 "MQ provides a command, <command role=\"hg-ext-mq\">qfold</command> that lets " 37.14318 "you combine entire patches. This <quote>folds</quote> the patches you name, " 37.14319 @@ -15053,7 +14131,7 @@ 37.14320 msgstr "" 37.14321 37.14322 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14323 -#: ../en/ch12-mq.xml:1241 37.14324 +#: ../en/ch11-mq.xml:1234 37.14325 msgid "" 37.14326 "The order in which you fold patches matters. If your topmost applied patch " 37.14327 "is <literal>foo</literal>, and you <command role=\"hg-ext-mq\">qfold</" 37.14328 @@ -15064,19 +14142,19 @@ 37.14329 msgstr "" 37.14330 37.14331 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14332 -#: ../en/ch12-mq.xml:1252 37.14333 +#: ../en/ch11-mq.xml:1245 37.14334 msgid "Merging part of one patch into another" 37.14335 msgstr "合并补丁的部分内容到其它补丁" 37.14336 37.14337 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14338 -#: ../en/ch12-mq.xml:1254 37.14339 +#: ../en/ch11-mq.xml:1247 37.14340 msgid "" 37.14341 "Merging <emphasis>part</emphasis> of one patch into another is more difficult " 37.14342 "than combining entire patches." 37.14343 msgstr "" 37.14344 37.14345 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14346 -#: ../en/ch12-mq.xml:1258 37.14347 +#: ../en/ch11-mq.xml:1251 37.14348 msgid "" 37.14349 "If you want to move changes to entire files, you can use <command>filterdiff</" 37.14350 "command>'s <option role=\"cmd-opt-filterdiff\">-i</option> and <option role=" 37.14351 @@ -15090,7 +14168,7 @@ 37.14352 msgstr "" 37.14353 37.14354 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14355 -#: ../en/ch12-mq.xml:1271 37.14356 +#: ../en/ch11-mq.xml:1264 37.14357 msgid "" 37.14358 "If you have a patch that has multiple hunks modifying a file, and you only " 37.14359 "want to move a few of those hunks, the job becomes more messy, but you can " 37.14360 @@ -15099,32 +14177,32 @@ 37.14361 msgstr "" 37.14362 37.14363 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14364 -#: ../en/ch12-mq.xml:1279 37.14365 +#: ../en/ch11-mq.xml:1272 37.14366 msgid "This command prints three different kinds of number:" 37.14367 msgstr "" 37.14368 37.14369 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.14370 -#: ../en/ch12-mq.xml:1282 37.14371 +#: ../en/ch11-mq.xml:1275 37.14372 msgid "" 37.14373 "(in the first column) a <emphasis>file number</emphasis> to identify each " 37.14374 "file modified in the patch;" 37.14375 msgstr "" 37.14376 37.14377 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.14378 -#: ../en/ch12-mq.xml:1286 37.14379 +#: ../en/ch11-mq.xml:1279 37.14380 msgid "" 37.14381 "(on the next line, indented) the line number within a modified file where a " 37.14382 "hunk starts; and" 37.14383 msgstr "" 37.14384 37.14385 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.14386 -#: ../en/ch12-mq.xml:1289 37.14387 +#: ../en/ch11-mq.xml:1282 37.14388 msgid "" 37.14389 "(on the same line) a <emphasis>hunk number</emphasis> to identify that hunk." 37.14390 msgstr "" 37.14391 37.14392 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14393 -#: ../en/ch12-mq.xml:1293 37.14394 +#: ../en/ch11-mq.xml:1286 37.14395 msgid "" 37.14396 "You'll have to use some visual inspection, and reading of the patch, to " 37.14397 "identify the file and hunk numbers you'll want, but you can then pass them to " 37.14398 @@ -15134,7 +14212,7 @@ 37.14399 msgstr "" 37.14400 37.14401 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14402 -#: ../en/ch12-mq.xml:1301 37.14403 +#: ../en/ch11-mq.xml:1294 37.14404 msgid "" 37.14405 "Once you have this hunk, you can concatenate it onto the end of your " 37.14406 "destination patch and continue with the remainder of section <xref linkend=" 37.14407 @@ -15142,19 +14220,19 @@ 37.14408 msgstr "" 37.14409 37.14410 #. type: Content of: <book><chapter><sect1><title> 37.14411 -#: ../en/ch12-mq.xml:1308 37.14412 +#: ../en/ch11-mq.xml:1301 37.14413 msgid "Differences between quilt and MQ" 37.14414 msgstr "MQ 与 quilt 的区别" 37.14415 37.14416 #. type: Content of: <book><chapter><sect1><para> 37.14417 -#: ../en/ch12-mq.xml:1310 37.14418 +#: ../en/ch11-mq.xml:1303 37.14419 msgid "" 37.14420 "If you are already familiar with quilt, MQ provides a similar command set. " 37.14421 "There are a few differences in the way that it works." 37.14422 msgstr "" 37.14423 37.14424 #. type: Content of: <book><chapter><sect1><para> 37.14425 -#: ../en/ch12-mq.xml:1314 37.14426 +#: ../en/ch11-mq.xml:1307 37.14427 msgid "" 37.14428 "You will already have noticed that most quilt commands have MQ counterparts " 37.14429 "that simply begin with a <quote><literal>q</literal></quote>. The exceptions " 37.14430 @@ -15166,12 +14244,12 @@ 37.14431 msgstr "" 37.14432 37.14433 #. type: Content of: <book><chapter><title> 37.14434 -#: ../en/ch13-mq-collab.xml:5 37.14435 +#: ../en/ch12-mq-collab.xml:5 37.14436 msgid "Advanced uses of Mercurial Queues" 37.14437 msgstr "MQ 的高级用法" 37.14438 37.14439 #. type: Content of: <book><chapter><para> 37.14440 -#: ../en/ch13-mq-collab.xml:7 37.14441 +#: ../en/ch12-mq-collab.xml:7 37.14442 msgid "" 37.14443 "While it's easy to pick up straightforward uses of Mercurial Queues, use of a " 37.14444 "little discipline and some of MQ's less frequently used capabilities makes it " 37.14445 @@ -15179,7 +14257,7 @@ 37.14446 msgstr "" 37.14447 37.14448 #. type: Content of: <book><chapter><para> 37.14449 -#: ../en/ch13-mq-collab.xml:12 37.14450 +#: ../en/ch12-mq-collab.xml:12 37.14451 msgid "" 37.14452 "In this chapter, I will use as an example a technique I have used to manage " 37.14453 "the development of an Infiniband device driver for the Linux kernel. The " 37.14454 @@ -15189,7 +14267,7 @@ 37.14455 msgstr "" 37.14456 37.14457 #. type: Content of: <book><chapter><para> 37.14458 -#: ../en/ch13-mq-collab.xml:18 37.14459 +#: ../en/ch12-mq-collab.xml:18 37.14460 msgid "" 37.14461 "While much of the material in this chapter is specific to Linux, the same " 37.14462 "principles apply to any code base for which you're not the primary owner, and " 37.14463 @@ -15197,12 +14275,12 @@ 37.14464 msgstr "" 37.14465 37.14466 #. type: Content of: <book><chapter><sect1><title> 37.14467 -#: ../en/ch13-mq-collab.xml:24 37.14468 +#: ../en/ch12-mq-collab.xml:24 37.14469 msgid "The problem of many targets" 37.14470 msgstr "多个目标的问题" 37.14471 37.14472 #. type: Content of: <book><chapter><sect1><para> 37.14473 -#: ../en/ch13-mq-collab.xml:26 37.14474 +#: ../en/ch12-mq-collab.xml:26 37.14475 msgid "" 37.14476 "The Linux kernel changes rapidly, and has never been internally stable; " 37.14477 "developers frequently make drastic changes between releases. This means that " 37.14478 @@ -15212,14 +14290,14 @@ 37.14479 msgstr "" 37.14480 37.14481 #. type: Content of: <book><chapter><sect1><para> 37.14482 -#: ../en/ch13-mq-collab.xml:33 37.14483 +#: ../en/ch12-mq-collab.xml:33 37.14484 msgid "" 37.14485 "To maintain a driver, we have to keep a number of distinct versions of Linux " 37.14486 "in mind." 37.14487 msgstr "" 37.14488 37.14489 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14490 -#: ../en/ch13-mq-collab.xml:36 37.14491 +#: ../en/ch12-mq-collab.xml:36 37.14492 msgid "" 37.14493 "One target is the main Linux kernel development tree. Maintenance of the code " 37.14494 "is in this case partly shared by other developers in the kernel community, " 37.14495 @@ -15228,7 +14306,7 @@ 37.14496 msgstr "" 37.14497 37.14498 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14499 -#: ../en/ch13-mq-collab.xml:42 37.14500 +#: ../en/ch12-mq-collab.xml:42 37.14501 msgid "" 37.14502 "We also maintain a number of <quote>backports</quote> to older versions of " 37.14503 "the Linux kernel, to support the needs of customers who are running older " 37.14504 @@ -15239,7 +14317,7 @@ 37.14505 msgstr "" 37.14506 37.14507 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14508 -#: ../en/ch13-mq-collab.xml:50 37.14509 +#: ../en/ch12-mq-collab.xml:50 37.14510 msgid "" 37.14511 "Finally, we make software releases on a schedule that is necessarily not " 37.14512 "aligned with those used by Linux distributors and kernel developers, so that " 37.14513 @@ -15248,19 +14326,19 @@ 37.14514 msgstr "" 37.14515 37.14516 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14517 -#: ../en/ch13-mq-collab.xml:58 37.14518 +#: ../en/ch12-mq-collab.xml:58 37.14519 msgid "Tempting approaches that don't work well" 37.14520 msgstr "工作不好的诱人方法" 37.14521 37.14522 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14523 -#: ../en/ch13-mq-collab.xml:60 37.14524 +#: ../en/ch12-mq-collab.xml:60 37.14525 msgid "" 37.14526 "There are two <quote>standard</quote> ways to maintain a piece of software " 37.14527 "that has to target many different environments." 37.14528 msgstr "" 37.14529 37.14530 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14531 -#: ../en/ch13-mq-collab.xml:64 37.14532 +#: ../en/ch12-mq-collab.xml:64 37.14533 msgid "" 37.14534 "The first is to maintain a number of branches, each intended for a single " 37.14535 "target. The trouble with this approach is that you must maintain iron " 37.14536 @@ -15272,7 +14350,7 @@ 37.14537 msgstr "" 37.14538 37.14539 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14540 -#: ../en/ch13-mq-collab.xml:74 37.14541 +#: ../en/ch12-mq-collab.xml:74 37.14542 msgid "" 37.14543 "The second is to maintain a single source tree filled with conditional " 37.14544 "statements that turn chunks of code on or off depending on the intended " 37.14545 @@ -15284,7 +14362,7 @@ 37.14546 msgstr "" 37.14547 37.14548 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14549 -#: ../en/ch13-mq-collab.xml:83 37.14550 +#: ../en/ch12-mq-collab.xml:83 37.14551 msgid "" 37.14552 "Neither of these approaches is well suited to a situation where you don't " 37.14553 "<quote>own</quote> the canonical copy of a source tree. In the case of a " 37.14554 @@ -15296,14 +14374,14 @@ 37.14555 msgstr "" 37.14556 37.14557 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14558 -#: ../en/ch13-mq-collab.xml:93 37.14559 +#: ../en/ch12-mq-collab.xml:93 37.14560 msgid "" 37.14561 "These approaches have the added weakness of making it difficult to generate " 37.14562 "well-formed patches to submit upstream." 37.14563 msgstr "" 37.14564 37.14565 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14566 -#: ../en/ch13-mq-collab.xml:97 37.14567 +#: ../en/ch12-mq-collab.xml:97 37.14568 msgid "" 37.14569 "In principle, Mercurial Queues seems like a good candidate to manage a " 37.14570 "development scenario such as the above. While this is indeed the case, MQ " 37.14571 @@ -15311,12 +14389,12 @@ 37.14572 msgstr "" 37.14573 37.14574 #. type: Content of: <book><chapter><sect1><title> 37.14575 -#: ../en/ch13-mq-collab.xml:105 37.14576 +#: ../en/ch12-mq-collab.xml:105 37.14577 msgid "Conditionally applying patches with guards" 37.14578 msgstr "有条件的应用补丁" 37.14579 37.14580 #. type: Content of: <book><chapter><sect1><para> 37.14581 -#: ../en/ch13-mq-collab.xml:107 37.14582 +#: ../en/ch12-mq-collab.xml:107 37.14583 msgid "" 37.14584 "Perhaps the best way to maintain sanity with so many targets is to be able to " 37.14585 "choose specific patches to apply for a given situation. MQ provides a " 37.14586 @@ -15326,14 +14404,14 @@ 37.14587 msgstr "" 37.14588 37.14589 #. type: Content of: <book><chapter><sect1><para> 37.14590 -#: ../en/ch13-mq-collab.xml:116 37.14591 +#: ../en/ch12-mq-collab.xml:116 37.14592 msgid "" 37.14593 "This gives us a tiny repository that contains two patches that don't have any " 37.14594 "dependencies on each other, because they touch different files." 37.14595 msgstr "" 37.14596 37.14597 #. type: Content of: <book><chapter><sect1><para> 37.14598 -#: ../en/ch13-mq-collab.xml:120 37.14599 +#: ../en/ch12-mq-collab.xml:120 37.14600 msgid "" 37.14601 "The idea behind conditional application is that you can <quote>tag</quote> a " 37.14602 "patch with a <emphasis>guard</emphasis>, which is simply a text string of " 37.14603 @@ -15343,7 +14421,7 @@ 37.14604 msgstr "" 37.14605 37.14606 #. type: Content of: <book><chapter><sect1><para> 37.14607 -#: ../en/ch13-mq-collab.xml:127 37.14608 +#: ../en/ch12-mq-collab.xml:127 37.14609 msgid "" 37.14610 "A patch can have an arbitrary number of guards; each one is " 37.14611 "<emphasis>positive</emphasis> (<quote>apply this patch if this guard is " 37.14612 @@ -15352,12 +14430,12 @@ 37.14613 msgstr "" 37.14614 37.14615 #. type: Content of: <book><chapter><sect1><title> 37.14616 -#: ../en/ch13-mq-collab.xml:135 37.14617 +#: ../en/ch12-mq-collab.xml:135 37.14618 msgid "Controlling the guards on a patch" 37.14619 msgstr "控制补丁的应用条件" 37.14620 37.14621 #. type: Content of: <book><chapter><sect1><para> 37.14622 -#: ../en/ch13-mq-collab.xml:137 37.14623 +#: ../en/ch12-mq-collab.xml:137 37.14624 msgid "" 37.14625 "The <command role=\"hg-ext-mq\">qguard</command> command lets you determine " 37.14626 "which guards should apply to a patch, or display the guards that are already " 37.14627 @@ -15366,21 +14444,21 @@ 37.14628 msgstr "" 37.14629 37.14630 #. type: Content of: <book><chapter><sect1><para> 37.14631 -#: ../en/ch13-mq-collab.xml:144 37.14632 +#: ../en/ch12-mq-collab.xml:144 37.14633 msgid "" 37.14634 "To set a positive guard on a patch, prefix the name of the guard with a " 37.14635 "<quote><literal>+</literal></quote>." 37.14636 msgstr "" 37.14637 37.14638 #. type: Content of: <book><chapter><sect1><para> 37.14639 -#: ../en/ch13-mq-collab.xml:149 37.14640 +#: ../en/ch12-mq-collab.xml:149 37.14641 msgid "" 37.14642 "To set a negative guard on a patch, prefix the name of the guard with a " 37.14643 "<quote><literal>-</literal></quote>." 37.14644 msgstr "" 37.14645 37.14646 #. type: Content of: <book><chapter><sect1><note><para> 37.14647 -#: ../en/ch13-mq-collab.xml:156 37.14648 +#: ../en/ch12-mq-collab.xml:156 37.14649 msgid "" 37.14650 "The <command role=\"hg-ext-mq\">qguard</command> command <emphasis>sets</" 37.14651 "emphasis> the guards on a patch; it doesn't <emphasis>modify</emphasis> " 37.14652 @@ -15392,7 +14470,7 @@ 37.14653 37.14654 # 37.14655 #. type: Content of: <book><chapter><sect1><para> 37.14656 -#: ../en/ch13-mq-collab.xml:165 37.14657 +#: ../en/ch12-mq-collab.xml:165 37.14658 msgid "" 37.14659 "Mercurial stores guards in the <filename role=\"special\">series</filename> " 37.14660 "file; the form in which they are stored is easy both to understand and to " 37.14661 @@ -15402,12 +14480,12 @@ 37.14662 msgstr "" 37.14663 37.14664 #. type: Content of: <book><chapter><sect1><title> 37.14665 -#: ../en/ch13-mq-collab.xml:177 37.14666 +#: ../en/ch12-mq-collab.xml:177 37.14667 msgid "Selecting the guards to use" 37.14668 msgstr "选择使用的条件" 37.14669 37.14670 #. type: Content of: <book><chapter><sect1><para> 37.14671 -#: ../en/ch13-mq-collab.xml:179 37.14672 +#: ../en/ch12-mq-collab.xml:179 37.14673 msgid "" 37.14674 "The <command role=\"hg-ext-mq\">qselect</command> command determines which " 37.14675 "guards are active at a given time. The effect of this is to determine which " 37.14676 @@ -15417,7 +14495,7 @@ 37.14677 msgstr "" 37.14678 37.14679 #. type: Content of: <book><chapter><sect1><para> 37.14680 -#: ../en/ch13-mq-collab.xml:186 37.14681 +#: ../en/ch12-mq-collab.xml:186 37.14682 msgid "" 37.14683 "With no arguments, the <command role=\"hg-ext-mq\">qselect</command> command " 37.14684 "lists the guards currently in effect, one per line of output. Each argument " 37.14685 @@ -15425,21 +14503,21 @@ 37.14686 msgstr "" 37.14687 37.14688 #. type: Content of: <book><chapter><sect1><para> 37.14689 -#: ../en/ch13-mq-collab.xml:193 37.14690 +#: ../en/ch12-mq-collab.xml:193 37.14691 msgid "" 37.14692 "In case you're interested, the currently selected guards are stored in the " 37.14693 "<filename role=\"special\">guards</filename> file." 37.14694 msgstr "" 37.14695 37.14696 #. type: Content of: <book><chapter><sect1><para> 37.14697 -#: ../en/ch13-mq-collab.xml:198 37.14698 +#: ../en/ch12-mq-collab.xml:198 37.14699 msgid "" 37.14700 "We can see the effect the selected guards have when we run <command role=\"hg-" 37.14701 "ext-mq\">qpush</command>." 37.14702 msgstr "" 37.14703 37.14704 #. type: Content of: <book><chapter><sect1><para> 37.14705 -#: ../en/ch13-mq-collab.xml:203 37.14706 +#: ../en/ch12-mq-collab.xml:203 37.14707 msgid "" 37.14708 "A guard cannot start with a <quote><literal>+</literal></quote> or " 37.14709 "<quote><literal>-</literal></quote> character. The name of a guard must not " 37.14710 @@ -15448,61 +14526,61 @@ 37.14711 msgstr "" 37.14712 37.14713 #. type: Content of: <book><chapter><sect1><para> 37.14714 -#: ../en/ch13-mq-collab.xml:212 37.14715 +#: ../en/ch12-mq-collab.xml:212 37.14716 msgid "Changing the selected guards changes the patches that are applied." 37.14717 msgstr "" 37.14718 37.14719 #. type: Content of: <book><chapter><sect1><para> 37.14720 -#: ../en/ch13-mq-collab.xml:217 37.14721 +#: ../en/ch12-mq-collab.xml:217 37.14722 msgid "" 37.14723 "You can see in the example below that negative guards take precedence over " 37.14724 "positive guards." 37.14725 msgstr "" 37.14726 37.14727 #. type: Content of: <book><chapter><sect1><title> 37.14728 -#: ../en/ch13-mq-collab.xml:224 37.14729 +#: ../en/ch12-mq-collab.xml:224 37.14730 msgid "MQ's rules for applying patches" 37.14731 msgstr "MQ 应用补丁的规则" 37.14732 37.14733 #. type: Content of: <book><chapter><sect1><para> 37.14734 -#: ../en/ch13-mq-collab.xml:226 37.14735 +#: ../en/ch12-mq-collab.xml:226 37.14736 msgid "" 37.14737 "The rules that MQ uses when deciding whether to apply a patch are as follows." 37.14738 msgstr "" 37.14739 37.14740 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14741 -#: ../en/ch13-mq-collab.xml:229 37.14742 +#: ../en/ch12-mq-collab.xml:229 37.14743 msgid "A patch that has no guards is always applied." 37.14744 msgstr "" 37.14745 37.14746 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14747 -#: ../en/ch13-mq-collab.xml:232 37.14748 +#: ../en/ch12-mq-collab.xml:232 37.14749 msgid "" 37.14750 "If the patch has any negative guard that matches any currently selected " 37.14751 "guard, the patch is skipped." 37.14752 msgstr "" 37.14753 37.14754 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14755 -#: ../en/ch13-mq-collab.xml:235 37.14756 +#: ../en/ch12-mq-collab.xml:235 37.14757 msgid "" 37.14758 "If the patch has any positive guard that matches any currently selected " 37.14759 "guard, the patch is applied." 37.14760 msgstr "" 37.14761 37.14762 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14763 -#: ../en/ch13-mq-collab.xml:238 37.14764 +#: ../en/ch12-mq-collab.xml:238 37.14765 msgid "" 37.14766 "If the patch has positive or negative guards, but none matches any currently " 37.14767 "selected guard, the patch is skipped." 37.14768 msgstr "" 37.14769 37.14770 #. type: Content of: <book><chapter><sect1><title> 37.14771 -#: ../en/ch13-mq-collab.xml:245 37.14772 +#: ../en/ch12-mq-collab.xml:245 37.14773 msgid "Trimming the work environment" 37.14774 msgstr "修剪工作环境" 37.14775 37.14776 #. type: Content of: <book><chapter><sect1><para> 37.14777 -#: ../en/ch13-mq-collab.xml:247 37.14778 +#: ../en/ch12-mq-collab.xml:247 37.14779 msgid "" 37.14780 "In working on the device driver I mentioned earlier, I don't apply the " 37.14781 "patches to a normal Linux kernel tree. Instead, I use a repository that " 37.14782 @@ -15512,7 +14590,7 @@ 37.14783 msgstr "" 37.14784 37.14785 #. type: Content of: <book><chapter><sect1><para> 37.14786 -#: ../en/ch13-mq-collab.xml:254 37.14787 +#: ../en/ch12-mq-collab.xml:254 37.14788 msgid "" 37.14789 "I then choose a <quote>base</quote> version on top of which the patches are " 37.14790 "applied. This is a snapshot of the Linux kernel tree as of a revision of my " 37.14791 @@ -15524,7 +14602,7 @@ 37.14792 msgstr "" 37.14793 37.14794 #. type: Content of: <book><chapter><sect1><para> 37.14795 -#: ../en/ch13-mq-collab.xml:263 37.14796 +#: ../en/ch12-mq-collab.xml:263 37.14797 msgid "" 37.14798 "Normally, the base tree atop which the patches apply should be a snapshot of " 37.14799 "a very recent upstream tree. This best facilitates the development of " 37.14800 @@ -15532,12 +14610,12 @@ 37.14801 msgstr "" 37.14802 37.14803 #. type: Content of: <book><chapter><sect1><title> 37.14804 -#: ../en/ch13-mq-collab.xml:270 37.14805 +#: ../en/ch12-mq-collab.xml:270 37.14806 msgid "Dividing up the <filename role=\"special\">series</filename> file" 37.14807 msgstr "分类补丁<filename role=\"special\">系列</filename>" 37.14808 37.14809 #. type: Content of: <book><chapter><sect1><para> 37.14810 -#: ../en/ch13-mq-collab.xml:273 37.14811 +#: ../en/ch12-mq-collab.xml:273 37.14812 msgid "" 37.14813 "I categorise the patches in the <filename role=\"special\">series</filename> " 37.14814 "file into a number of logical groups. Each section of like patches begins " 37.14815 @@ -15546,14 +14624,14 @@ 37.14816 msgstr "" 37.14817 37.14818 #. type: Content of: <book><chapter><sect1><para> 37.14819 -#: ../en/ch13-mq-collab.xml:279 37.14820 +#: ../en/ch12-mq-collab.xml:279 37.14821 msgid "" 37.14822 "The sequence of patch groups that I maintain follows. The ordering of these " 37.14823 "groups is important; I'll describe why after I introduce the groups." 37.14824 msgstr "" 37.14825 37.14826 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14827 -#: ../en/ch13-mq-collab.xml:283 37.14828 +#: ../en/ch12-mq-collab.xml:283 37.14829 msgid "" 37.14830 "The <quote>accepted</quote> group. Patches that the development team has " 37.14831 "submitted to the maintainer of the Infiniband subsystem, and which he has " 37.14832 @@ -15564,14 +14642,14 @@ 37.14833 msgstr "" 37.14834 37.14835 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14836 -#: ../en/ch13-mq-collab.xml:291 37.14837 +#: ../en/ch12-mq-collab.xml:291 37.14838 msgid "" 37.14839 "The <quote>rework</quote> group. Patches that I have submitted, but that the " 37.14840 "upstream maintainer has requested modifications to before he will accept them." 37.14841 msgstr "" 37.14842 37.14843 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14844 -#: ../en/ch13-mq-collab.xml:296 37.14845 +#: ../en/ch12-mq-collab.xml:296 37.14846 msgid "" 37.14847 "The <quote>pending</quote> group. Patches that I have not yet submitted to " 37.14848 "the upstream maintainer, but which we have finished working on. These will be " 37.14849 @@ -15582,21 +14660,21 @@ 37.14850 msgstr "" 37.14851 37.14852 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14853 -#: ../en/ch13-mq-collab.xml:305 37.14854 +#: ../en/ch12-mq-collab.xml:305 37.14855 msgid "" 37.14856 "The <quote>in progress</quote> group. Patches that are actively being " 37.14857 "developed, and should not be submitted anywhere yet." 37.14858 msgstr "" 37.14859 37.14860 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14861 -#: ../en/ch13-mq-collab.xml:309 37.14862 +#: ../en/ch12-mq-collab.xml:309 37.14863 msgid "" 37.14864 "The <quote>backport</quote> group. Patches that adapt the source tree to " 37.14865 "older versions of the kernel tree." 37.14866 msgstr "" 37.14867 37.14868 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14869 -#: ../en/ch13-mq-collab.xml:313 37.14870 +#: ../en/ch12-mq-collab.xml:313 37.14871 msgid "" 37.14872 "The <quote>do not ship</quote> group. Patches that for some reason should " 37.14873 "never be submitted upstream. For example, one such patch might change " 37.14874 @@ -15606,7 +14684,7 @@ 37.14875 msgstr "" 37.14876 37.14877 #. type: Content of: <book><chapter><sect1><para> 37.14878 -#: ../en/ch13-mq-collab.xml:321 37.14879 +#: ../en/ch12-mq-collab.xml:321 37.14880 msgid "" 37.14881 "Now to return to the reasons for ordering groups of patches in this way. We " 37.14882 "would like the lowest patches in the stack to be as stable as possible, so " 37.14883 @@ -15616,7 +14694,7 @@ 37.14884 msgstr "" 37.14885 37.14886 #. type: Content of: <book><chapter><sect1><para> 37.14887 -#: ../en/ch13-mq-collab.xml:329 37.14888 +#: ../en/ch12-mq-collab.xml:329 37.14889 msgid "" 37.14890 "We would also like the patches that we know we'll need to modify to be " 37.14891 "applied on top of a source tree that resembles the upstream tree as closely " 37.14892 @@ -15624,7 +14702,7 @@ 37.14893 msgstr "" 37.14894 37.14895 #. type: Content of: <book><chapter><sect1><para> 37.14896 -#: ../en/ch13-mq-collab.xml:334 37.14897 +#: ../en/ch12-mq-collab.xml:334 37.14898 msgid "" 37.14899 "The <quote>backport</quote> and <quote>do not ship</quote> patches float at " 37.14900 "the end of the <filename role=\"special\">series</filename> file. The " 37.14901 @@ -15633,19 +14711,19 @@ 37.14902 msgstr "" 37.14903 37.14904 #. type: Content of: <book><chapter><sect1><title> 37.14905 -#: ../en/ch13-mq-collab.xml:343 37.14906 +#: ../en/ch12-mq-collab.xml:343 37.14907 msgid "Maintaining the patch series" 37.14908 msgstr "维护补丁系列" 37.14909 37.14910 #. type: Content of: <book><chapter><sect1><para> 37.14911 -#: ../en/ch13-mq-collab.xml:345 37.14912 +#: ../en/ch12-mq-collab.xml:345 37.14913 msgid "" 37.14914 "In my work, I use a number of guards to control which patches are to be " 37.14915 "applied." 37.14916 msgstr "" 37.14917 37.14918 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14919 -#: ../en/ch13-mq-collab.xml:349 37.14920 +#: ../en/ch12-mq-collab.xml:349 37.14921 msgid "" 37.14922 "<quote>Accepted</quote> patches are guarded with <literal>accepted</" 37.14923 "literal>. I enable this guard most of the time. When I'm applying the " 37.14924 @@ -15654,7 +14732,7 @@ 37.14925 msgstr "" 37.14926 37.14927 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14928 -#: ../en/ch13-mq-collab.xml:356 37.14929 +#: ../en/ch12-mq-collab.xml:356 37.14930 msgid "" 37.14931 "Patches that are <quote>finished</quote>, but not yet submitted, have no " 37.14932 "guards. If I'm applying the patch stack to a copy of the upstream tree, I " 37.14933 @@ -15662,21 +14740,21 @@ 37.14934 msgstr "" 37.14935 37.14936 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14937 -#: ../en/ch13-mq-collab.xml:362 37.14938 +#: ../en/ch12-mq-collab.xml:362 37.14939 msgid "" 37.14940 "Those patches that need reworking before being resubmitted are guarded with " 37.14941 "<literal>rework</literal>." 37.14942 msgstr "" 37.14943 37.14944 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14945 -#: ../en/ch13-mq-collab.xml:366 37.14946 +#: ../en/ch12-mq-collab.xml:366 37.14947 msgid "" 37.14948 "For those patches that are still under development, I use <literal>devel</" 37.14949 "literal>." 37.14950 msgstr "" 37.14951 37.14952 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.14953 -#: ../en/ch13-mq-collab.xml:369 37.14954 +#: ../en/ch12-mq-collab.xml:369 37.14955 msgid "" 37.14956 "A backport patch may have several guards, one for each version of the kernel " 37.14957 "to which it applies. For example, a patch that backports a piece of code to " 37.14958 @@ -15684,7 +14762,7 @@ 37.14959 msgstr "" 37.14960 37.14961 #. type: Content of: <book><chapter><sect1><para> 37.14962 -#: ../en/ch13-mq-collab.xml:374 37.14963 +#: ../en/ch12-mq-collab.xml:374 37.14964 msgid "" 37.14965 "This variety of guards gives me considerable flexibility in determining what " 37.14966 "kind of source tree I want to end up with. For most situations, the " 37.14967 @@ -15693,12 +14771,12 @@ 37.14968 msgstr "" 37.14969 37.14970 #. type: Content of: <book><chapter><sect1><sect2><title> 37.14971 -#: ../en/ch13-mq-collab.xml:381 37.14972 +#: ../en/ch12-mq-collab.xml:381 37.14973 msgid "The art of writing backport patches" 37.14974 msgstr "编写向后移植补丁的艺术" 37.14975 37.14976 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14977 -#: ../en/ch13-mq-collab.xml:383 37.14978 +#: ../en/ch12-mq-collab.xml:383 37.14979 msgid "" 37.14980 "Using MQ, writing a backport patch is a simple process. All such a patch has " 37.14981 "to do is modify a piece of code that uses a kernel feature not present in the " 37.14982 @@ -15707,7 +14785,7 @@ 37.14983 msgstr "" 37.14984 37.14985 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14986 -#: ../en/ch13-mq-collab.xml:389 37.14987 +#: ../en/ch12-mq-collab.xml:389 37.14988 msgid "" 37.14989 "A useful goal when writing a good backport patch is to make your code look as " 37.14990 "if it was written for the older version of the kernel you're targeting. The " 37.14991 @@ -15721,7 +14799,7 @@ 37.14992 msgstr "" 37.14993 37.14994 #. type: Content of: <book><chapter><sect1><sect2><para> 37.14995 -#: ../en/ch13-mq-collab.xml:402 37.14996 +#: ../en/ch12-mq-collab.xml:402 37.14997 msgid "" 37.14998 "There are two reasons to divide backport patches into a distinct group, away " 37.14999 "from the <quote>regular</quote> patches whose effects they modify. The first " 37.15000 @@ -15734,17 +14812,17 @@ 37.15001 msgstr "" 37.15002 37.15003 #. type: Content of: <book><chapter><sect1><title> 37.15004 -#: ../en/ch13-mq-collab.xml:417 37.15005 +#: ../en/ch12-mq-collab.xml:417 37.15006 msgid "Useful tips for developing with MQ" 37.15007 msgstr "使用 MQ 开发的技巧" 37.15008 37.15009 #. type: Content of: <book><chapter><sect1><sect2><title> 37.15010 -#: ../en/ch13-mq-collab.xml:420 37.15011 +#: ../en/ch12-mq-collab.xml:420 37.15012 msgid "Organising patches in directories" 37.15013 msgstr "将补丁放到几个目录中" 37.15014 37.15015 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15016 -#: ../en/ch13-mq-collab.xml:422 37.15017 +#: ../en/ch12-mq-collab.xml:422 37.15018 msgid "" 37.15019 "If you're working on a substantial project with MQ, it's not difficult to " 37.15020 "accumulate a large number of patches. For example, I have one patch " 37.15021 @@ -15752,7 +14830,7 @@ 37.15022 msgstr "" 37.15023 37.15024 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15025 -#: ../en/ch13-mq-collab.xml:427 37.15026 +#: ../en/ch12-mq-collab.xml:427 37.15027 msgid "" 37.15028 "If you can group these patches into separate logical categories, you can if " 37.15029 "you like store them in different directories; MQ has no problems with patch " 37.15030 @@ -15760,12 +14838,12 @@ 37.15031 msgstr "" 37.15032 37.15033 #. type: Content of: <book><chapter><sect1><sect2><title> 37.15034 -#: ../en/ch13-mq-collab.xml:434 37.15035 +#: ../en/ch12-mq-collab.xml:434 37.15036 msgid "Viewing the history of a patch" 37.15037 msgstr "察看补丁的历史" 37.15038 37.15039 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15040 -#: ../en/ch13-mq-collab.xml:436 37.15041 +#: ../en/ch12-mq-collab.xml:436 37.15042 msgid "" 37.15043 "If you're developing a set of patches over a long time, it's a good idea to " 37.15044 "maintain them in a repository, as discussed in section <xref linkend=\"sec.mq." 37.15045 @@ -15778,7 +14856,7 @@ 37.15046 msgstr "" 37.15047 37.15048 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15049 -#: ../en/ch13-mq-collab.xml:448 37.15050 +#: ../en/ch12-mq-collab.xml:448 37.15051 msgid "" 37.15052 "However, you can use the <literal role=\"hg-ext\">extdiff</literal> " 37.15053 "extension, which is bundled with Mercurial, to turn a diff of two versions of " 37.15054 @@ -15791,18 +14869,18 @@ 37.15055 msgstr "" 37.15056 37.15057 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15058 -#: ../en/ch13-mq-collab.xml:459 37.15059 +#: ../en/ch12-mq-collab.xml:459 37.15060 msgid "" 37.15061 "You can enable the <literal role=\"hg-ext\">extdiff</literal> extension in " 37.15062 "the usual way, by adding a line to the <literal role=\"rc-extensions" 37.15063 -"\">extensions</literal> section of your <filename role=\"special\"> /.hgrc</" 37.15064 +"\">extensions</literal> section of your <filename role=\"special\">~/.hgrc</" 37.15065 "filename>." 37.15066 msgstr "" 37.15067 37.15068 # 37.15069 #. &example.hg-interdiff; 37.15070 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15071 -#: ../en/ch13-mq-collab.xml:465 37.15072 +#: ../en/ch12-mq-collab.xml:466 37.15073 msgid "" 37.15074 "The <command>interdiff</command> command expects to be passed the names of " 37.15075 "two files, but the <literal role=\"hg-ext\">extdiff</literal> extension " 37.15076 @@ -15815,7 +14893,7 @@ 37.15077 msgstr "" 37.15078 37.15079 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15080 -#: ../en/ch13-mq-collab.xml:477 37.15081 +#: ../en/ch12-mq-collab.xml:478 37.15082 msgid "" 37.15083 "With the <filename role=\"special\">hg-interdiff</filename> program in your " 37.15084 "shell's search path, you can run it as follows, from inside an MQ patch " 37.15085 @@ -15823,16 +14901,16 @@ 37.15086 msgstr "" 37.15087 37.15088 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15089 -#: ../en/ch13-mq-collab.xml:482 37.15090 +#: ../en/ch12-mq-collab.xml:482 37.15091 msgid "" 37.15092 "Since you'll probably want to use this long-winded command a lot, you can get " 37.15093 "<literal role=\"hg-ext\">hgext</literal> to make it available as a normal " 37.15094 -"Mercurial command, again by editing your <filename role=\"special\"> /.hgrc</" 37.15095 +"Mercurial command, again by editing your <filename role=\"special\">~/.hgrc</" 37.15096 "filename>." 37.15097 msgstr "" 37.15098 37.15099 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15100 -#: ../en/ch13-mq-collab.xml:489 37.15101 +#: ../en/ch12-mq-collab.xml:489 37.15102 msgid "" 37.15103 "This directs <literal role=\"hg-ext\">hgext</literal> to make an " 37.15104 "<literal>interdiff</literal> command available, so you can now shorten the " 37.15105 @@ -15841,7 +14919,7 @@ 37.15106 msgstr "" 37.15107 37.15108 #. type: Content of: <book><chapter><sect1><sect2><note><para> 37.15109 -#: ../en/ch13-mq-collab.xml:498 37.15110 +#: ../en/ch12-mq-collab.xml:497 37.15111 msgid "" 37.15112 "The <command>interdiff</command> command works well only if the underlying " 37.15113 "files against which versions of a patch are generated remain the same. If " 37.15114 @@ -15850,7 +14928,7 @@ 37.15115 msgstr "" 37.15116 37.15117 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15118 -#: ../en/ch13-mq-collab.xml:506 37.15119 +#: ../en/ch12-mq-collab.xml:505 37.15120 msgid "" 37.15121 "The <literal role=\"hg-ext\">extdiff</literal> extension is useful for more " 37.15122 "than merely improving the presentation of MQ patches. To read more about it, " 37.15123 @@ -15858,12 +14936,12 @@ 37.15124 msgstr "" 37.15125 37.15126 #. type: Content of: <book><chapter><title> 37.15127 -#: ../en/ch14-hgext.xml:5 37.15128 +#: ../en/ch13-hgext.xml:5 37.15129 msgid "Adding functionality with extensions" 37.15130 msgstr "使用扩展增加功能" 37.15131 37.15132 #. type: Content of: <book><chapter><para> 37.15133 -#: ../en/ch14-hgext.xml:7 37.15134 +#: ../en/ch13-hgext.xml:7 37.15135 msgid "" 37.15136 "While the core of Mercurial is quite complete from a functionality " 37.15137 "standpoint, it's deliberately shorn of fancy features. This approach of " 37.15138 @@ -15872,7 +14950,7 @@ 37.15139 msgstr "" 37.15140 37.15141 #. type: Content of: <book><chapter><para> 37.15142 -#: ../en/ch14-hgext.xml:12 37.15143 +#: ../en/ch13-hgext.xml:12 37.15144 msgid "" 37.15145 "However, Mercurial doesn't box you in with an inflexible command set: you can " 37.15146 "add features to it as <emphasis>extensions</emphasis> (sometimes known as " 37.15147 @@ -15881,7 +14959,7 @@ 37.15148 msgstr "" 37.15149 37.15150 #. type: Content of: <book><chapter><itemizedlist><listitem><para> 37.15151 -#: ../en/ch14-hgext.xml:18 37.15152 +#: ../en/ch13-hgext.xml:18 37.15153 msgid "" 37.15154 "Section <xref linkend=\"sec.tour-merge.fetch\"/> covers the <literal role=" 37.15155 "\"hg-ext\">fetch</literal> extension; this combines pulling new changes and " 37.15156 @@ -15890,7 +14968,7 @@ 37.15157 msgstr "" 37.15158 37.15159 #. type: Content of: <book><chapter><itemizedlist><listitem><para> 37.15160 -#: ../en/ch14-hgext.xml:24 37.15161 +#: ../en/ch13-hgext.xml:24 37.15162 msgid "" 37.15163 "In chapter <xref linkend=\"chap.hook\"/>, we covered several extensions that " 37.15164 "are useful for hook-related functionality: <literal role=\"hg-ext\">acl</" 37.15165 @@ -15900,7 +14978,7 @@ 37.15166 msgstr "" 37.15167 37.15168 #. type: Content of: <book><chapter><itemizedlist><listitem><para> 37.15169 -#: ../en/ch14-hgext.xml:33 37.15170 +#: ../en/ch13-hgext.xml:33 37.15171 msgid "" 37.15172 "The Mercurial Queues patch management extension is so invaluable that it " 37.15173 "merits two chapters and an appendix all to itself. Chapter <xref linkend=" 37.15174 @@ -15910,7 +14988,7 @@ 37.15175 msgstr "" 37.15176 37.15177 #. type: Content of: <book><chapter><para> 37.15178 -#: ../en/ch14-hgext.xml:43 37.15179 +#: ../en/ch13-hgext.xml:43 37.15180 msgid "" 37.15181 "In this chapter, we'll cover some of the other extensions that are available " 37.15182 "for Mercurial, and briefly touch on some of the machinery you'll need to know " 37.15183 @@ -15918,7 +14996,7 @@ 37.15184 msgstr "" 37.15185 37.15186 #. type: Content of: <book><chapter><itemizedlist><listitem><para> 37.15187 -#: ../en/ch14-hgext.xml:48 37.15188 +#: ../en/ch13-hgext.xml:48 37.15189 msgid "" 37.15190 "In section <xref linkend=\"sec.hgext.inotify\"/>, we'll discuss the " 37.15191 "possibility of <emphasis>huge</emphasis> performance improvements using the " 37.15192 @@ -15926,21 +15004,21 @@ 37.15193 msgstr "" 37.15194 37.15195 #. type: Content of: <book><chapter><sect1><title> 37.15196 -#: ../en/ch14-hgext.xml:55 37.15197 +#: ../en/ch13-hgext.xml:55 37.15198 msgid "" 37.15199 "Improve performance with the <literal role=\"hg-ext\">inotify</literal> " 37.15200 "extension" 37.15201 msgstr "使用扩展 <literal role=\"hg-ext\">inotify</literal> 以提高性能" 37.15202 37.15203 #. type: Content of: <book><chapter><sect1><para> 37.15204 -#: ../en/ch14-hgext.xml:58 37.15205 +#: ../en/ch13-hgext.xml:58 37.15206 msgid "" 37.15207 "Are you interested in having some of the most common Mercurial operations run " 37.15208 "as much as a hundred times faster? Read on!" 37.15209 msgstr "" 37.15210 37.15211 #. type: Content of: <book><chapter><sect1><para> 37.15212 -#: ../en/ch14-hgext.xml:62 37.15213 +#: ../en/ch13-hgext.xml:62 37.15214 msgid "" 37.15215 "Mercurial has great performance under normal circumstances. For example, " 37.15216 "when you run the <command role=\"hg-cmd\">hg status</command> command, " 37.15217 @@ -15952,7 +15030,7 @@ 37.15218 msgstr "" 37.15219 37.15220 #. type: Content of: <book><chapter><sect1><para> 37.15221 -#: ../en/ch14-hgext.xml:72 37.15222 +#: ../en/ch13-hgext.xml:72 37.15223 msgid "" 37.15224 "Because obtaining file status is crucial to good performance, the authors of " 37.15225 "Mercurial have optimised this code to within an inch of its life. However, " 37.15226 @@ -15964,7 +15042,7 @@ 37.15227 msgstr "" 37.15228 37.15229 #. type: Content of: <book><chapter><sect1><para> 37.15230 -#: ../en/ch14-hgext.xml:82 37.15231 +#: ../en/ch13-hgext.xml:82 37.15232 msgid "" 37.15233 "To put a number on the magnitude of this effect, I created a repository " 37.15234 "containing 150,000 managed files. I timed <command role=\"hg-cmd\">hg " 37.15235 @@ -15973,7 +15051,7 @@ 37.15236 msgstr "" 37.15237 37.15238 #. type: Content of: <book><chapter><sect1><para> 37.15239 -#: ../en/ch14-hgext.xml:88 37.15240 +#: ../en/ch13-hgext.xml:88 37.15241 msgid "" 37.15242 "Many modern operating systems contain a file notification facility. If a " 37.15243 "program signs up to an appropriate service, the operating system will notify " 37.15244 @@ -15983,7 +15061,7 @@ 37.15245 msgstr "" 37.15246 37.15247 #. type: Content of: <book><chapter><sect1><para> 37.15248 -#: ../en/ch14-hgext.xml:95 37.15249 +#: ../en/ch13-hgext.xml:95 37.15250 msgid "" 37.15251 "Mercurial's <literal role=\"hg-ext\">inotify</literal> extension talks to the " 37.15252 "kernel's <literal>inotify</literal> component to optimise <command role=\"hg-" 37.15253 @@ -15998,7 +15076,7 @@ 37.15254 msgstr "" 37.15255 37.15256 #. type: Content of: <book><chapter><sect1><para> 37.15257 -#: ../en/ch14-hgext.xml:108 37.15258 +#: ../en/ch13-hgext.xml:108 37.15259 msgid "" 37.15260 "Recall the ten seconds that I measured plain Mercurial as taking to run " 37.15261 "<command role=\"hg-cmd\">hg status</command> on a 150,000 file repository. " 37.15262 @@ -16008,12 +15086,12 @@ 37.15263 msgstr "" 37.15264 37.15265 #. type: Content of: <book><chapter><sect1><para> 37.15266 -#: ../en/ch14-hgext.xml:115 37.15267 +#: ../en/ch13-hgext.xml:115 37.15268 msgid "Before we continue, please pay attention to some caveats." 37.15269 msgstr "" 37.15270 37.15271 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.15272 -#: ../en/ch14-hgext.xml:118 37.15273 +#: ../en/ch13-hgext.xml:118 37.15274 msgid "" 37.15275 "The <literal role=\"hg-ext\">inotify</literal> extension is Linux-specific. " 37.15276 "Because it interfaces directly to the Linux kernel's <literal>inotify</" 37.15277 @@ -16021,7 +15099,7 @@ 37.15278 msgstr "" 37.15279 37.15280 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.15281 -#: ../en/ch14-hgext.xml:123 37.15282 +#: ../en/ch13-hgext.xml:123 37.15283 msgid "" 37.15284 "It should work on any Linux distribution that was released after early 2005. " 37.15285 "Older distributions are likely to have a kernel that lacks <literal>inotify</" 37.15286 @@ -16030,7 +15108,7 @@ 37.15287 msgstr "" 37.15288 37.15289 #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> 37.15290 -#: ../en/ch14-hgext.xml:130 37.15291 +#: ../en/ch13-hgext.xml:130 37.15292 msgid "" 37.15293 "Not all filesystems are suitable for use with the <literal role=\"hg-ext" 37.15294 "\">inotify</literal> extension. Network filesystems such as NFS are a non-" 37.15295 @@ -16042,7 +15120,7 @@ 37.15296 msgstr "" 37.15297 37.15298 #. type: Content of: <book><chapter><sect1><para> 37.15299 -#: ../en/ch14-hgext.xml:141 37.15300 +#: ../en/ch13-hgext.xml:141 37.15301 msgid "" 37.15302 "The <literal role=\"hg-ext\">inotify</literal> extension is not yet shipped " 37.15303 "with Mercurial as of May 2007, so it's a little more involved to set up than " 37.15304 @@ -16050,7 +15128,7 @@ 37.15305 msgstr "" 37.15306 37.15307 #. type: Content of: <book><chapter><sect1><para> 37.15308 -#: ../en/ch14-hgext.xml:146 37.15309 +#: ../en/ch13-hgext.xml:146 37.15310 msgid "" 37.15311 "The extension currently comes in two parts: a set of patches to the Mercurial " 37.15312 "source code, and a library of Python bindings to the <literal>inotify</" 37.15313 @@ -16058,7 +15136,7 @@ 37.15314 msgstr "" 37.15315 37.15316 #. type: Content of: <book><chapter><sect1><note><para> 37.15317 -#: ../en/ch14-hgext.xml:150 37.15318 +#: ../en/ch13-hgext.xml:150 37.15319 msgid "" 37.15320 "There are <emphasis>two</emphasis> Python <literal>inotify</literal> binding " 37.15321 "libraries. One of them is called <literal>pyinotify</literal>, and is " 37.15322 @@ -16068,14 +15146,14 @@ 37.15323 msgstr "" 37.15324 37.15325 #. type: Content of: <book><chapter><sect1><para> 37.15326 -#: ../en/ch14-hgext.xml:157 37.15327 +#: ../en/ch13-hgext.xml:157 37.15328 msgid "" 37.15329 "To get going, it's best to already have a functioning copy of Mercurial " 37.15330 "installed." 37.15331 msgstr "" 37.15332 37.15333 #. type: Content of: <book><chapter><sect1><note><para> 37.15334 -#: ../en/ch14-hgext.xml:160 37.15335 +#: ../en/ch13-hgext.xml:160 37.15336 msgid "" 37.15337 "If you follow the instructions below, you'll be <emphasis>replacing</" 37.15338 "emphasis> and overwriting any existing installation of Mercurial that you " 37.15339 @@ -16084,14 +15162,14 @@ 37.15340 msgstr "" 37.15341 37.15342 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15343 -#: ../en/ch14-hgext.xml:167 37.15344 +#: ../en/ch13-hgext.xml:167 37.15345 msgid "" 37.15346 "Clone the Python <literal>inotify</literal> binding repository. Build and " 37.15347 "install it." 37.15348 msgstr "" 37.15349 37.15350 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15351 -#: ../en/ch14-hgext.xml:175 37.15352 +#: ../en/ch13-hgext.xml:174 37.15353 msgid "" 37.15354 "Clone the <filename class=\"directory\">crew</filename> Mercurial " 37.15355 "repository. Clone the <literal role=\"hg-ext\">inotify</literal> patch " 37.15356 @@ -16100,7 +15178,7 @@ 37.15357 msgstr "" 37.15358 37.15359 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15360 -#: ../en/ch14-hgext.xml:188 37.15361 +#: ../en/ch13-hgext.xml:184 37.15362 msgid "" 37.15363 "Make sure that you have the Mercurial Queues extension, <literal role=\"hg-ext" 37.15364 "\">mq</literal>, enabled. If you've never used MQ, read section <xref " 37.15365 @@ -16108,7 +15186,7 @@ 37.15366 msgstr "" 37.15367 37.15368 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15369 -#: ../en/ch14-hgext.xml:194 37.15370 +#: ../en/ch13-hgext.xml:190 37.15371 msgid "" 37.15372 "Go into the <filename class=\"directory\">inotify</filename> repo, and apply " 37.15373 "all of the <literal role=\"hg-ext\">inotify</literal> patches using the " 37.15374 @@ -16117,27 +15195,27 @@ 37.15375 msgstr "" 37.15376 37.15377 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15378 -#: ../en/ch14-hgext.xml:204 37.15379 +#: ../en/ch13-hgext.xml:199 37.15380 msgid "" 37.15381 "If you get an error message from <command role=\"hg-ext-mq\">qpush</command>, " 37.15382 "you should not continue. Instead, ask for help." 37.15383 msgstr "" 37.15384 37.15385 #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> 37.15386 -#: ../en/ch14-hgext.xml:208 37.15387 +#: ../en/ch13-hgext.xml:203 37.15388 msgid "Build and install the patched version of Mercurial." 37.15389 msgstr "" 37.15390 37.15391 #. type: Content of: <book><chapter><sect1><para> 37.15392 -#: ../en/ch14-hgext.xml:216 37.15393 +#: ../en/ch13-hgext.xml:209 37.15394 msgid "" 37.15395 "Once you've build a suitably patched version of Mercurial, all you need to do " 37.15396 "to enable the <literal role=\"hg-ext\">inotify</literal> extension is add an " 37.15397 -"entry to your <filename role=\"special\"> /.hgrc</filename>." 37.15398 -msgstr "" 37.15399 - 37.15400 -#. type: Content of: <book><chapter><sect1><para> 37.15401 -#: ../en/ch14-hgext.xml:221 37.15402 +"entry to your <filename role=\"special\">~/.hgrc</filename>." 37.15403 +msgstr "" 37.15404 + 37.15405 +#. type: Content of: <book><chapter><sect1><para> 37.15406 +#: ../en/ch13-hgext.xml:214 37.15407 msgid "" 37.15408 "When the <literal role=\"hg-ext\">inotify</literal> extension is enabled, " 37.15409 "Mercurial will automatically and transparently start the status daemon the " 37.15410 @@ -16146,7 +15224,7 @@ 37.15411 msgstr "" 37.15412 37.15413 #. type: Content of: <book><chapter><sect1><para> 37.15414 -#: ../en/ch14-hgext.xml:227 37.15415 +#: ../en/ch13-hgext.xml:220 37.15416 msgid "" 37.15417 "The status daemon is started silently, and runs in the background. If you " 37.15418 "look at a list of running processes after you've enabled the <literal role=" 37.15419 @@ -16156,7 +15234,7 @@ 37.15420 msgstr "" 37.15421 37.15422 #. type: Content of: <book><chapter><sect1><para> 37.15423 -#: ../en/ch14-hgext.xml:235 37.15424 +#: ../en/ch13-hgext.xml:228 37.15425 msgid "" 37.15426 "The first time you run a Mercurial command in a repository when you have the " 37.15427 "<literal role=\"hg-ext\">inotify</literal> extension enabled, it will run " 37.15428 @@ -16172,7 +15250,7 @@ 37.15429 msgstr "" 37.15430 37.15431 #. type: Content of: <book><chapter><sect1><para> 37.15432 -#: ../en/ch14-hgext.xml:249 37.15433 +#: ../en/ch13-hgext.xml:242 37.15434 msgid "" 37.15435 "If you like, you can manually start a status daemon using the <command role=" 37.15436 "\"hg-ext-inotify\">inserve</command> command. This gives you slightly finer " 37.15437 @@ -16182,7 +15260,7 @@ 37.15438 msgstr "" 37.15439 37.15440 #. type: Content of: <book><chapter><sect1><para> 37.15441 -#: ../en/ch14-hgext.xml:256 37.15442 +#: ../en/ch13-hgext.xml:249 37.15443 msgid "" 37.15444 "When you're using the <literal role=\"hg-ext\">inotify</literal> extension, " 37.15445 "you should notice <emphasis>no difference at all</emphasis> in Mercurial's " 37.15446 @@ -16193,14 +15271,14 @@ 37.15447 msgstr "" 37.15448 37.15449 #. type: Content of: <book><chapter><sect1><title> 37.15450 -#: ../en/ch14-hgext.xml:267 37.15451 +#: ../en/ch13-hgext.xml:260 37.15452 msgid "" 37.15453 "Flexible diff support with the <literal role=\"hg-ext\">extdiff</literal> " 37.15454 "extension" 37.15455 msgstr "使用扩展 <literal role=\"hg-ext\">extdiff</literal> 以扩展差异支持" 37.15456 37.15457 #. type: Content of: <book><chapter><sect1><para> 37.15458 -#: ../en/ch14-hgext.xml:270 37.15459 +#: ../en/ch13-hgext.xml:263 37.15460 msgid "" 37.15461 "Mercurial's built-in <command role=\"hg-cmd\">hg diff</command> command " 37.15462 "outputs plaintext unified diffs." 37.15463 @@ -16209,7 +15287,7 @@ 37.15464 "不同。" 37.15465 37.15466 #. type: Content of: <book><chapter><sect1><para> 37.15467 -#: ../en/ch14-hgext.xml:275 37.15468 +#: ../en/ch13-hgext.xml:268 37.15469 msgid "" 37.15470 "If you would like to use an external tool to display modifications, you'll " 37.15471 "want to use the <literal role=\"hg-ext\">extdiff</literal> extension. This " 37.15472 @@ -16217,16 +15295,16 @@ 37.15473 msgstr "" 37.15474 37.15475 #. type: Content of: <book><chapter><sect1><para> 37.15476 -#: ../en/ch14-hgext.xml:280 37.15477 +#: ../en/ch13-hgext.xml:273 37.15478 msgid "" 37.15479 "The <literal role=\"hg-ext\">extdiff</literal> extension is bundled with " 37.15480 "Mercurial, so it's easy to set up. In the <literal role=\"rc-extensions" 37.15481 -"\">extensions</literal> section of your <filename role=\"special\"> /.hgrc</" 37.15482 +"\">extensions</literal> section of your <filename role=\"special\">~/.hgrc</" 37.15483 "filename>, simply add a one-line entry to enable the extension." 37.15484 msgstr "" 37.15485 37.15486 #. type: Content of: <book><chapter><sect1><para> 37.15487 -#: ../en/ch14-hgext.xml:286 37.15488 +#: ../en/ch13-hgext.xml:280 37.15489 msgid "" 37.15490 "This introduces a command named <command role=\"hg-ext-extdiff\">extdiff</" 37.15491 "command>, which by default uses your system's <command>diff</command> command " 37.15492 @@ -16235,7 +15313,7 @@ 37.15493 msgstr "" 37.15494 37.15495 #. type: Content of: <book><chapter><sect1><para> 37.15496 -#: ../en/ch14-hgext.xml:294 37.15497 +#: ../en/ch13-hgext.xml:288 37.15498 msgid "" 37.15499 "The result won't be exactly the same as with the built-in <command role=\"hg-" 37.15500 "cmd\">hg diff</command> variations, because the output of <command>diff</" 37.15501 @@ -16243,7 +15321,7 @@ 37.15502 msgstr "" 37.15503 37.15504 #. type: Content of: <book><chapter><sect1><para> 37.15505 -#: ../en/ch14-hgext.xml:299 37.15506 +#: ../en/ch13-hgext.xml:293 37.15507 msgid "" 37.15508 "As the <quote><literal>making snapshot</literal></quote> lines of output " 37.15509 "above imply, the <command role=\"hg-ext-extdiff\">extdiff</command> command " 37.15510 @@ -16257,7 +15335,7 @@ 37.15511 msgstr "" 37.15512 37.15513 #. type: Content of: <book><chapter><sect1><para> 37.15514 -#: ../en/ch14-hgext.xml:312 37.15515 +#: ../en/ch13-hgext.xml:306 37.15516 msgid "" 37.15517 "Snapshot directory names have the same base name as your repository. If your " 37.15518 "repository path is <filename class=\"directory\">/quux/bar/foo</filename>, " 37.15519 @@ -16274,7 +15352,7 @@ 37.15520 msgstr "" 37.15521 37.15522 #. type: Content of: <book><chapter><sect1><para> 37.15523 -#: ../en/ch14-hgext.xml:328 37.15524 +#: ../en/ch13-hgext.xml:322 37.15525 msgid "" 37.15526 "The <command role=\"hg-ext-extdiff\">extdiff</command> command accepts two " 37.15527 "important options. The <option role=\"hg-ext-extdiff-cmd-extdiff-opt\">hg -p</" 37.15528 @@ -16292,7 +15370,7 @@ 37.15529 37.15530 # 37.15531 #. type: Content of: <book><chapter><sect1><para> 37.15532 -#: ../en/ch14-hgext.xml:345 37.15533 +#: ../en/ch13-hgext.xml:339 37.15534 msgid "" 37.15535 "As an example, here's how to run the normal system <command>diff</command> " 37.15536 "command, getting it to generate context diffs (using the <option role=\"cmd-" 37.15537 @@ -16302,14 +15380,14 @@ 37.15538 msgstr "" 37.15539 37.15540 #. type: Content of: <book><chapter><sect1><para> 37.15541 -#: ../en/ch14-hgext.xml:354 37.15542 +#: ../en/ch13-hgext.xml:348 37.15543 msgid "" 37.15544 "Launching a visual diff tool is just as easy. Here's how to launch the " 37.15545 "<command>kdiff3</command> viewer." 37.15546 msgstr "" 37.15547 37.15548 #. type: Content of: <book><chapter><sect1><para> 37.15549 -#: ../en/ch14-hgext.xml:358 37.15550 +#: ../en/ch13-hgext.xml:352 37.15551 msgid "" 37.15552 "If your diff viewing command can't deal with directories, you can easily work " 37.15553 "around this with a little scripting. For an example of such scripting in " 37.15554 @@ -16319,12 +15397,12 @@ 37.15555 msgstr "" 37.15556 37.15557 #. type: Content of: <book><chapter><sect1><sect2><title> 37.15558 -#: ../en/ch14-hgext.xml:366 37.15559 +#: ../en/ch13-hgext.xml:360 37.15560 msgid "Defining command aliases" 37.15561 msgstr "定义命令的别名" 37.15562 37.15563 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15564 -#: ../en/ch14-hgext.xml:368 37.15565 +#: ../en/ch13-hgext.xml:362 37.15566 msgid "" 37.15567 "It can be cumbersome to remember the options to both the <command role=\"hg-" 37.15568 "ext-extdiff\">extdiff</command> command and the diff viewer you want to use, " 37.15569 @@ -16334,9 +15412,9 @@ 37.15570 msgstr "" 37.15571 37.15572 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15573 -#: ../en/ch14-hgext.xml:375 37.15574 -msgid "" 37.15575 -"All you need to do is edit your <filename role=\"special\"> /.hgrc</" 37.15576 +#: ../en/ch13-hgext.xml:369 37.15577 +msgid "" 37.15578 +"All you need to do is edit your <filename role=\"special\">~/.hgrc</" 37.15579 "filename>, and add a section named <literal role=\"rc-extdiff\">extdiff</" 37.15580 "literal>. Inside this section, you can define multiple commands. Here's how " 37.15581 "to add a <literal>kdiff3</literal> command. Once you've defined this, you " 37.15582 @@ -16346,7 +15424,7 @@ 37.15583 msgstr "" 37.15584 37.15585 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15586 -#: ../en/ch14-hgext.xml:384 37.15587 +#: ../en/ch13-hgext.xml:379 37.15588 msgid "" 37.15589 "If you leave the right hand side of the definition empty, as above, the " 37.15590 "<literal role=\"hg-ext\">extdiff</literal> extension uses the name of the " 37.15591 @@ -16357,7 +15435,7 @@ 37.15592 msgstr "" 37.15593 37.15594 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15595 -#: ../en/ch14-hgext.xml:393 37.15596 +#: ../en/ch13-hgext.xml:389 37.15597 msgid "" 37.15598 "You can also specify the default options that you want to invoke your diff " 37.15599 "viewing program with. The prefix to use is <quote><literal>opts.</literal></" 37.15600 @@ -16367,19 +15445,19 @@ 37.15601 msgstr "" 37.15602 37.15603 #. type: Content of: <book><chapter><sect1><title> 37.15604 -#: ../en/ch14-hgext.xml:406 37.15605 +#: ../en/ch13-hgext.xml:403 37.15606 msgid "" 37.15607 "Cherrypicking changes with the <literal role=\"hg-ext\">transplant</literal> " 37.15608 "extension" 37.15609 msgstr "使用扩展 <literal role=\"hg-ext\">transplant</literal> 以挑选修改" 37.15610 37.15611 #. type: Content of: <book><chapter><sect1><para> 37.15612 -#: ../en/ch14-hgext.xml:409 37.15613 +#: ../en/ch13-hgext.xml:406 37.15614 msgid "Need to have a long chat with Brendan about this." 37.15615 msgstr "" 37.15616 37.15617 #. type: Content of: <book><chapter><sect1><title> 37.15618 -#: ../en/ch14-hgext.xml:413 37.15619 +#: ../en/ch13-hgext.xml:410 37.15620 msgid "" 37.15621 "Send changes via email with the <literal role=\"hg-ext\">patchbomb</literal> " 37.15622 "extension" 37.15623 @@ -16387,7 +15465,7 @@ 37.15624 "使用扩展 <literal role=\"hg-ext\">patchbomb</literal> 通过 email 发送修改" 37.15625 37.15626 #. type: Content of: <book><chapter><sect1><para> 37.15627 -#: ../en/ch14-hgext.xml:416 37.15628 +#: ../en/ch13-hgext.xml:413 37.15629 msgid "" 37.15630 "Many projects have a culture of <quote>change review</quote>, in which people " 37.15631 "send their modifications to a mailing list for others to read and comment on " 37.15632 @@ -16397,7 +15475,7 @@ 37.15633 msgstr "" 37.15634 37.15635 #. type: Content of: <book><chapter><sect1><para> 37.15636 -#: ../en/ch14-hgext.xml:424 37.15637 +#: ../en/ch13-hgext.xml:421 37.15638 msgid "" 37.15639 "Mercurial makes it easy to send changes over email for review or application, " 37.15640 "via its <literal role=\"hg-ext\">patchbomb</literal> extension. The " 37.15641 @@ -16408,7 +15486,7 @@ 37.15642 msgstr "" 37.15643 37.15644 #. type: Content of: <book><chapter><sect1><para> 37.15645 -#: ../en/ch14-hgext.xml:432 37.15646 +#: ../en/ch13-hgext.xml:429 37.15647 msgid "" 37.15648 "As usual, the basic configuration of the <literal role=\"hg-ext\">patchbomb</" 37.15649 "literal> extension takes just one or two lines in your <filename role=" 37.15650 @@ -16416,14 +15494,14 @@ 37.15651 msgstr "" 37.15652 37.15653 #. type: Content of: <book><chapter><sect1><para> 37.15654 -#: ../en/ch14-hgext.xml:437 37.15655 +#: ../en/ch13-hgext.xml:435 37.15656 msgid "" 37.15657 "Once you've enabled the extension, you will have a new command available, " 37.15658 "named <command role=\"hg-ext-patchbomb\">email</command>." 37.15659 msgstr "" 37.15660 37.15661 #. type: Content of: <book><chapter><sect1><para> 37.15662 -#: ../en/ch14-hgext.xml:441 37.15663 +#: ../en/ch13-hgext.xml:439 37.15664 msgid "" 37.15665 "The safest and best way to invoke the <command role=\"hg-ext-patchbomb" 37.15666 "\">email</command> command is to <emphasis>always</emphasis> run it first " 37.15667 @@ -16436,7 +15514,7 @@ 37.15668 msgstr "" 37.15669 37.15670 #. type: Content of: <book><chapter><sect1><para> 37.15671 -#: ../en/ch14-hgext.xml:452 37.15672 +#: ../en/ch13-hgext.xml:450 37.15673 msgid "" 37.15674 "The <command role=\"hg-ext-patchbomb\">email</command> command accepts the " 37.15675 "same kind of revision syntax as every other Mercurial command. For example, " 37.15676 @@ -16445,7 +15523,7 @@ 37.15677 msgstr "" 37.15678 37.15679 #. type: Content of: <book><chapter><sect1><para> 37.15680 -#: ../en/ch14-hgext.xml:457 37.15681 +#: ../en/ch13-hgext.xml:455 37.15682 msgid "" 37.15683 "You can also specify a <emphasis>repository</emphasis> to compare with. If " 37.15684 "you provide a repository but no revisions, the <command role=\"hg-ext-" 37.15685 @@ -16457,7 +15535,7 @@ 37.15686 msgstr "" 37.15687 37.15688 #. type: Content of: <book><chapter><sect1><para> 37.15689 -#: ../en/ch14-hgext.xml:466 37.15690 +#: ../en/ch13-hgext.xml:464 37.15691 msgid "" 37.15692 "It's perfectly safe to run the <command role=\"hg-ext-patchbomb\">email</" 37.15693 "command> command without the names of the people you want to send to: if you " 37.15694 @@ -16468,7 +15546,7 @@ 37.15695 msgstr "" 37.15696 37.15697 #. type: Content of: <book><chapter><sect1><para> 37.15698 -#: ../en/ch14-hgext.xml:474 37.15699 +#: ../en/ch13-hgext.xml:472 37.15700 msgid "" 37.15701 "When you are sending just one revision, the <command role=\"hg-ext-patchbomb" 37.15702 "\">email</command> command will by default use the first line of the " 37.15703 @@ -16476,7 +15554,7 @@ 37.15704 msgstr "" 37.15705 37.15706 #. type: Content of: <book><chapter><sect1><para> 37.15707 -#: ../en/ch14-hgext.xml:479 37.15708 +#: ../en/ch13-hgext.xml:477 37.15709 msgid "" 37.15710 "If you send multiple revisions, the <command role=\"hg-ext-patchbomb\">email</" 37.15711 "command> command will usually send one message per changeset. It will " 37.15712 @@ -16485,12 +15563,12 @@ 37.15713 msgstr "" 37.15714 37.15715 #. type: Content of: <book><chapter><sect1><sect2><title> 37.15716 -#: ../en/ch14-hgext.xml:486 37.15717 +#: ../en/ch13-hgext.xml:484 37.15718 msgid "Changing the behaviour of patchbombs" 37.15719 msgstr "修改 patchbomb 的行为" 37.15720 37.15721 #. type: Content of: <book><chapter><sect1><sect2><para> 37.15722 -#: ../en/ch14-hgext.xml:488 37.15723 +#: ../en/ch13-hgext.xml:486 37.15724 msgid "" 37.15725 "Not every project has exactly the same conventions for sending changes in " 37.15726 "email; the <literal role=\"hg-ext\">patchbomb</literal> extension tries to " 37.15727 @@ -16498,7 +15576,7 @@ 37.15728 msgstr "" 37.15729 37.15730 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15731 -#: ../en/ch14-hgext.xml:494 37.15732 +#: ../en/ch13-hgext.xml:492 37.15733 msgid "" 37.15734 "You can write a subject for the introductory message on the command line " 37.15735 "using the <option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -s</option> " 37.15736 @@ -16506,7 +15584,7 @@ 37.15737 msgstr "" 37.15738 37.15739 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15740 -#: ../en/ch14-hgext.xml:500 37.15741 +#: ../en/ch13-hgext.xml:498 37.15742 msgid "" 37.15743 "To change the email address from which the messages originate, use the " 37.15744 "<option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -f</option> option. This " 37.15745 @@ -16514,7 +15592,7 @@ 37.15746 msgstr "" 37.15747 37.15748 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15749 -#: ../en/ch14-hgext.xml:506 37.15750 +#: ../en/ch13-hgext.xml:504 37.15751 msgid "" 37.15752 "The default behaviour is to send unified diffs (see section <xref linkend=" 37.15753 "\"sec.mq.patch\"/> for a description of the format), one per message. You " 37.15754 @@ -16523,7 +15601,7 @@ 37.15755 msgstr "" 37.15756 37.15757 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15758 -#: ../en/ch14-hgext.xml:514 37.15759 +#: ../en/ch13-hgext.xml:512 37.15760 msgid "" 37.15761 "Unified diffs are normally prefaced with a metadata header. You can omit " 37.15762 "this, and send unadorned diffs, with the <option role=\"hg-ext-patchbomb-cmd-" 37.15763 @@ -16531,7 +15609,7 @@ 37.15764 msgstr "" 37.15765 37.15766 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15767 -#: ../en/ch14-hgext.xml:520 37.15768 +#: ../en/ch13-hgext.xml:518 37.15769 msgid "" 37.15770 "Diffs are normally sent <quote>inline</quote>, in the same body part as the " 37.15771 "description of a patch. This makes it easiest for the largest number of " 37.15772 @@ -16542,7 +15620,7 @@ 37.15773 msgstr "" 37.15774 37.15775 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15776 -#: ../en/ch14-hgext.xml:530 37.15777 +#: ../en/ch13-hgext.xml:528 37.15778 msgid "" 37.15779 "Instead of sending mail messages, you can write them to an <literal>mbox</" 37.15780 "literal>-format mail folder using the <option role=\"hg-ext-patchbomb-cmd-" 37.15781 @@ -16551,7 +15629,7 @@ 37.15782 msgstr "" 37.15783 37.15784 #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> 37.15785 -#: ../en/ch14-hgext.xml:537 37.15786 +#: ../en/ch13-hgext.xml:535 37.15787 msgid "" 37.15788 "If you would like to add a <command>diffstat</command>-format summary to each " 37.15789 "patch, and one to the introductory message, use the <option role=\"hg-ext-" 37.15790 @@ -16560,3 +15638,60 @@ 37.15791 "the number of lines affected, and a histogram showing how much each file is " 37.15792 "modified. This gives readers a qualitative glance at how complex a patch is." 37.15793 msgstr "" 37.15794 + 37.15795 +#~ msgid "Introduction" 37.15796 +#~ msgstr "简介" 37.15797 + 37.15798 +#~ msgid "About revision control" 37.15799 +#~ msgstr "关于版本控制" 37.15800 + 37.15801 +#~ msgid "Why use revision control?" 37.15802 +#~ msgstr "为什么使用版本控制?" 37.15803 + 37.15804 +#~ msgid "The many names of revision control" 37.15805 +#~ msgstr "版本控制的别名" 37.15806 + 37.15807 +#~ msgid "Revision control (RCS)" 37.15808 +#~ msgstr "版本控制(RCS)" 37.15809 + 37.15810 +#~ msgid "Software configuration management (SCM), or configuration management" 37.15811 +#~ msgstr "软件配置管理(SCM),或配置管理" 37.15812 + 37.15813 +#~ msgid "Source code management" 37.15814 +#~ msgstr "源代码管理" 37.15815 + 37.15816 +#~ msgid "Source code control, or source control" 37.15817 +#~ msgstr "源代码控制,或源控制" 37.15818 + 37.15819 +#~ msgid "Version control (VCS)" 37.15820 +#~ msgstr "版本控制(VCS)" 37.15821 + 37.15822 +#~ msgid "A short history of revision control" 37.15823 +#~ msgstr "版本控制简史" 37.15824 + 37.15825 +#~ msgid "Trends in revision control" 37.15826 +#~ msgstr "版本控制的发展趋势" 37.15827 + 37.15828 +#~ msgid "A few of the advantages of distributed revision control" 37.15829 +#~ msgstr "分布版本控制的优点" 37.15830 + 37.15831 +#~ msgid "Advantages for open source projects" 37.15832 +#~ msgstr "开源项目的优点" 37.15833 + 37.15834 +#~ msgid "Advantages for commercial projects" 37.15835 +#~ msgstr "商业项目的优点" 37.15836 + 37.15837 +#~ msgid "Why choose Mercurial?" 37.15838 +#~ msgstr "为什么选择 Mercurial?" 37.15839 + 37.15840 +#~ msgid "Mercurial compared with other tools" 37.15841 +#~ msgstr "Mercurial 与其它工具的比较" 37.15842 + 37.15843 +#~ msgid "Commercial tools" 37.15844 +#~ msgstr "商业工具" 37.15845 + 37.15846 +#~ msgid "Choosing a revision control tool" 37.15847 +#~ msgstr "选择版本控制工具" 37.15848 + 37.15849 +#~ msgid "Switching from another tool to Mercurial" 37.15850 +#~ msgstr "从其它工具切换到 Mercurial"
38.1 --- a/web/hgbook/dbutil.py Fri Mar 20 15:40:06 2009 +0800 38.2 +++ b/web/hgbook/dbutil.py Fri Mar 20 16:43:35 2009 +0800 38.3 @@ -1,4 +1,5 @@ 38.4 import MySQLdb as mysql 38.5 +import sys 38.6 38.7 def connect(): 38.8 try:
39.1 --- a/web/hgbook/load_elements.py Fri Mar 20 15:40:06 2009 +0800 39.2 +++ b/web/hgbook/load_elements.py Fri Mar 20 16:43:35 2009 +0800 39.3 @@ -8,7 +8,7 @@ 39.4 sys.path.append(os.path.dirname(__file__)) 39.5 import dbutil 39.6 39.7 -os.system('make -C ../../en ids') 39.8 +os.system('make -C ../../en all-ids.dat') 39.9 39.10 conn = dbutil.connect() 39.11 c = conn.cursor()