Mercurial > hgbook
view po/zh.po @ 781:93d19b27859c
started concepts.tex
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 12 May 2009 17:49:11 +0900 |
parents | 55e2953f82d6 |
children |
line wrap: on
line source
# # Simplified Chinese translation for hgbook # This file is distributed under the same license as the hgbook. # # Authors: # Dongsheng Song <dongsheng.song@gmail.com>, 2009 # # Check translation: # msgfmt --statistics -c -o zh.mo zh.po # # Please format your translation before commit: # msgcat --sort-by-file --width=80 -o zh_new.po zh.po # mv -f zh_new.po zh.po # # Dictionary: # blame 追溯 # branch 分支 # changes 修改 # changeset 修改集 # checkout 检出 # remove 移除(从版本库删除) # delete 删除(只从文件系统删除) # filelog 文件日志 # patchset 补丁集 # pushing to 推到 # pulling from 拉自,抓取 # rename 改名 # repository 版本库 # revert 恢复 # revision 版本 # revlog 版本日志 # tag 标签 # tip 顶点 # undo 撤销 # unversioned 未版本控制 # updated 更新到,同步到(适用于旧版本) # versioned 受版本控制 # working copy 工作副本 # ... # msgid "" msgstr "" "Project-Id-Version: hgbook 1.2\n" "POT-Creation-Date: 2009-04-05 11:48+0800\n" "PO-Revision-Date: 2009-04-05 12:10+0800\n" "Last-Translator: 宋冬生 <songdonogsheng@live.cn>\n" "Language-Team: Simplified Chinese <i18n-zh@googlegroups.com >\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Chinese\n" "X-Poedit-Country: CHINA\n" "X-Poedit-SourceCharset: utf-8\n" #. type: Content of: <book><title> #: ../en/00book.xml:41 msgid "Mercurial: The Definitive Guide" msgstr "Mercurial 权威指南" #. type: Content of: <book><subtitle> #: ../en/00book.xml:46 msgid "Compiled from $rev_id$" msgstr "编译自 $rev_id$" #. type: Content of: <book><bookinfo> #: ../en/00book.xml:48 msgid "<edition>1</edition> <isbn>9780596800673</isbn>" msgstr "<edition>1</edition> <isbn>9780596800673</isbn>" #. type: Content of: <book><bookinfo><authorgroup><author><firstname> #: ../en/00book.xml:52 msgid "Bryan" msgstr "Bryan" #. type: Content of: <book><bookinfo><authorgroup><author><surname> #: ../en/00book.xml:53 msgid "O'Sullivan" msgstr "O'Sullivan" #. type: Content of: <book><bookinfo> #: ../en/00book.xml:57 msgid "" "<editor> <firstname>Mike</firstname> <surname>Loukides</surname> </editor> " "<copyright> <year>2006</year> <year>2007</year> <year>2008</year> <year>2009</" "year> <holder>Bryan O'Sullivan</holder> </copyright>" msgstr "" "<editor> <firstname>Mike</firstname> <surname>Loukides</surname> </editor> " "<copyright> <year>2006</year> <year>2007</year> <year>2008</year> <year>2009</" "year> <holder>Bryan O'Sullivan</holder> </copyright>" #. type: Content of: <book><appendix><title> #: ../en/appB-mq-ref.xml:5 msgid "Mercurial Queues reference" msgstr "Mercurial 队列参考" #. type: Content of: <book><appendix><sect1><title> #: ../en/appB-mq-ref.xml:8 msgid "MQ command reference" msgstr "MQ 命令参考" #. type: Content of: <book><appendix><sect1><para> #: ../en/appB-mq-ref.xml:10 msgid "" "For an overview of the commands provided by MQ, use the command <command role=" "\"hg-cmd\">hg help mq</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:14 msgid "" "<command role=\"hg-ext-mq\">qapplied</command>&emdash;print applied patches" msgstr "<command role=\"hg-ext-mq\">qapplied</command>—显示已应用的补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:17 msgid "" "The <command role=\"hg-ext-mq\">qapplied</command> command prints the current " "stack of applied patches. Patches are printed in oldest-to-newest order, so " "the last patch in the list is the <quote>top</quote> patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:24 msgid "" "<command role=\"hg-ext-mq\">qcommit</command>&emdash;commit changes in the " "queue repository" msgstr "<command role=\"hg-ext-mq\">qcommit</command>—提交队列中的修改" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:27 msgid "" "The <command role=\"hg-ext-mq\">qcommit</command> command commits any " "outstanding changes in the <filename role=\"special\" class=\"directory\">.hg/" "patches</filename> repository. This command only works if the <filename role=" "\"special\" class=\"directory\">.hg/patches</filename> directory is a " "repository, i.e. you created the directory using <command role=\"hg-cmd\">hg " "qinit <option role=\"hg-ext-mq-cmd-qinit-opt\">-c</option></command> or ran " "<command role=\"hg-cmd\">hg init</command> in the directory after running " "<command role=\"hg-ext-mq\">qinit</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:39 msgid "" "This command is shorthand for <command role=\"hg-cmd\">hg commit --cwd .hg/" "patches</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:43 msgid "" "<command role=\"hg-ext-mq\">qdelete</command>&emdash;delete a patch from the " "<filename role=\"special\">series</filename> file" msgstr "" "<command role=\"hg-ext-mq\">qdelete</command>—从文件 <filename role=\"special" "\">series</filename> 中删除补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:48 msgid "" "The <command role=\"hg-ext-mq\">qdelete</command> command removes the entry " "for a patch from the <filename role=\"special\">series</filename> file in the " "<filename role=\"special\" class=\"directory\">.hg/patches</filename> " "directory. It does not pop the patch if the patch is already applied. By " "default, it does not delete the patch file; use the <option role=\"hg-ext-mq-" "cmd-qdel-opt\">-f</option> option to do that." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:57 ../en/appB-mq-ref.xml:99 ../en/appB-mq-ref.xml:157 #: ../en/appB-mq-ref.xml:197 ../en/appB-mq-ref.xml:264 #: ../en/appB-mq-ref.xml:335 ../en/appB-mq-ref.xml:404 #: ../en/appB-mq-ref.xml:497 msgid "Options:" msgstr "选项:" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:59 msgid "" "<option role=\"hg-ext-mq-cmd-qdel-opt\">-f</option>: Delete the patch file." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:66 msgid "" "<command role=\"hg-ext-mq\">qdiff</command>&emdash;print a diff of the " "topmost applied patch" msgstr "<command role=\"hg-ext-mq\">qdiff</command>—显示最新应用补丁的差异" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:69 msgid "" "The <command role=\"hg-ext-mq\">qdiff</command> command prints a diff of the " "topmost applied patch. It is equivalent to <command role=\"hg-cmd\">hg diff -" "r-2:-1</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:75 msgid "" "<command role=\"hg-ext-mq\">qfold</command>&emdash;merge (<quote>fold</" "quote>) several patches into one" msgstr "" "<command role=\"hg-ext-mq\">qfold</command>—将多个补丁合并(<quote>折叠</" "quote>)成一个" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:78 msgid "" "The <command role=\"hg-ext-mq\">qfold</command> command merges multiple " "patches into the topmost applied patch, so that the topmost applied patch " "makes the union of all of the changes in the patches in question." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:83 msgid "" "The patches to fold must not be applied; <command role=\"hg-ext-mq\">qfold</" "command> will exit with an error if any is. The order in which patches are " "folded is significant; <command role=\"hg-cmd\">hg qfold a b</command> means " "<quote>apply the current topmost patch, followed by <literal>a</literal>, " "followed by <literal>b</literal></quote>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:91 msgid "" "The comments from the folded patches are appended to the comments of the " "destination patch, with each block of comments separated by three asterisk " "(<quote><literal>*</literal></quote>) characters. Use the <option role=\"hg-" "ext-mq-cmd-qfold-opt\">-e</option> option to edit the commit message for the " "combined patch/changeset after the folding has completed." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:101 msgid "" "<option role=\"hg-ext-mq-cmd-qfold-opt\">-e</option>: Edit the commit message " "and patch description for the newly folded patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:106 msgid "" "<option role=\"hg-ext-mq-cmd-qfold-opt\">-l</option>: Use the contents of the " "given file as the new commit message and patch description for the folded " "patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:111 msgid "" "<option role=\"hg-ext-mq-cmd-qfold-opt\">-m</option>: Use the given text as " "the new commit message and patch description for the folded patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:119 msgid "" "<command role=\"hg-ext-mq\">qheader</command>&emdash;display the header/" "description of a patch" msgstr "<command role=\"hg-ext-mq\">qheader</command>—显示补丁头部描述" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:123 msgid "" "The <command role=\"hg-ext-mq\">qheader</command> command prints the header, " "or description, of a patch. By default, it prints the header of the topmost " "applied patch. Given an argument, it prints the header of the named patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:130 msgid "" "<command role=\"hg-ext-mq\">qimport</command>&emdash;import a third-party " "patch into the queue" msgstr "<command role=\"hg-ext-mq\">qimport</command>—将第三方补丁导入队列" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:133 msgid "" "The <command role=\"hg-ext-mq\">qimport</command> command adds an entry for " "an external patch to the <filename role=\"special\">series</filename> file, " "and copies the patch into the <filename role=\"special\" class=\"directory\">." "hg/patches</filename> directory. It adds the entry immediately after the " "topmost applied patch, but does not push the patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:141 msgid "" "If the <filename role=\"special\" class=\"directory\">.hg/patches</filename> " "directory is a repository, <command role=\"hg-ext-mq\">qimport</command> " "automatically does an <command role=\"hg-cmd\">hg add</command> of the " "imported patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:149 msgid "" "<command role=\"hg-ext-mq\">qinit</command>&emdash;prepare a repository to " "work with MQ" msgstr "<command role=\"hg-ext-mq\">qinit</command>—为使用 MQ 配置版本库" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:152 msgid "" "The <command role=\"hg-ext-mq\">qinit</command> command prepares a repository " "to work with MQ. It creates a directory called <filename role=\"special\" " "class=\"directory\">.hg/patches</filename>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:159 msgid "" "<option role=\"hg-ext-mq-cmd-qinit-opt\">-c</option>: Create <filename role=" "\"special\" class=\"directory\">.hg/patches</filename> as a repository in its " "own right. Also creates a <filename role=\"special\">.hgignore</filename> " "file that will ignore the <filename role=\"special\">status</filename> file." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:169 msgid "" "When the <filename role=\"special\" class=\"directory\">.hg/patches</" "filename> directory is a repository, the <command role=\"hg-ext-mq\">qimport</" "command> and <command role=\"hg-ext-mq\">qnew</command> commands " "automatically <command role=\"hg-cmd\">hg add</command> new patches." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:178 msgid "<command role=\"hg-ext-mq\">qnew</command>&emdash;create a new patch" msgstr "<command role=\"hg-ext-mq\">qnew</command>—创建新补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:181 msgid "" "The <command role=\"hg-ext-mq\">qnew</command> command creates a new patch. " "It takes one mandatory argument, the name to use for the patch file. The " "newly created patch is created empty by default. It is added to the " "<filename role=\"special\">series</filename> file after the current topmost " "applied patch, and is immediately pushed on top of that patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:189 msgid "" "If <command role=\"hg-ext-mq\">qnew</command> finds modified files in the " "working directory, it will refuse to create a new patch unless the <option " "role=\"hg-ext-mq-cmd-qnew-opt\">-f</option> option is used (see below). This " "behaviour allows you to <command role=\"hg-ext-mq\">qrefresh</command> your " "topmost applied patch before you apply a new patch on top of it." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:199 msgid "" "<option role=\"hg-ext-mq-cmd-qnew-opt\">-f</option>: Create a new patch if " "the contents of the working directory are modified. Any outstanding " "modifications are added to the newly created patch, so after this command " "completes, the working directory will no longer be modified." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:206 msgid "" "<option role=\"hg-ext-mq-cmd-qnew-opt\">-m</option>: Use the given text as " "the commit message. This text will be stored at the beginning of the patch " "file, before the patch data." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:215 msgid "" "<command role=\"hg-ext-mq\">qnext</command>&emdash;print the name of the next " "patch" msgstr "<command role=\"hg-ext-mq\">qnext</command>—显示下个补丁的名称" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:218 msgid "" "The <command role=\"hg-ext-mq\">qnext</command> command prints the name name " "of the next patch in the <filename role=\"special\">series</filename> file " "after the topmost applied patch. This patch will become the topmost applied " "patch if you run <command role=\"hg-ext-mq\">qpush</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:227 msgid "" "<command role=\"hg-ext-mq\">qpop</command>&emdash;pop patches off the stack" msgstr "<command role=\"hg-ext-mq\">qpop</command>—删除堆栈顶部的补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:230 msgid "" "The <command role=\"hg-ext-mq\">qpop</command> command removes applied " "patches from the top of the stack of applied patches. By default, it removes " "only one patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:234 msgid "" "This command removes the changesets that represent the popped patches from " "the repository, and updates the working directory to undo the effects of the " "patches." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:238 msgid "" "This command takes an optional argument, which it uses as the name or index " "of the patch to pop to. If given a name, it will pop patches until the named " "patch is the topmost applied patch. If given a number, <command role=\"hg-" "ext-mq\">qpop</command> treats the number as an index into the entries in the " "series file, counting from zero (empty lines and lines containing only " "comments do not count). It pops patches until the patch identified by the " "given index is the topmost applied patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:248 msgid "" "The <command role=\"hg-ext-mq\">qpop</command> command does not read or write " "patches or the <filename role=\"special\">series</filename> file. It is thus " "safe to <command role=\"hg-ext-mq\">qpop</command> a patch that you have " "removed from the <filename role=\"special\">series</filename> file, or a " "patch that you have renamed or deleted entirely. In the latter two cases, " "use the name of the patch as it was when you applied it." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:257 msgid "" "By default, the <command role=\"hg-ext-mq\">qpop</command> command will not " "pop any patches if the working directory has been modified. You can override " "this behaviour using the <option role=\"hg-ext-mq-cmd-qpop-opt\">-f</option> " "option, which reverts all modifications in the working directory." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:266 msgid "" "<option role=\"hg-ext-mq-cmd-qpop-opt\">-a</option>: Pop all applied " "patches. This returns the repository to its state before you applied any " "patches." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:271 msgid "" "<option role=\"hg-ext-mq-cmd-qpop-opt\">-f</option>: Forcibly revert any " "modifications to the working directory when popping." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:276 msgid "" "<option role=\"hg-ext-mq-cmd-qpop-opt\">-n</option>: Pop a patch from the " "named queue." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:281 msgid "" "The <command role=\"hg-ext-mq\">qpop</command> command removes one line from " "the end of the <filename role=\"special\">status</filename> file for each " "patch that it pops." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:288 msgid "" "<command role=\"hg-ext-mq\">qprev</command>&emdash;print the name of the " "previous patch" msgstr "<command role=\"hg-ext-mq\">qprev</command>—显示上个补丁的名称" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:291 msgid "" "The <command role=\"hg-ext-mq\">qprev</command> command prints the name of " "the patch in the <filename role=\"special\">series</filename> file that comes " "before the topmost applied patch. This will become the topmost applied patch " "if you run <command role=\"hg-ext-mq\">qpop</command>." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:300 msgid "" "<command role=\"hg-ext-mq\">qpush</command>&emdash;push patches onto the stack" msgstr "<command role=\"hg-ext-mq\">qpush</command>—增加补丁到堆栈" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:303 msgid "" "The <command role=\"hg-ext-mq\">qpush</command> command adds patches onto the " "applied stack. By default, it adds only one patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:307 msgid "" "This command creates a new changeset to represent each applied patch, and " "updates the working directory to apply the effects of the patches." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:311 msgid "The default data used when creating a changeset are as follows:" msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:314 msgid "" "The commit date and time zone are the current date and time zone. Because " "these data are used to compute the identity of a changeset, this means that " "if you <command role=\"hg-ext-mq\">qpop</command> a patch and <command role=" "\"hg-ext-mq\">qpush</command> it again, the changeset that you push will have " "a different identity than the changeset you popped." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:322 msgid "" "The author is the same as the default used by the <command role=\"hg-cmd\">hg " "commit</command> command." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:326 msgid "" "The commit message is any text from the patch file that comes before the " "first diff header. If there is no such text, a default commit message is " "used that identifies the name of the patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:331 msgid "" "If a patch contains a Mercurial patch header (XXX add link), the information " "in the patch header overrides these defaults." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:337 msgid "" "<option role=\"hg-ext-mq-cmd-qpush-opt\">-a</option>: Push all unapplied " "patches from the <filename role=\"special\">series</filename> file until " "there are none left to push." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:343 msgid "" "<option role=\"hg-ext-mq-cmd-qpush-opt\">-l</option>: Add the name of the " "patch to the end of the commit message." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:347 msgid "" "<option role=\"hg-ext-mq-cmd-qpush-opt\">-m</option>: If a patch fails to " "apply cleanly, use the entry for the patch in another saved queue to compute " "the parameters for a three-way merge, and perform a three-way merge using the " "normal Mercurial merge machinery. Use the resolution of the merge as the new " "patch content." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:355 msgid "" "<option role=\"hg-ext-mq-cmd-qpush-opt\">-n</option>: Use the named queue if " "merging while pushing." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:360 msgid "" "The <command role=\"hg-ext-mq\">qpush</command> command reads, but does not " "modify, the <filename role=\"special\">series</filename> file. It appends " "one line to the <command role=\"hg-cmd\">hg status</command> file for each " "patch that it pushes." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:368 msgid "" "<command role=\"hg-ext-mq\">qrefresh</command>&emdash;update the topmost " "applied patch" msgstr "<command role=\"hg-ext-mq\">qrefresh</command>—更新最新的补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:372 msgid "" "The <command role=\"hg-ext-mq\">qrefresh</command> command updates the " "topmost applied patch. It modifies the patch, removes the old changeset that " "represented the patch, and creates a new changeset to represent the modified " "patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:378 msgid "" "The <command role=\"hg-ext-mq\">qrefresh</command> command looks for the " "following modifications:" msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:381 msgid "" "Changes to the commit message, i.e. the text before the first diff header in " "the patch file, are reflected in the new changeset that represents the patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:386 msgid "" "Modifications to tracked files in the working directory are added to the " "patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:389 msgid "" "Changes to the files tracked using <command role=\"hg-cmd\">hg add</command>, " "<command role=\"hg-cmd\">hg copy</command>, <command role=\"hg-cmd\">hg " "remove</command>, or <command role=\"hg-cmd\">hg rename</command>. Added " "files and copy and rename destinations are added to the patch, while removed " "files and rename sources are removed." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:398 msgid "" "Even if <command role=\"hg-ext-mq\">qrefresh</command> detects no changes, it " "still recreates the changeset that represents the patch. This causes the " "identity of the changeset to differ from the previous changeset that " "identified the patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:406 msgid "" "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-e</option>: Modify the commit " "and patch description, using the preferred text editor." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:411 msgid "" "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-m</option>: Modify the commit " "message and patch description, using the given text." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:416 msgid "" "<option role=\"hg-ext-mq-cmd-qrefresh-opt\">-l</option>: Modify the commit " "message and patch description, using text from the given file." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:424 msgid "<command role=\"hg-ext-mq\">qrename</command>&emdash;rename a patch" msgstr "<command role=\"hg-ext-mq\">qrename</command>—改名补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:427 msgid "" "The <command role=\"hg-ext-mq\">qrename</command> command renames a patch, " "and changes the entry for the patch in the <filename role=\"special\">series</" "filename> file." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:431 msgid "" "With a single argument, <command role=\"hg-ext-mq\">qrename</command> renames " "the topmost applied patch. With two arguments, it renames its first argument " "to its second." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:438 msgid "" "<command role=\"hg-ext-mq\">qrestore</command>&emdash;restore saved queue " "state" msgstr "<command role=\"hg-ext-mq\">qrestore</command>—恢复保存的队列" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:442 msgid "XXX No idea what this does." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:446 msgid "" "<command role=\"hg-ext-mq\">qsave</command>&emdash;save current queue state" msgstr "<command role=\"hg-ext-mq\">qsave</command>—保存当前的队列状态" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:449 msgid "XXX Likewise." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:453 msgid "" "<command role=\"hg-ext-mq\">qseries</command>&emdash;print the entire patch " "series" msgstr "<command role=\"hg-ext-mq\">qseries</command>—显示补丁序列" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:456 msgid "" "The <command role=\"hg-ext-mq\">qseries</command> command prints the entire " "patch series from the <filename role=\"special\">series</filename> file. It " "prints only patch names, not empty lines or comments. It prints in order " "from first to be applied to last." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:464 msgid "" "<command role=\"hg-ext-mq\">qtop</command>&emdash;print the name of the " "current patch" msgstr "<command role=\"hg-ext-mq\">qtop</command>—显示当前补丁的名称" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:467 msgid "" "The <command role=\"hg-ext-mq\">qtop</command> prints the name of the topmost " "currently applied patch." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:472 msgid "" "<command role=\"hg-ext-mq\">qunapplied</command>&emdash;print patches not yet " "applied" msgstr "<command role=\"hg-ext-mq\">qunapplied</command>—显示尚未应用的补丁" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:476 msgid "" "The <command role=\"hg-ext-mq\">qunapplied</command> command prints the names " "of patches from the <filename role=\"special\">series</filename> file that " "are not yet applied. It prints them in order from the next patch that will " "be pushed to the last." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:484 msgid "" "<command role=\"hg-cmd\">hg strip</command>&emdash;remove a revision and " "descendants" msgstr "<command role=\"hg-cmd\">hg strip</command>—删除一个版本及其后继" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:487 msgid "" "The <command role=\"hg-cmd\">hg strip</command> command removes a revision, " "and all of its descendants, from the repository. It undoes the effects of " "the removed revisions from the repository, and updates the working directory " "to the first parent of the removed revision." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:493 msgid "" "The <command role=\"hg-cmd\">hg strip</command> command saves a backup of the " "removed changesets in a bundle, so that they can be reapplied if removed in " "error." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:499 msgid "" "<option role=\"hg-opt-strip\">-b</option>: Save unrelated changesets that are " "intermixed with the stripped changesets in the backup bundle." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:503 msgid "" "<option role=\"hg-opt-strip\">-f</option>: If a branch has multiple heads, " "remove all heads. XXX This should be renamed, and use <literal>-f</literal> " "to strip revs when there are pending changes." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><itemizedlist><listitem><para> #: ../en/appB-mq-ref.xml:508 msgid "<option role=\"hg-opt-strip\">-n</option>: Do not save a backup bundle." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appB-mq-ref.xml:515 msgid "MQ file reference" msgstr "MQ 文件参考" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:518 msgid "The <filename role=\"special\">series</filename> file" msgstr "<filename role=\"special\">序列</filename>文件" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:521 msgid "" "The <filename role=\"special\">series</filename> file contains a list of the " "names of all patches that MQ can apply. It is represented as a list of " "names, with one name saved per line. Leading and trailing white space in " "each line are ignored." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:527 msgid "" "Lines may contain comments. A comment begins with the <quote><literal>#</" "literal></quote> character, and extends to the end of the line. Empty lines, " "and lines that contain only comments, are ignored." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:532 msgid "" "You will often need to edit the <filename role=\"special\">series</filename> " "file by hand, hence the support for comments and empty lines noted above. " "For example, you can comment out a patch temporarily, and <command role=\"hg-" "ext-mq\">qpush</command> will skip over that patch when applying patches. " "You can also change the order in which patches are applied by reordering " "their entries in the <filename role=\"special\">series</filename> file." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:541 msgid "" "Placing the <filename role=\"special\">series</filename> file under revision " "control is also supported; it is a good idea to place all of the patches that " "it refers to under revision control, as well. If you create a patch " "directory using the <option role=\"hg-ext-mq-cmd-qinit-opt\">-c</option> " "option to <command role=\"hg-ext-mq\">qinit</command>, this will be done for " "you automatically." msgstr "" #. type: Content of: <book><appendix><sect1><sect2><title> #: ../en/appB-mq-ref.xml:551 msgid "The <filename role=\"special\">status</filename> file" msgstr "<filename role=\"special\">状态</filename>文件" #. type: Content of: <book><appendix><sect1><sect2><para> #: ../en/appB-mq-ref.xml:554 msgid "" "The <filename role=\"special\">status</filename> file contains the names and " "changeset hashes of all patches that MQ currently has applied. Unlike the " "<filename role=\"special\">series</filename> file, this file is not intended " "for editing. You should not place this file under revision control, or " "modify it in any way. It is used by MQ strictly for internal book-keeping." msgstr "" #. type: Content of: <book><appendix><title> #: ../en/appC-srcinstall.xml:5 msgid "Installing Mercurial from source" msgstr "从源代码安装 Mercurial" #. type: Content of: <book><appendix><sect1><title> #: ../en/appC-srcinstall.xml:8 msgid "On a Unix-like system" msgstr "类 Unix 系统" #. type: Content of: <book><appendix><sect1><para> #: ../en/appC-srcinstall.xml:10 msgid "" "If you are using a Unix-like system that has a sufficiently recent version of " "Python (2.3 or newer) available, it is easy to install Mercurial from source." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appC-srcinstall.xml:14 msgid "" "Download a recent source tarball from <ulink url=\"http://www.selenic.com/" "mercurial/download\">http://www.selenic.com/mercurial/download</ulink>." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appC-srcinstall.xml:17 msgid "Unpack the tarball:" msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appC-srcinstall.xml:20 msgid "" "Go into the source directory and run the installer script. This will build " "Mercurial and install it in your home directory." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appC-srcinstall.xml:27 msgid "" "Once the install finishes, Mercurial will be in the <literal>bin</literal> " "subdirectory of your home directory. Don't forget to make sure that this " "directory is present in your shell's search path." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appC-srcinstall.xml:32 msgid "" "You will probably need to set the <envar>PYTHONPATH</envar> environment " "variable so that the Mercurial executable can find the rest of the Mercurial " "packages. For example, on my laptop, I have set it to <literal>/home/bos/lib/" "python</literal>. The exact path that you will need to use depends on how " "Python was built for your system, but should be easy to figure out. If " "you're uncertain, look through the output of the installer script above, and " "see where the contents of the <literal>mercurial</literal> directory were " "installed to." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appC-srcinstall.xml:44 msgid "On Windows" msgstr "Windows 系统" #. type: Content of: <book><appendix><sect1><para> #: ../en/appC-srcinstall.xml:46 msgid "" "Building and installing Mercurial on Windows requires a variety of tools, a " "fair amount of technical knowledge, and considerable patience. I very much " "<emphasis>do not recommend</emphasis> this route if you are a <quote>casual " "user</quote>. Unless you intend to hack on Mercurial, I strongly suggest " "that you use a binary package instead." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appC-srcinstall.xml:53 msgid "" "If you are intent on building Mercurial from source on Windows, follow the " "<quote>hard way</quote> directions on the Mercurial wiki at <ulink url=" "\"http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall\">http://www." "selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, and expect the " "process to involve a lot of fiddly work." msgstr "" #. type: Content of: <book><appendix><title> #: ../en/appD-license.xml:5 msgid "Open Publication License" msgstr "" #. type: Content of: <book><appendix><para> #: ../en/appD-license.xml:7 msgid "Version 1.0, 8 June 1999" msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:10 msgid "Requirements on both unmodified and modified versions" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:13 msgid "" "The Open Publication works may be reproduced and distributed in whole or in " "part, in any medium physical or electronic, provided that the terms of this " "license are adhered to, and that this license or an incorporation of it by " "reference (with any options elected by the author(s) and/or publisher) is " "displayed in the reproduction." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:20 msgid "Proper form for an incorporation by reference is as follows:" msgstr "" #. type: Content of: <book><appendix><sect1><blockquote><para> #: ../en/appD-license.xml:24 msgid "" "Copyright (c) <emphasis>year</emphasis> by <emphasis>author's name or " "designee</emphasis>. This material may be distributed only subject to the " "terms and conditions set forth in the Open Publication License, v<emphasis>x." "y</emphasis> or later (the latest version is presently available at <ulink " "url=\"http://www.opencontent.org/openpub/\">http://www.opencontent.org/" "openpub/</ulink>)." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:33 msgid "" "The reference must be immediately followed with any options elected by the " "author(s) and/or publisher of the document (see <xref linkend=\"sec:opl:" "options\"/>)." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:37 msgid "" "Commercial redistribution of Open Publication-licensed material is permitted." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:40 msgid "" "Any publication in standard (paper) book form shall require the citation of " "the original publisher and author. The publisher and author's names shall " "appear on all outer surfaces of the book. On all outer surfaces of the book " "the original publisher's name shall be as large as the title of the work and " "cited as possessive with respect to the title." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:49 msgid "Copyright" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:51 msgid "" "The copyright to each Open Publication is owned by its author(s) or designee." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:56 msgid "Scope of license" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:58 msgid "" "The following license terms apply to all Open Publication works, unless " "otherwise explicitly stated in the document." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:62 msgid "" "Mere aggregation of Open Publication works or a portion of an Open " "Publication work with other works or programs on the same media shall not " "cause this license to apply to those other works. The aggregate work shall " "contain a notice specifying the inclusion of the Open Publication material " "and appropriate copyright notice." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:69 msgid "" "<emphasis role=\"bold\">Severability</emphasis>. If any part of this license " "is found to be unenforceable in any jurisdiction, the remaining portions of " "the license remain in force." msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:74 msgid "" "<emphasis role=\"bold\">No warranty</emphasis>. Open Publication works are " "licensed and provided <quote>as is</quote> without warranty of any kind, " "express or implied, including, but not limited to, the implied warranties of " "merchantability and fitness for a particular purpose or a warranty of non-" "infringement." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:83 msgid "Requirements on modified works" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:85 msgid "" "All modified versions of documents covered by this license, including " "translations, anthologies, compilations and partial documents, must meet the " "following requirements:" msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:90 msgid "The modified version must be labeled as such." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:93 msgid "" "The person making the modifications must be identified and the modifications " "dated." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:96 msgid "" "Acknowledgement of the original author and publisher if applicable must be " "retained according to normal academic citation practices." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:100 msgid "The location of the original unmodified document must be identified." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:103 msgid "" "The original author's (or authors') name(s) may not be used to assert or " "imply endorsement of the resulting document without the original author's (or " "authors') permission." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:111 msgid "Good-practice recommendations" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:113 msgid "" "In addition to the requirements of this license, it is requested from and " "strongly recommended of redistributors that:" msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:118 msgid "" "If you are distributing Open Publication works on hardcopy or CD-ROM, you " "provide email notification to the authors of your intent to redistribute at " "least thirty days before your manuscript or media freeze, to give the authors " "time to provide updated documents. This notification should describe " "modifications, if any, made to the document." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:125 msgid "" "All substantive modifications (including deletions) be either clearly marked " "up in the document or else described in an attachment to the document." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:129 msgid "" "Finally, while it is not mandatory under this license, it is considered good " "form to offer a free copy of any hardcopy and CD-ROM expression of an Open " "Publication-licensed work to its author(s)." msgstr "" #. type: Content of: <book><appendix><sect1><title> #: ../en/appD-license.xml:137 msgid "License options" msgstr "" #. type: Content of: <book><appendix><sect1><para> #: ../en/appD-license.xml:139 msgid "" "The author(s) and/or publisher of an Open Publication-licensed document may " "elect certain options by appending language to the reference to or copy of " "the license. These options are considered part of the license instance and " "must be included with the license (or its incorporation by reference) in " "derived works." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:147 msgid "" "To prohibit distribution of substantively modified versions without the " "explicit permission of the author(s). <quote>Substantive modification</quote> " "is defined as a change to the semantic content of the document, and excludes " "mere changes in format or typographical corrections." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:154 msgid "" "To accomplish this, add the phrase <quote>Distribution of substantively " "modified versions of this document is prohibited without the explicit " "permission of the copyright holder.</quote> to the license reference or copy." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:160 msgid "" "To prohibit any publication of this work or derivative works in whole or in " "part in standard (paper) book form for commercial purposes is prohibited " "unless prior permission is obtained from the copyright holder." msgstr "" #. type: Content of: <book><appendix><sect1><orderedlist><listitem><para> #: ../en/appD-license.xml:165 msgid "" "To accomplish this, add the phrase <quote>Distribution of the work or " "derivative of the work in any standard (paper) book form is prohibited unless " "prior permission is obtained from the copyright holder.</quote> to the " "license reference or copy." msgstr "" #. type: Content of: <book><preface><title> #: ../en/ch00-preface.xml:5 msgid "Preface" msgstr "序言" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:8 msgid "Why revision control? Why Mercurial?" msgstr "为什么使用版本控制? 为什么使用 Mercurial?" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:10 msgid "" "Revision control is the process of managing multiple versions of a piece of " "information. In its simplest form, this is something that many people do by " "hand: every time you modify a file, save it under a new name that contains a " "number, each one higher than the number of the preceding version." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:16 msgid "" "Manually managing multiple versions of even a single file is an error-prone " "task, though, so software tools to help automate this process have long been " "available. The earliest automated revision control tools were intended to " "help a single user to manage revisions of a single file. Over the past few " "decades, the scope of revision control tools has expanded greatly; they now " "manage multiple files, and help multiple people to work together. The best " "modern revision control tools have no problem coping with thousands of people " "working together on projects that consist of hundreds of thousands of files." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:27 msgid "" "The arrival of distributed revision control is relatively recent, and so far " "this new field has grown due to people's willingness to explore ill-charted " "territory." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:31 msgid "" "I am writing a book about distributed revision control because I believe that " "it is an important subject that deserves a field guide. I chose to write " "about Mercurial because it is the easiest tool to learn the terrain with, and " "yet it scales to the demands of real, challenging environments where many " "other revision control tools buckle." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:39 msgid "Why use revision control?" msgstr "为什么使用版本控制?" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:41 msgid "" "There are a number of reasons why you or your team might want to use an " "automated revision control tool for a project." msgstr "" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:46 msgid "" "It will track the history and evolution of your project, so you don't have " "to. For every change, you'll have a log of <emphasis>who</emphasis> made it; " "<emphasis>why</emphasis> they made it; <emphasis>when</emphasis> they made " "it; and <emphasis>what</emphasis> the change was." msgstr "" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:53 msgid "" "When you're working with other people, revision control software makes it " "easier for you to collaborate. For example, when people more or less " "simultaneously make potentially incompatible changes, the software will help " "you to identify and resolve those conflicts." msgstr "" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:59 msgid "" "It can help you to recover from mistakes. If you make a change that later " "turns out to be in error, you can revert to an earlier version of one or more " "files. In fact, a <emphasis>really</emphasis> good revision control tool " "will even help you to efficiently figure out exactly when a problem was " "introduced (see <xref linkend=\"sec:undo:bisect\"/> for details)." msgstr "" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:66 msgid "" "It will help you to work simultaneously on, and manage the drift between, " "multiple versions of your project." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:71 msgid "" "Most of these reasons are equally valid&emdash;at least in theory&emdash;" "whether you're working on a project by yourself, or with a hundred other " "people." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:76 msgid "" "A key question about the practicality of revision control at these two " "different scales (<quote>lone hacker</quote> and <quote>huge team</quote>) is " "how its <emphasis>benefits</emphasis> compare to its <emphasis>costs</" "emphasis>. A revision control tool that's difficult to understand or use is " "going to impose a high cost." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:84 msgid "" "A five-hundred-person project is likely to collapse under its own weight " "almost immediately without a revision control tool and process. In this case, " "the cost of using revision control might hardly seem worth considering, since " "<emphasis>without</emphasis> it, failure is almost guaranteed." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:91 msgid "" "On the other hand, a one-person <quote>quick hack</quote> might seem like a " "poor place to use a revision control tool, because surely the cost of using " "one must be close to the overall cost of the project. Right?" msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:96 msgid "" "Mercurial uniquely supports <emphasis>both</emphasis> of these scales of " "development. You can learn the basics in just a few minutes, and due to its " "low overhead, you can apply revision control to the smallest of projects with " "ease. Its simplicity means you won't have a lot of abstruse concepts or " "command sequences competing for mental space with whatever you're " "<emphasis>really</emphasis> trying to do. At the same time, Mercurial's high " "performance and peer-to-peer nature let you scale painlessly to handle large " "projects." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:106 msgid "" "No revision control tool can rescue a poorly run project, but a good choice " "of tools can make a huge difference to the fluidity with which you can work " "on a project." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:113 msgid "The many names of revision control" msgstr "版本控制的别名" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:115 msgid "" "Revision control is a diverse field, so much so that it is referred to by " "many names and acronyms. Here are a few of the more common variations you'll " "encounter:" msgstr "" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:119 msgid "Revision control (RCS)" msgstr "版本控制(RCS)" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:120 msgid "Software configuration management (SCM), or configuration management" msgstr "软件配置管理(SCM),或配置管理" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:122 msgid "Source code management" msgstr "源代码管理" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:123 msgid "Source code control, or source control" msgstr "源代码控制,或源控制" #. type: Content of: <book><preface><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:125 msgid "Version control (VCS)" msgstr "版本控制(VCS)" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:127 msgid "" "Some people claim that these terms actually have different meanings, but in " "practice they overlap so much that there's no agreed or even useful way to " "tease them apart." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:135 msgid "This book is a work in progress" msgstr "本书正在编写中" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:137 msgid "" "I am releasing this book while I am still writing it, in the hope that it " "will prove useful to others. I am writing under an open license in the hope " "that you, my readers, will contribute feedback and perhaps content of your " "own." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:144 msgid "About the examples in this book" msgstr "本书的例子" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:146 msgid "" "This book takes an unusual approach to code samples. Every example is " "<quote>live</quote>&emdash;each one is actually the result of a shell script " "that executes the Mercurial commands you see. Every time an image of the " "book is built from its sources, all the example scripts are automatically " "run, and their current results compared against their expected results." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:153 msgid "" "The advantage of this approach is that the examples are always accurate; they " "describe <emphasis>exactly</emphasis> the behaviour of the version of " "Mercurial that's mentioned at the front of the book. If I update the version " "of Mercurial that I'm documenting, and the output of some command changes, " "the build fails." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:160 msgid "" "There is a small disadvantage to this approach, which is that the dates and " "times you'll see in examples tend to be <quote>squashed</quote> together in a " "way that they wouldn't be if the same commands were being typed by a human. " "Where a human can issue no more than one command every few seconds, with any " "resulting timestamps correspondingly spread out, my automated example scripts " "run many commands in one second." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:168 msgid "" "As an instance of this, several consecutive commits in an example can show up " "as having occurred during the same second. You can see this occur in the " "<literal role=\"hg-ext\">bisect</literal> example in <xref linkend=\"sec:undo:" "bisect\"/>, for instance." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:174 msgid "" "So when you're reading examples, don't place too much weight on the dates or " "times you see in the output of commands. But <emphasis>do</emphasis> be " "confident that the behaviour you're seeing is consistent and reproducible." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:182 msgid "Trends in the field" msgstr "版本控制的发展趋势" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:184 msgid "" "There has been an unmistakable trend in the development and use of revision " "control tools over the past four decades, as people have become familiar with " "the capabilities of their tools and constrained by their limitations." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:189 msgid "" "The first generation began by managing single files on individual computers. " "Although these tools represented a huge advance over ad-hoc manual revision " "control, their locking model and reliance on a single computer limited them " "to small, tightly-knit teams." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:195 msgid "" "The second generation loosened these constraints by moving to network-" "centered architectures, and managing entire projects at a time. As projects " "grew larger, they ran into new problems. With clients needing to talk to " "servers very frequently, server scaling became an issue for large projects. " "An unreliable network connection could prevent remote users from being able " "to talk to the server at all. As open source projects started making read-" "only access available anonymously to anyone, people without commit privileges " "found that they could not use the tools to interact with a project in a " "natural way, as they could not record their changes." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:207 msgid "" "The current generation of revision control tools is peer-to-peer in nature. " "All of these systems have dropped the dependency on a single central server, " "and allow people to distribute their revision control data to where it's " "actually needed. Collaboration over the Internet has moved from constrained " "by technology to a matter of choice and consensus. Modern tools can operate " "offline indefinitely and autonomously, with a network connection only needed " "when syncing changes with another repository." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:219 msgid "A few of the advantages of distributed revision control" msgstr "分布版本控制的优点" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:222 msgid "" "Even though distributed revision control tools have for several years been as " "robust and usable as their previous-generation counterparts, people using " "older tools have not yet necessarily woken up to their advantages. There are " "a number of ways in which distributed tools shine relative to centralised " "ones." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:229 msgid "" "For an individual developer, distributed tools are almost always much faster " "than centralised tools. This is for a simple reason: a centralised tool " "needs to talk over the network for many common operations, because most " "metadata is stored in a single copy on the central server. A distributed " "tool stores all of its metadata locally. All else being equal, talking over " "the network adds overhead to a centralised tool. Don't underestimate the " "value of a snappy, responsive tool: you're going to spend a lot of time " "interacting with your revision control software." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:240 msgid "" "Distributed tools are indifferent to the vagaries of your server " "infrastructure, again because they replicate metadata to so many locations. " "If you use a centralised system and your server catches fire, you'd better " "hope that your backup media are reliable, and that your last backup was " "recent and actually worked. With a distributed tool, you have many backups " "available on every contributor's computer." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:248 msgid "" "The reliability of your network will affect distributed tools far less than " "it will centralised tools. You can't even use a centralised tool without a " "network connection, except for a few highly constrained commands. With a " "distributed tool, if your network connection goes down while you're working, " "you may not even notice. The only thing you won't be able to do is talk to " "repositories on other computers, something that is relatively rare compared " "with local operations. If you have a far-flung team of collaborators, this " "may be significant." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:259 msgid "Advantages for open source projects" msgstr "开源项目的优点" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:261 msgid "" "If you take a shine to an open source project and decide that you would like " "to start hacking on it, and that project uses a distributed revision control " "tool, you are at once a peer with the people who consider themselves the " "<quote>core</quote> of that project. If they publish their repositories, you " "can immediately copy their project history, start making changes, and record " "your work, using the same tools in the same ways as insiders. By contrast, " "with a centralised tool, you must use the software in a <quote>read only</" "quote> mode unless someone grants you permission to commit changes to their " "central server. Until then, you won't be able to record changes, and your " "local modifications will be at risk of corruption any time you try to update " "your client's view of the repository." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><title> #: ../en/ch00-preface.xml:277 msgid "The forking non-problem" msgstr "分叉不是问题" #. type: Content of: <book><preface><sect1><sect2><sect3><para> #: ../en/ch00-preface.xml:279 msgid "" "It has been suggested that distributed revision control tools pose some sort " "of risk to open source projects because they make it easy to <quote>fork</" "quote> the development of a project. A fork happens when there are " "differences in opinion or attitude between groups of developers that cause " "them to decide that they can't work together any longer. Each side takes a " "more or less complete copy of the project's source code, and goes off in its " "own direction." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><para> #: ../en/ch00-preface.xml:289 msgid "" "Sometimes the camps in a fork decide to reconcile their differences. With a " "centralised revision control system, the <emphasis>technical</emphasis> " "process of reconciliation is painful, and has to be performed largely by " "hand. You have to decide whose revision history is going to <quote>win</" "quote>, and graft the other team's changes into the tree somehow. This " "usually loses some or all of one side's revision history." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><para> #: ../en/ch00-preface.xml:298 msgid "" "What distributed tools do with respect to forking is they make forking the " "<emphasis>only</emphasis> way to develop a project. Every single change that " "you make is potentially a fork point. The great strength of this approach is " "that a distributed revision control tool has to be really good at " "<emphasis>merging</emphasis> forks, because forks are absolutely fundamental: " "they happen all the time." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><para> #: ../en/ch00-preface.xml:307 msgid "" "If every piece of work that everybody does, all the time, is framed in terms " "of forking and merging, then what the open source world refers to as a " "<quote>fork</quote> becomes <emphasis>purely</emphasis> a social issue. If " "anything, distributed tools <emphasis>lower</emphasis> the likelihood of a " "fork:" msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:314 msgid "" "They eliminate the social distinction that centralised tools impose: that " "between insiders (people with commit access) and outsiders (people without)." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:318 msgid "" "They make it easier to reconcile after a social fork, because all that's " "involved from the perspective of the revision control software is just " "another merge." msgstr "" #. type: Content of: <book><preface><sect1><sect2><sect3><para> #: ../en/ch00-preface.xml:323 msgid "" "Some people resist distributed tools because they want to retain tight " "control over their projects, and they believe that centralised tools give " "them this control. However, if you're of this belief, and you publish your " "CVS or Subversion repositories publicly, there are plenty of tools available " "that can pull out your entire project's history (albeit slowly) and recreate " "it somewhere that you don't control. So while your control in this case is " "illusory, you are forgoing the ability to fluidly collaborate with whatever " "people feel compelled to mirror and fork your history." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:338 msgid "Advantages for commercial projects" msgstr "商业项目的优点" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:340 msgid "" "Many commercial projects are undertaken by teams that are scattered across " "the globe. Contributors who are far from a central server will see slower " "command execution and perhaps less reliability. Commercial revision control " "systems attempt to ameliorate these problems with remote-site replication add-" "ons that are typically expensive to buy and cantankerous to administer. A " "distributed system doesn't suffer from these problems in the first place. " "Better yet, you can easily set up multiple authoritative servers, say one per " "site, so that there's no redundant communication between repositories over " "expensive long-haul network links." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:352 msgid "" "Centralised revision control systems tend to have relatively low " "scalability. It's not unusual for an expensive centralised system to fall " "over under the combined load of just a few dozen concurrent users. Once " "again, the typical response tends to be an expensive and clunky replication " "facility. Since the load on a central server&emdash;if you have one at " "all&emdash;is many times lower with a distributed tool (because all of the " "data is replicated everywhere), a single cheap server can handle the needs of " "a much larger team, and replication to balance load becomes a simple matter " "of scripting." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:364 msgid "" "If you have an employee in the field, troubleshooting a problem at a " "customer's site, they'll benefit from distributed revision control. The tool " "will let them generate custom builds, try different fixes in isolation from " "each other, and search efficiently through history for the sources of bugs " "and regressions in the customer's environment, all without needing to connect " "to your company's network." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:375 msgid "Why choose Mercurial?" msgstr "为什么选择 Mercurial?" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:377 msgid "" "Mercurial has a unique set of properties that make it a particularly good " "choice as a revision control system." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:380 msgid "It is easy to learn and use." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:381 msgid "It is lightweight." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:382 msgid "It scales excellently." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:383 msgid "It is easy to customise." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:386 msgid "" "If you are at all familiar with revision control systems, you should be able " "to get up and running with Mercurial in less than five minutes. Even if not, " "it will take no more than a few minutes longer. Mercurial's command and " "feature sets are generally uniform and consistent, so you can keep track of a " "few general rules instead of a host of exceptions." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:393 msgid "" "On a small project, you can start working with Mercurial in moments. Creating " "new changes and branches; transferring changes around (whether locally or " "over a network); and history and status operations are all fast. Mercurial " "attempts to stay nimble and largely out of your way by combining low " "cognitive overhead with blazingly fast operations." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:400 msgid "" "The usefulness of Mercurial is not limited to small projects: it is used by " "projects with hundreds to thousands of contributors, each containing tens of " "thousands of files and hundreds of megabytes of source code." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:405 msgid "" "If the core functionality of Mercurial is not enough for you, it's easy to " "build on. Mercurial is well suited to scripting tasks, and its clean " "internals and implementation in Python make it easy to add features in the " "form of extensions. There are a number of popular and useful extensions " "already available, ranging from helping to identify bugs to improving " "performance." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:415 msgid "Mercurial compared with other tools" msgstr "Mercurial 与其它工具的比较" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:417 msgid "" "Before you read on, please understand that this section necessarily reflects " "my own experiences, interests, and (dare I say it) biases. I have used every " "one of the revision control tools listed below, in most cases for several " "years at a time." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:425 ../en/ch00-preface.xml:636 msgid "Subversion" msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:427 msgid "" "Subversion is a popular revision control tool, developed to replace CVS. It " "has a centralised client/server architecture." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:431 msgid "" "Subversion and Mercurial have similarly named commands for performing the " "same operations, so if you're familiar with one, it is easy to learn to use " "the other. Both tools are portable to all popular operating systems." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:436 msgid "" "Prior to version 1.5, Subversion had no useful support for merges. At the " "time of writing, its merge tracking capability is new, and known to be <ulink " "url=\"http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced." "html#svn.branchmerge.advanced.finalword\">complicated and buggy</ulink>." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:442 msgid "" "Mercurial has a substantial performance advantage over Subversion on every " "revision control operation I have benchmarked. I have measured its advantage " "as ranging from a factor of two to a factor of six when compared with " "Subversion 1.4.3's <emphasis>ra_local</emphasis> file store, which is the " "fastest access method available. In more realistic deployments involving a " "network-based store, Subversion will be at a substantially larger " "disadvantage. Because many Subversion commands must talk to the server and " "Subversion does not have useful replication facilities, server capacity and " "network bandwidth become bottlenecks for modestly large projects." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:455 msgid "" "Additionally, Subversion incurs substantial storage overhead to avoid network " "transactions for a few common operations, such as finding modified files " "(<literal>status</literal>) and displaying modifications against the current " "revision (<literal>diff</literal>). As a result, a Subversion working copy " "is often the same size as, or larger than, a Mercurial repository and working " "directory, even though the Mercurial repository contains a complete history " "of the project." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:465 msgid "" "Subversion is widely supported by third party tools. Mercurial currently " "lags considerably in this area. This gap is closing, however, and indeed " "some of Mercurial's GUI tools now outshine their Subversion equivalents. " "Like Mercurial, Subversion has an excellent user manual." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:471 msgid "" "Because Subversion doesn't store revision history on the client, it is well " "suited to managing projects that deal with lots of large, opaque binary " "files. If you check in fifty revisions to an incompressible 10MB file, " "Subversion's client-side space usage stays constant The space used by any " "distributed SCM will grow rapidly in proportion to the number of revisions, " "because the differences between each revision are large." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:480 msgid "" "In addition, it's often difficult or, more usually, impossible to merge " "different versions of a binary file. Subversion's ability to let a user lock " "a file, so that they temporarily have the exclusive right to commit changes " "to it, can be a significant advantage to a project where binary files are " "widely used." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:487 msgid "" "Mercurial can import revision history from a Subversion repository. It can " "also export revision history to a Subversion repository. This makes it easy " "to <quote>test the waters</quote> and use Mercurial and Subversion in " "parallel before deciding to switch. History conversion is incremental, so " "you can perform an initial conversion, then small additional conversions " "afterwards to bring in new changes." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:499 ../en/ch00-preface.xml:638 msgid "Git" msgstr "Git" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:501 msgid "" "Git is a distributed revision control tool that was developed for managing " "the Linux kernel source tree. Like Mercurial, its early design was somewhat " "influenced by Monotone." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:506 msgid "" "Git has a very large command set, with version 1.5.0 providing 139 individual " "commands. It has something of a reputation for being difficult to learn. " "Compared to Git, Mercurial has a strong focus on simplicity." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:511 msgid "" "In terms of performance, Git is extremely fast. In several cases, it is " "faster than Mercurial, at least on Linux, while Mercurial performs better on " "other operations. However, on Windows, the performance and general level of " "support that Git provides is, at the time of writing, far behind that of " "Mercurial." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:518 msgid "" "While a Mercurial repository needs no maintenance, a Git repository requires " "frequent manual <quote>repacks</quote> of its metadata. Without these, " "performance degrades, while space usage grows rapidly. A server that " "contains many Git repositories that are not rigorously and frequently " "repacked will become heavily disk-bound during backups, and there have been " "instances of daily backups taking far longer than 24 hours as a result. A " "freshly packed Git repository is slightly smaller than a Mercurial " "repository, but an unpacked repository is several orders of magnitude larger." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:529 msgid "" "The core of Git is written in C. Many Git commands are implemented as shell " "or Perl scripts, and the quality of these scripts varies widely. I have " "encountered several instances where scripts charged along blindly in the " "presence of errors that should have been fatal." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:535 msgid "Mercurial can import revision history from a Git repository." msgstr "" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:541 ../en/ch00-preface.xml:637 msgid "CVS" msgstr "CVS" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:543 msgid "" "CVS is probably the most widely used revision control tool in the world. Due " "to its age and internal untidiness, it has been only lightly maintained for " "many years." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:547 msgid "" "It has a centralised client/server architecture. It does not group related " "file changes into atomic commits, making it easy for people to <quote>break " "the build</quote>: one person can successfully commit part of a change and " "then be blocked by the need for a merge, causing other people to see only a " "portion of the work they intended to do. This also affects how you work with " "project history. If you want to see all of the modifications someone made as " "part of a task, you will need to manually inspect the descriptions and " "timestamps of the changes made to each file involved (if you even know what " "those files were)." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:559 msgid "" "CVS has a muddled notion of tags and branches that I will not attempt to even " "describe. It does not support renaming of files or directories well, making " "it easy to corrupt a repository. It has almost no internal consistency " "checking capabilities, so it is usually not even possible to tell whether or " "how a repository is corrupt. I would not recommend CVS for any project, " "existing or new." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:567 msgid "" "Mercurial can import CVS revision history. However, there are a few caveats " "that apply; these are true of every other revision control tool's CVS " "importer, too. Due to CVS's lack of atomic changes and unversioned " "filesystem hierarchy, it is not possible to reconstruct CVS history " "completely accurately; some guesswork is involved, and renames will usually " "not show up. Because a lot of advanced CVS administration has to be done by " "hand and is hence error-prone, it's common for CVS importers to run into " "multiple problems with corrupted repositories (completely bogus revision " "timestamps and files that have remained locked for over a decade are just two " "of the less interesting problems I can recall from personal experience)." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:581 msgid "Mercurial can import revision history from a CVS repository." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:587 msgid "Commercial tools" msgstr "商业工具" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:589 msgid "" "Perforce has a centralised client/server architecture, with no client-side " "caching of any data. Unlike modern revision control tools, Perforce requires " "that a user run a command to inform the server about every file they intend " "to edit." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:595 msgid "" "The performance of Perforce is quite good for small teams, but it falls off " "rapidly as the number of users grows beyond a few dozen. Modestly large " "Perforce installations require the deployment of proxies to cope with the " "load their users generate." msgstr "" #. type: Content of: <book><preface><sect1><sect2><title> #: ../en/ch00-preface.xml:604 msgid "Choosing a revision control tool" msgstr "选择版本控制工具" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:606 msgid "" "With the exception of CVS, all of the tools listed above have unique " "strengths that suit them to particular styles of work. There is no single " "revision control tool that is best in all situations." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:611 msgid "" "As an example, Subversion is a good choice for working with frequently edited " "binary files, due to its centralised nature and support for file locking." msgstr "" #. type: Content of: <book><preface><sect1><sect2><para> #: ../en/ch00-preface.xml:615 msgid "" "I personally find Mercurial's properties of simplicity, performance, and good " "merge support to be a compelling combination that has served me well for " "several years." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:623 msgid "Switching from another tool to Mercurial" msgstr "从其它工具切换到 Mercurial" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:625 msgid "" "Mercurial is bundled with an extension named <literal role=\"hg-ext" "\">convert</literal>, which can incrementally import revision history from " "several other revision control tools. By <quote>incremental</quote>, I mean " "that you can convert all of a project's history to date in one go, then rerun " "the conversion later to obtain new changes that happened after the initial " "conversion." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:633 msgid "" "The revision control tools supported by <literal role=\"hg-ext\">convert</" "literal> are as follows:" msgstr "<literal role=\"hg-ext\">convert</literal> 支持的版本控制工具有:" #. type: Content of: <book><preface><sect1><itemizedlist><listitem><para> #: ../en/ch00-preface.xml:639 msgid "Darcs" msgstr "Darcs" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:641 msgid "" "In addition, <literal role=\"hg-ext\">convert</literal> can export changes " "from Mercurial to Subversion. This makes it possible to try Subversion and " "Mercurial in parallel before committing to a switchover, without risking the " "loss of any work." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:647 msgid "" "The <command role=\"hg-ext-convert\">convert</command> command is easy to " "use. Simply point it at the path or URL of the source repository, optionally " "give it the name of the destination repository, and it will start working. " "After the initial conversion, just run the same command again to import new " "changes." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:656 msgid "A short history of revision control" msgstr "版本控制简史" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:658 msgid "" "The best known of the old-time revision control tools is SCCS (Source Code " "Control System), which Marc Rochkind wrote at Bell Labs, in the early 1970s. " "SCCS operated on individual files, and required every person working on a " "project to have access to a shared workspace on a single system. Only one " "person could modify a file at any time; arbitration for access to files was " "via locks. It was common for people to lock files, and later forget to " "unlock them, preventing anyone else from modifying those files without the " "help of an administrator." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:669 msgid "" "Walter Tichy developed a free alternative to SCCS in the early 1980s; he " "called his program RCS (Revision Control System). Like SCCS, RCS required " "developers to work in a single shared workspace, and to lock files to prevent " "multiple people from modifying them simultaneously." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:675 msgid "" "Later in the 1980s, Dick Grune used RCS as a building block for a set of " "shell scripts he initially called cmt, but then renamed to CVS (Concurrent " "Versions System). The big innovation of CVS was that it let developers work " "simultaneously and somewhat independently in their own personal workspaces. " "The personal workspaces prevented developers from stepping on each other's " "toes all the time, as was common with SCCS and RCS. Each developer had a copy " "of every project file, and could modify their copies independently. They had " "to merge their edits prior to committing changes to the central repository." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:686 msgid "" "Brian Berliner took Grune's original scripts and rewrote them in C, releasing " "in 1989 the code that has since developed into the modern version of CVS. " "CVS subsequently acquired the ability to operate over a network connection, " "giving it a client/server architecture. CVS's architecture is centralised; " "only the server has a copy of the history of the project. Client workspaces " "just contain copies of recent versions of the project's files, and a little " "metadata to tell them where the server is. CVS has been enormously " "successful; it is probably the world's most widely used revision control " "system." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:697 msgid "" "In the early 1990s, Sun Microsystems developed an early distributed revision " "control system, called TeamWare. A TeamWare workspace contains a complete " "copy of the project's history. TeamWare has no notion of a central " "repository. (CVS relied upon RCS for its history storage; TeamWare used " "SCCS.)" msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:704 msgid "" "As the 1990s progressed, awareness grew of a number of problems with CVS. It " "records simultaneous changes to multiple files individually, instead of " "grouping them together as a single logically atomic operation. It does not " "manage its file hierarchy well; it is easy to make a mess of a repository by " "renaming files and directories. Worse, its source code is difficult to read " "and maintain, which made the <quote>pain level</quote> of fixing these " "architectural problems prohibitive." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:714 msgid "" "In 2001, Jim Blandy and Karl Fogel, two developers who had worked on CVS, " "started a project to replace it with a tool that would have a better " "architecture and cleaner code. The result, Subversion, does not stray from " "CVS's centralised client/server model, but it adds multi-file atomic commits, " "better namespace management, and a number of other features that make it a " "generally better tool than CVS. Since its initial release, it has rapidly " "grown in popularity." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:723 msgid "" "More or less simultaneously, Graydon Hoare began working on an ambitious " "distributed revision control system that he named Monotone. While Monotone " "addresses many of CVS's design flaws and has a peer-to-peer architecture, it " "goes beyond earlier (and subsequent) revision control tools in a number of " "innovative ways. It uses cryptographic hashes as identifiers, and has an " "integral notion of <quote>trust</quote> for code from different sources." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:732 msgid "" "Mercurial began life in 2005. While a few aspects of its design are " "influenced by Monotone, Mercurial focuses on ease of use, high performance, " "and scalability to very large projects." msgstr "" #. type: Content of: <book><preface><sect1><title> #: ../en/ch00-preface.xml:740 msgid "Colophon&emdash;this book is Free" msgstr "后记—本书是自由的!" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:742 msgid "" "This book is licensed under the Open Publication License, and is produced " "entirely using Free Software tools. It is typeset with DocBook XML. " "Illustrations are drawn and rendered with <ulink url=\"http://www.inkscape." "org/\">Inkscape</ulink>." msgstr "" #. type: Content of: <book><preface><sect1><para> #: ../en/ch00-preface.xml:747 msgid "" "The complete source code for this book is published as a Mercurial " "repository, at <ulink url=\"http://hg.serpentine.com/mercurial/book\">http://" "hg.serpentine.com/mercurial/book</ulink>." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch01-tour-basic.xml:5 msgid "A tour of Mercurial: the basics" msgstr "Mercurial 教程: 基础知识" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:8 msgid "Installing Mercurial on your system" msgstr "安装 Mercurial" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:10 msgid "" "Prebuilt binary packages of Mercurial are available for every popular " "operating system. These make it easy to start using Mercurial on your " "computer immediately." msgstr "" "对于每种流行的操作系统,都有已经构建的二进制软件包。这让在你的计算机上开始使" "用 Mercurial 变得很容易。" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:15 msgid "Windows" msgstr "Windows" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:17 msgid "" "The best version of Mercurial for Windows is TortoiseHg, which can be found " "at <ulink url=\"http://bitbucket.org/tortoisehg/stable/wiki/Home\">http://" "bitbucket.org/tortoisehg/stable/wiki/Home</ulink>. This package has no " "external dependencies; it <quote>just works</quote>. It provides both " "command line and graphical user interfaces." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:27 msgid "Mac OS X" msgstr "Mac OS X" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:29 msgid "" "Lee Cantey publishes an installer of Mercurial for Mac OS X at <ulink url=" "\"http://mercurial.berkwood.com\">http://mercurial.berkwood.com</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:35 msgid "Linux" msgstr "Linux" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:37 msgid "" "Because each Linux distribution has its own packaging tools, policies, and " "rate of development, it's difficult to give a comprehensive set of " "instructions on how to install Mercurial binaries. The version of Mercurial " "that you will end up with can vary depending on how active the person is who " "maintains the package for your distribution." msgstr "" "由于每种 Linux 发行版都有自己的包管理工具,开发策略和进度,从而很难给出安装 " "Mercurial 二进制包的全面说明。你安装的 Mercurial 版本,在很大程度上依赖于你所" "使用的发行版的 Mercurial 维护者的活跃程度。" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:44 msgid "" "To keep things simple, I will focus on installing Mercurial from the command " "line under the most popular Linux distributions. Most of these distributions " "provide graphical package managers that will let you install Mercurial with a " "single click; the package name to look for is <literal>mercurial</literal>." msgstr "" "为了让事情简单,我会致力于说明在最流行的 Linux 发行版中,从命令行安装 " "Mercurial 的方法。这些发行版都提供了图形界面的包管理器,让你通过点击鼠标安装 " "Mercurial;寻找的包名称是 <literal>mercurial</literal>。" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:52 msgid "Ubuntu and Debian:" msgstr "Ubuntu 与 Debian:" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:54 msgid "Fedora and OpenSUSE:" msgstr "Fedora and OpenSUSE:" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:56 msgid "Gentoo:" msgstr "Gentoo:" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:62 msgid "Solaris" msgstr "Solaris" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:64 msgid "" "SunFreeWare, at <ulink url=\"http://www.sunfreeware.com\">http://www." "sunfreeware.com</ulink>, provides prebuilt packages of Mercurial." msgstr "" "位于 <ulink url=\"http://www.sunfreeware.com\">http://www.sunfreeware.com</" "ulink> 的 SunFreeWare 提供了 Mercurial 的二进制安装包。" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:73 msgid "Getting started" msgstr "开始" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:75 msgid "" "To begin, we'll use the <command role=\"hg-cmd\">hg version</command> command " "to find out whether Mercurial is actually installed properly. The actual " "version information that it prints isn't so important; it's whether it prints " "anything at all that we care about." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:84 msgid "Built-in help" msgstr "内置帮助" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:86 msgid "" "Mercurial provides a built-in help system. This is invaluable for those " "times when you find yourself stuck trying to remember how to run a command. " "If you are completely stuck, simply run <command role=\"hg-cmd\">hg help</" "command>; it will print a brief list of commands, along with a description of " "what each does. If you ask for help on a specific command (as below), it " "prints more detailed information." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:97 msgid "" "For a more impressive level of detail (which you won't usually need) run " "<command role=\"hg-cmd\">hg help <option role=\"hg-opt-global\">-v</option></" "command>. The <option role=\"hg-opt-global\">-v</option> option is short for " "<option role=\"hg-opt-global\">--verbose</option>, and tells Mercurial to " "print more information than it usually would." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:108 msgid "Working with a repository" msgstr "使用版本库" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:110 msgid "" "In Mercurial, everything happens inside a <emphasis>repository</emphasis>. " "The repository for a project contains all of the files that <quote>belong to</" "quote> that project, along with a historical record of the project's files." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:116 msgid "" "There's nothing particularly magical about a repository; it is simply a " "directory tree in your filesystem that Mercurial treats as special. You can " "rename or delete a repository any time you like, using either the command " "line or your file browser." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:123 msgid "Making a local copy of a repository" msgstr "创建版本库的工作副本" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:125 msgid "" "<emphasis>Copying</emphasis> a repository is just a little bit special. " "While you could use a normal file copying command to make a copy of a " "repository, it's best to use a built-in command that Mercurial provides. " "This command is called <command role=\"hg-cmd\">hg clone</command>, because " "it makes an identical copy of an existing repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:134 msgid "" "One advantage of using <command role=\"hg-cmd\">hg clone</command> is that, " "as we can see above, it lets us clone repositories over the network. Another " "is that it remembers where we cloned from, which we'll find useful soon when " "we want to fetch new changes from another repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:140 msgid "" "If our clone succeeded, we should now have a local directory called <filename " "class=\"directory\">hello</filename>. This directory will contain some files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:146 msgid "" "These files have the same contents and history in our repository as they do " "in the repository we cloned." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:149 msgid "" "Every Mercurial repository is complete, self-contained, and independent. It " "contains its own private copy of a project's files and history. As we just " "mentioned, a cloned repository remembers the location of the repository it " "was cloned from, but Mercurial will not communicate with that repository, or " "any other, unless you tell it to." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:156 msgid "" "What this means for now is that we're free to experiment with our repository, " "safe in the knowledge that it's a private <quote>sandbox</quote> that won't " "affect anyone else." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:162 msgid "What's in a repository?" msgstr "什么是版本库?" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:164 msgid "" "When we take a more detailed look inside a repository, we can see that it " "contains a directory named <filename class=\"directory\">.hg</filename>. " "This is where Mercurial keeps all of its metadata for the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:171 msgid "" "The contents of the <filename class=\"directory\">.hg</filename> directory " "and its subdirectories are private to Mercurial. Every other file and " "directory in the repository is yours to do with as you please." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:177 msgid "" "To introduce a little terminology, the <filename class=\"directory\">.hg</" "filename> directory is the <quote>real</quote> repository, and all of the " "files and directories that coexist with it are said to live in the " "<emphasis>working directory</emphasis>. An easy way to remember the " "distinction is that the <emphasis>repository</emphasis> contains the " "<emphasis>history</emphasis> of your project, while the <emphasis>working " "directory</emphasis> contains a <emphasis>snapshot</emphasis> of your project " "at a particular point in history." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:192 msgid "A tour through history" msgstr "回溯历史" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:194 msgid "" "One of the first things we might want to do with a new, unfamiliar repository " "is understand its history. The <command role=\"hg-cmd\">hg log</command> " "command gives us a view of the history of changes in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:201 msgid "" "By default, this command prints a brief paragraph of output for each change " "to the project that was recorded. In Mercurial terminology, we call each of " "these recorded events a <emphasis>changeset</emphasis>, because it can " "contain a record of changes to several files." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:207 msgid "" "The fields in a record of output from <command role=\"hg-cmd\">hg log</" "command> are as follows." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:211 msgid "" "<literal>changeset</literal>: This field has the format of a number, followed " "by a colon, followed by a hexadecimal (or <emphasis>hex</emphasis>) string. " "These are <emphasis>identifiers</emphasis> for the changeset. The hex string " "is a unique identifier: the same hex string will always refer to the same " "changeset. The number is shorter and easier to type than the hex string, but " "it isn't unique: the same number in two different clones of a repository may " "identify different changesets. Why provide the number at all, then? For " "local convenience." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:223 msgid "" "<literal>user</literal>: The identity of the person who created the " "changeset. This is a free-form field, but it most often contains a person's " "name and email address." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:227 msgid "" "<literal>date</literal>: The date and time on which the changeset was " "created, and the timezone in which it was created. (The date and time are " "local to that timezone; they display what time and date it was for the person " "who created the changeset.)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:232 msgid "" "<literal>summary</literal>: The first line of the text message that the " "creator of the changeset entered to describe the changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:236 msgid "" "Some changesets, such as the first in the list above, have a <literal>tag</" "literal> field. A tag is another way to identify a changeset, by giving it " "an easy-to-remember name. (The tag named <literal>tip</literal> is special: " "it always refers to the newest change in a repository.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:244 msgid "" "The default output printed by <command role=\"hg-cmd\">hg log</command> is " "purely a summary; it is missing a lot of detail." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:248 msgid "" "<xref linkend=\"fig:tour-basic:history\"/> provides a graphical " "representation of the history of the <filename class=\"directory\">hello</" "filename> repository, to make it a little easier to see which direction " "history is <quote>flowing</quote> in. We'll be returning to this figure " "several times in this chapter and the chapter that follows." msgstr "" #. type: Content of: <book><chapter><sect1><figure><title> #: ../en/ch01-tour-basic.xml:257 msgid "" "Graphical history of the <filename class=\"directory\">hello</filename> " "repository" msgstr "版本库 <filename class=\"directory\">hello</filename> 的历史图" #. type: Content of: <book><chapter><sect1><figure> #: ../en/ch01-tour-basic.xml:259 ../en/ch02-tour-merge.xml:50 #: ../en/ch02-tour-merge.xml:181 ../en/ch03-concepts.xml:293 msgid "<placeholder type=\"mediaobject\" id=\"0\"/>" msgstr "" #. type: Content of: <book><chapter><sect1><figure><mediaobject> #: ../en/ch01-tour-basic.xml:260 msgid "" "<imageobject><imagedata fileref=\"figs/tour-history.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject><textobject><phrase> #: ../en/ch01-tour-basic.xml:261 ../en/ch02-tour-merge.xml:52 #: ../en/ch02-tour-merge.xml:82 ../en/ch02-tour-merge.xml:129 #: ../en/ch02-tour-merge.xml:183 ../en/ch02-tour-merge.xml:254 #: ../en/ch03-concepts.xml:57 ../en/ch03-concepts.xml:106 #: ../en/ch03-concepts.xml:191 ../en/ch03-concepts.xml:295 #: ../en/ch03-concepts.xml:346 ../en/ch03-concepts.xml:361 #: ../en/ch03-concepts.xml:402 ../en/ch03-concepts.xml:422 #: ../en/ch03-concepts.xml:465 ../en/ch05-collab.xml:276 #: ../en/ch08-undo.xml:365 ../en/ch08-undo.xml:412 ../en/ch08-undo.xml:477 #: ../en/ch08-undo.xml:515 ../en/ch11-mq.xml:412 msgid "XXX add text" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:266 msgid "Changesets, revisions, and talking to other people" msgstr "修改集,版本,与其它用户交互" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:269 msgid "" "As English is a notoriously sloppy language, and computer science has a " "hallowed history of terminological confusion (why use one term when four will " "do?), revision control has a variety of words and phrases that mean the same " "thing. If you are talking about Mercurial history with other people, you " "will find that the word <quote>changeset</quote> is often compressed to " "<quote>change</quote> or (when written) <quote>cset</quote>, and sometimes a " "changeset is referred to as a <quote>revision</quote> or a <quote>rev</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:279 msgid "" "While it doesn't matter what <emphasis>word</emphasis> you use to refer to " "the concept of <quote>a changeset</quote>, the <emphasis>identifier</" "emphasis> that you use to refer to <quote>a <emphasis>specific</emphasis> " "changeset</quote> is of great importance. Recall that the <literal>changeset</" "literal> field in the output from <command role=\"hg-cmd\">hg log</command> " "identifies a changeset using both a number and a hexadecimal string." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:288 msgid "" "The revision number is a handy notation that is <emphasis>only valid in that " "repository</emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:291 msgid "" "The hexadecimal string is the <emphasis>permanent, unchanging identifier</" "emphasis> that will always identify that exact changeset in <emphasis>every</" "emphasis> copy of the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:297 msgid "" "This distinction is important. If you send someone an email talking about " "<quote>revision 33</quote>, there's a high likelihood that their revision 33 " "will <emphasis>not be the same</emphasis> as yours. The reason for this is " "that a revision number depends on the order in which changes arrived in a " "repository, and there is no guarantee that the same changes will happen in " "the same order in different repositories. Three changes <literal>a,b,c</" "literal> can easily appear in one repository as <literal>0,1,2</literal>, " "while in another as <literal>0,2,1</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:309 msgid "" "Mercurial uses revision numbers purely as a convenient shorthand. If you " "need to discuss a changeset with someone, or make a record of a changeset for " "some other reason (for example, in a bug report), use the hexadecimal " "identifier." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:317 msgid "Viewing specific revisions" msgstr "察看指定版本" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:319 msgid "" "To narrow the output of <command role=\"hg-cmd\">hg log</command> down to a " "single revision, use the <option role=\"hg-opt-log\">-r</option> (or <option " "role=\"hg-opt-log\">--rev</option>) option. You can use either a revision " "number or a hexadecimal identifier, and you can provide as many revisions as " "you want." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:328 msgid "" "If you want to see the history of several revisions without having to list " "each one, you can use <emphasis>range notation</emphasis>; this lets you " "express the idea <quote>I want all revisions between <literal>abc</literal> " "and <literal>def</literal>, inclusive</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:336 msgid "" "Mercurial also honours the order in which you specify revisions, so <command " "role=\"hg-cmd\">hg log -r 2:4</command> prints 2, 3, and 4. while <command " "role=\"hg-cmd\">hg log -r 4:2</command> prints 4, 3, and 2." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:343 msgid "More detailed information" msgstr "更详细的信息" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:345 msgid "" "While the summary information printed by <command role=\"hg-cmd\">hg log</" "command> is useful if you already know what you're looking for, you may need " "to see a complete description of the change, or a list of the files changed, " "if you're trying to decide whether a changeset is the one you're looking for. " "The <command role=\"hg-cmd\">hg log</command> command's <option role=\"hg-opt-" "global\">-v</option> (or <option role=\"hg-opt-global\">--verbose</option>) " "option gives you this extra detail." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:357 msgid "" "If you want to see both the description and content of a change, add the " "<option role=\"hg-opt-log\">-p</option> (or <option role=\"hg-opt-log\">--" "patch</option>) option. This displays the content of a change as a " "<emphasis>unified diff</emphasis> (if you've never seen a unified diff " "before, see <xref linkend=\"sec:mq:patch\"/> for an overview)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:367 msgid "" "The <option role=\"hg-opt-log\">-p</option> option is tremendously useful, so " "it's well worth remembering." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:374 msgid "All about command options" msgstr "命令选项" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:376 msgid "" "Let's take a brief break from exploring Mercurial commands to discuss a " "pattern in the way that they work; you may find this useful to keep in mind " "as we continue our tour." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:380 msgid "" "Mercurial has a consistent and straightforward approach to dealing with the " "options that you can pass to commands. It follows the conventions for " "options that are common to modern Linux and Unix systems." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:387 msgid "" "Every option has a long name. For example, as we've already seen, the " "<command role=\"hg-cmd\">hg log</command> command accepts a <option role=\"hg-" "opt-log\">--rev</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:393 msgid "" "Most options have short names, too. Instead of <option role=\"hg-opt-log\">--" "rev</option>, we can use <option role=\"hg-opt-log\">-r</option>. (The " "reason that some options don't have short names is that the options in " "question are rarely used.)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:400 msgid "" "Long options start with two dashes (e.g. <option role=\"hg-opt-log\">--rev</" "option>), while short options start with one (e.g. <option role=\"hg-opt-log" "\">-r</option>)." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:406 msgid "" "Option naming and usage is consistent across commands. For example, every " "command that lets you specify a changeset ID or revision number accepts both " "<option role=\"hg-opt-log\">-r</option> and <option role=\"hg-opt-log\">--" "rev</option> arguments." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch01-tour-basic.xml:413 msgid "" "If you are using short options, you can save typing by running them together. " "For example, the command <command role=\"hg-cmd\">hg log -v -p -r 2</command> " "can be written as <command role=\"hg-cmd\">hg log -vpr2</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:420 msgid "" "In the examples throughout this book, I use short options instead of long. " "This just reflects my own preference, so don't read anything significant into " "it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:424 msgid "" "Most commands that print output of some kind will print more output when " "passed a <option role=\"hg-opt-global\">-v</option> (or <option role=\"hg-opt-" "global\">--verbose</option>) option, and less when passed <option role=\"hg-" "opt-global\">-q</option> (or <option role=\"hg-opt-global\">--quiet</option>)." msgstr "" #. type: Content of: <book><chapter><sect1><note><title> #: ../en/ch01-tour-basic.xml:431 msgid "Option naming consistency" msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch01-tour-basic.xml:433 msgid "" "Almost always, Mercurial commands use consistent option names to refer to the " "same concepts. For instance, if a command deals with changesets, you'll " "always identify them with <option role=\"hg-opt-log\">--rev</option> or " "<option role=\"hg-opt-log\">-r</option>. This consistent use of option names " "makes it easier to remember what options a particular command takes." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:444 msgid "Making and reviewing changes" msgstr "创建和复审修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:446 msgid "" "Now that we have a grasp of viewing history in Mercurial, let's take a look " "at making some changes and examining them." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:450 msgid "" "The first thing we'll do is isolate our experiment in a repository of its " "own. We use the <command role=\"hg-cmd\">hg clone</command> command, but we " "don't need to clone a copy of the remote repository. Since we already have a " "copy of it locally, we can just clone that instead. This is much faster than " "cloning over the network, and cloning a local repository uses less disk space " "in most cases, too<placeholder type=\"footnote\" id=\"0\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><para><footnote><para> #: ../en/ch01-tour-basic.xml:457 msgid "" "The saving of space arises when source and destination repositories are on " "the same filesystem, in which case Mercurial will use hardlinks to do copy-on-" "write sharing of its internal metadata. If that explanation meant nothing to " "you, don't worry: everything happens transparently and automatically, and you " "don't need to understand it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:467 msgid "" "As an aside, it's often good practice to keep a <quote>pristine</quote> copy " "of a remote repository around, which you can then make temporary clones of to " "create sandboxes for each task you want to work on. This lets you work on " "multiple tasks in parallel, each isolated from the others until it's complete " "and you're ready to integrate it back. Because local clones are so cheap, " "there's almost no overhead to cloning and destroying repositories whenever " "you want." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:476 msgid "" "In our <filename class=\"directory\">my-hello</filename> repository, we have " "a file <filename>hello.c</filename> that contains the classic <quote>hello, " "world</quote> program." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:482 msgid "Let's edit this file so that it prints a second line of output." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:487 msgid "" "Mercurial's <command role=\"hg-cmd\">hg status</command> command will tell us " "what Mercurial knows about the files in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:493 msgid "" "The <command role=\"hg-cmd\">hg status</command> command prints no output for " "some files, but a line starting with <quote><literal>M</literal></quote> for " "<filename>hello.c</filename>. Unless you tell it to, <command role=\"hg-cmd" "\">hg status</command> will not print any output for files that have not been " "modified." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:500 msgid "" "The <quote><literal>M</literal></quote> indicates that Mercurial has noticed " "that we modified <filename>hello.c</filename>. We didn't need to " "<emphasis>inform</emphasis> Mercurial that we were going to modify the file " "before we started, or that we had modified the file after we were done; it " "was able to figure this out itself." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:508 msgid "" "It's somewhat helpful to know that we've modified <filename>hello.c</" "filename>, but we might prefer to know exactly <emphasis>what</emphasis> " "changes we've made to it. To do this, we use the <command role=\"hg-cmd\">hg " "diff</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:517 ../en/ch11-mq.xml:187 msgid "Understanding patches" msgstr "理解补丁" #. type: Content of: <book><chapter><sect1><tip><para> #: ../en/ch01-tour-basic.xml:519 msgid "" "Remember to take a look at <xref linkend=\"sec:mq:patch\"/> if you don't know " "how to read output above." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:525 msgid "Recording changes in a new changeset" msgstr "在新修改集中记录修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:527 msgid "" "We can modify files, build and test our changes, and use <command role=\"hg-" "cmd\">hg status</command> and <command role=\"hg-cmd\">hg diff</command> to " "review our changes, until we're satisfied with what we've done and arrive at " "a natural stopping point where we want to record our work in a new changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:534 msgid "" "The <command role=\"hg-cmd\">hg commit</command> command lets us create a new " "changeset; we'll usually refer to this as <quote>making a commit</quote> or " "<quote>committing</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:540 msgid "Setting up a username" msgstr "配置用户名称" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:542 msgid "" "When you try to run <command role=\"hg-cmd\">hg commit</command> for the " "first time, it is not guaranteed to succeed. Mercurial records your name and " "address with each change that you commit, so that you and others will later " "be able to tell who made each change. Mercurial tries to automatically " "figure out a sensible username to commit the change with. It will attempt " "each of the following methods, in order:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch01-tour-basic.xml:551 msgid "" "If you specify a <option role=\"hg-opt-commit\">-u</option> option to the " "<command role=\"hg-cmd\">hg commit</command> command on the command line, " "followed by a username, this is always given the highest precedence." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch01-tour-basic.xml:556 msgid "" "If you have set the <envar>HGUSER</envar> environment variable, this is " "checked next." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch01-tour-basic.xml:559 msgid "" "If you create a file in your home directory called <filename role=\"special" "\">.hgrc</filename>, with a <envar role=\"rc-item-ui\">username</envar> " "entry, that will be used next. To see what the contents of this file should " "look like, refer to <xref linkend=\"sec:tour-basic:username\"/> below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch01-tour-basic.xml:567 msgid "" "If you have set the <envar>EMAIL</envar> environment variable, this will be " "used next." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch01-tour-basic.xml:570 msgid "" "Mercurial will query your system to find out your local user name and host " "name, and construct a username from these components. Since this often " "results in a username that is not very useful, it will print a warning if it " "has to do this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:577 msgid "" "If all of these mechanisms fail, Mercurial will fail, printing an error " "message. In this case, it will not let you commit until you set up a " "username." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:581 msgid "" "You should think of the <envar>HGUSER</envar> environment variable and the " "<option role=\"hg-opt-commit\">-u</option> option to the <command role=\"hg-" "cmd\">hg commit</command> command as ways to <emphasis>override</emphasis> " "Mercurial's default selection of username. For normal use, the simplest and " "most robust way to set a username for yourself is by creating a <filename " "role=\"special\">.hgrc</filename> file; see below for details." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch01-tour-basic.xml:590 msgid "Creating a Mercurial configuration file" msgstr "创建 Mercurial 的配置文件" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch01-tour-basic.xml:592 msgid "" "To set a user name, use your favourite editor to create a file called " "<filename role=\"special\">.hgrc</filename> in your home directory. " "Mercurial will use this file to look up your personalised configuration " "settings. The initial contents of your <filename role=\"special\">.hgrc</" "filename> should look like this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><remark> #: ../en/ch01-tour-basic.xml:600 msgid "Figure out what the appropriate directory is on Windows." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch01-tour-basic.xml:607 msgid "" "The <quote><literal>[ui]</literal></quote> line begins a <emphasis>section</" "emphasis> of the config file, so you can read the <quote><literal>username " "= ...</literal></quote> line as meaning <quote>set the value of the " "<literal>username</literal> item in the <literal>ui</literal> section</" "quote>. A section continues until a new section begins, or the end of the " "file. Mercurial ignores empty lines and treats any text from " "<quote><literal>#</literal></quote> to the end of a line as a comment." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch01-tour-basic.xml:620 msgid "Choosing a user name" msgstr "选择用户名称" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch01-tour-basic.xml:622 msgid "" "You can use any text you like as the value of the <literal>username</literal> " "config item, since this information is for reading by other people, but will " "not be interpreted by Mercurial. The convention that most people follow is " "to use their name and email address, as in the example above." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><note><para> #: ../en/ch01-tour-basic.xml:629 msgid "" "Mercurial's built-in web server obfuscates email addresses, to make it more " "difficult for the email harvesting tools that spammers use. This reduces the " "likelihood that you'll start receiving more junk email if you publish a " "Mercurial repository on the web." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:639 msgid "Writing a commit message" msgstr "写提交日志" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:641 msgid "" "When we commit a change, Mercurial drops us into a text editor, to enter a " "message that will describe the modifications we've made in this changeset. " "This is called the <emphasis>commit message</emphasis>. It will be a record " "for readers of what we did and why, and it will be printed by <command role=" "\"hg-cmd\">hg log</command> after we've finished committing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:651 msgid "" "The editor that the <command role=\"hg-cmd\">hg commit</command> command " "drops us into will contain an empty line or two, followed by a number of " "lines starting with <quote><literal>HG:</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:665 msgid "" "Mercurial ignores the lines that start with <quote><literal>HG:</literal></" "quote>; it uses them only to tell us which files it's recording changes to. " "Modifying or deleting these lines has no effect." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:671 msgid "Writing a good commit message" msgstr "写好提交日志" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:673 msgid "" "Since <command role=\"hg-cmd\">hg log</command> only prints the first line of " "a commit message by default, it's best to write a commit message whose first " "line stands alone. Here's a real example of a commit message that " "<emphasis>doesn't</emphasis> follow this guideline, and hence has a summary " "that is not readable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:687 msgid "" "As far as the remainder of the contents of the commit message are concerned, " "there are no hard-and-fast rules. Mercurial itself doesn't interpret or care " "about the contents of the commit message, though your project may have " "policies that dictate a certain kind of formatting." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:693 msgid "" "My personal preference is for short, but informative, commit messages that " "tell me something that I can't figure out with a quick glance at the output " "of <command role=\"hg-cmd\">hg log --patch</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:700 msgid "Aborting a commit" msgstr "终止提交" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:702 msgid "" "If you decide that you don't want to commit while in the middle of editing a " "commit message, simply exit from your editor without saving the file that " "it's editing. This will cause nothing to happen to either the repository or " "the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:707 msgid "" "If we run the <command role=\"hg-cmd\">hg commit</command> command without " "any arguments, it records all of the changes we've made, as reported by " "<command role=\"hg-cmd\">hg status</command> and <command role=\"hg-cmd\">hg " "diff</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:714 msgid "Admiring our new handiwork" msgstr "欣赏我们的成果" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:716 msgid "" "Once we've finished the commit, we can use the <command role=\"hg-cmd\">hg " "tip</command> command to display the changeset we just created. This command " "produces output that is identical to <command role=\"hg-cmd\">hg log</" "command>, but it only displays the newest revision in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:725 msgid "" "We refer to the newest revision in the repository as the <emphasis>tip " "revision</emphasis>, or simply the <emphasis>tip</emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:729 msgid "" "By the way, the <command role=\"hg-cmd\">hg tip</command> command accepts " "many of the same options as <command role=\"hg-cmd\">hg log</command>, so " "<option role=\"hg-opt-global\">-v</option> above indicates <quote>be verbose</" "quote>, <option role=\"hg-opt-tip\">-p</option> specifies <quote>print a " "patch</quote>. The use of <option role=\"hg-opt-tip\">-p</option> to print " "patches is another example of the consistent naming we mentioned earlier." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch01-tour-basic.xml:741 msgid "Sharing changes" msgstr "共享修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch01-tour-basic.xml:743 msgid "" "We mentioned earlier that repositories in Mercurial are self-contained. This " "means that the changeset we just created exists only in our <filename class=" "\"directory\">my-hello</filename> repository. Let's look at a few ways that " "we can propagate this change into other repositories." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:751 msgid "Pulling changes from another repository" msgstr "从其它版本库取得修改" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:752 msgid "" "To get started, let's clone our original <filename class=\"directory\">hello</" "filename> repository, which does not contain the change we just committed. " "We'll call our temporary repository <filename class=\"directory\">hello-pull</" "filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:760 msgid "" "We'll use the <command role=\"hg-cmd\">hg pull</command> command to bring " "changes from <filename class=\"directory\">my-hello</filename> into <filename " "class=\"directory\">hello-pull</filename>. However, blindly pulling unknown " "changes into a repository is a somewhat scary prospect. Mercurial provides " "the <command role=\"hg-cmd\">hg incoming</command> command to tell us what " "changes the <command role=\"hg-cmd\">hg pull</command> command " "<emphasis>would</emphasis> pull into the repository, without actually pulling " "the changes in." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:773 msgid "" "Suppose you're pulling changes from a repository on the network somewhere. " "While you are looking at the <command role=\"hg-cmd\">hg incoming</command> " "output, and before you pull those changes, someone might have committed " "something in the remote repository. This means that it's possible to pull " "more changes than you saw when using <command role=\"hg-cmd\">hg incoming</" "command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:781 msgid "" "Bringing changes into a repository is a simple matter of running the <command " "role=\"hg-cmd\">hg pull</command> command, and telling it which repository to " "pull from." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:788 msgid "" "As you can see from the before-and-after output of <command role=\"hg-cmd" "\">hg tip</command>, we have successfully pulled changes into our " "repository. There remains one step before we can see these changes in the " "working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:796 msgid "Updating the working directory" msgstr "更新工作目录" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:798 msgid "" "We have so far glossed over the relationship between a repository and its " "working directory. The <command role=\"hg-cmd\">hg pull</command> command " "that we ran in <xref linkend=\"sec:tour:pull\"/> brought changes into the " "repository, but if we check, there's no sign of those changes in the working " "directory. This is because <command role=\"hg-cmd\">hg pull</command> does " "not (by default) touch the working directory. Instead, we use the <command " "role=\"hg-cmd\">hg update</command> command to do this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:810 msgid "" "It might seem a bit strange that <command role=\"hg-cmd\">hg pull</command> " "doesn't update the working directory automatically. There's actually a good " "reason for this: you can use <command role=\"hg-cmd\">hg update</command> to " "update the working directory to the state it was in at <emphasis>any " "revision</emphasis> in the history of the repository. If you had the working " "directory updated to an old revision&emdash;to hunt down the origin of a bug, " "say&emdash;and ran a <command role=\"hg-cmd\">hg pull</command> which " "automatically updated the working directory to a new revision, you might not " "be terribly happy." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:821 msgid "" "However, since pull-then-update is such a common thing to do, Mercurial lets " "you combine the two by passing the <option role=\"hg-opt-pull\">-u</option> " "option to <command role=\"hg-cmd\">hg pull</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:826 msgid "" "If you look back at the output of <command role=\"hg-cmd\">hg pull</command> " "in <xref linkend=\"sec:tour:pull\"/> when we ran it without <option role=\"hg-" "opt-pull\">-u</option>, you can see that it printed a helpful reminder that " "we'd have to take an explicit step to update the working directory:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:835 msgid "" "To find out what revision the working directory is at, use the <command role=" "\"hg-cmd\">hg parents</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:841 msgid "" "If you look back at <xref linkend=\"fig:tour-basic:history\"/>, you'll see " "arrows connecting each changeset. The node that the arrow leads " "<emphasis>from</emphasis> in each case is a parent, and the node that the " "arrow leads <emphasis>to</emphasis> is its child. The working directory has " "a parent in just the same way; this is the changeset that the working " "directory currently contains." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:850 msgid "" "To update the working directory to a particular revision, give a revision " "number or changeset ID to the <command role=\"hg-cmd\">hg update</command> " "command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:857 msgid "" "If you omit an explicit revision, <command role=\"hg-cmd\">hg update</" "command> will update to the tip revision, as shown by the second call to " "<command role=\"hg-cmd\">hg update</command> in the example above." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:865 msgid "Pushing changes to another repository" msgstr "发布修改到其它版本库" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:867 msgid "" "Mercurial lets us push changes to another repository, from the repository " "we're currently visiting. As with the example of <command role=\"hg-cmd\">hg " "pull</command> above, we'll create a temporary repository to push our changes " "into." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:875 msgid "" "The <command role=\"hg-cmd\">hg outgoing</command> command tells us what " "changes would be pushed into another repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:881 msgid "" "And the <command role=\"hg-cmd\">hg push</command> command does the actual " "push." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:887 msgid "" "As with <command role=\"hg-cmd\">hg pull</command>, the <command role=\"hg-cmd" "\">hg push</command> command does not update the working directory in the " "repository that it's pushing changes into. Unlike <command role=\"hg-cmd\">hg " "pull</command>, <command role=\"hg-cmd\">hg push</command> does not provide a " "<literal>-u</literal> option that updates the other repository's working " "directory. This asymmetry is deliberate: the repository we're pushing to " "might be on a remote server and shared between several people. If we were to " "update its working directory while someone was working in it, their work " "would be disrupted." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:899 msgid "" "What happens if we try to pull or push changes and the receiving repository " "already has those changes? Nothing too exciting." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch01-tour-basic.xml:906 msgid "Sharing changes over a network" msgstr "通过网络共享修改" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:908 msgid "" "The commands we have covered in the previous few sections are not limited to " "working with local repositories. Each works in exactly the same fashion over " "a network connection; simply pass in a URL instead of a local path." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch01-tour-basic.xml:916 msgid "" "In this example, we can see what changes we could push to the remote " "repository, but the repository is understandably not set up to let anonymous " "users push to it." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch02-tour-merge.xml:5 msgid "A tour of Mercurial: merging work" msgstr "Mercurial 教程: 合并工作" #. type: Content of: <book><chapter><para> #: ../en/ch02-tour-merge.xml:7 msgid "" "We've now covered cloning a repository, making changes in a repository, and " "pulling or pushing changes from one repository into another. Our next step " "is <emphasis>merging</emphasis> changes from separate repositories." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch02-tour-merge.xml:13 msgid "Merging streams of work" msgstr "合并的流程" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:15 msgid "" "Merging is a fundamental part of working with a distributed revision control " "tool." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch02-tour-merge.xml:18 msgid "" "Alice and Bob each have a personal copy of a repository for a project they're " "collaborating on. Alice fixes a bug in her repository; Bob adds a new " "feature in his. They want the shared repository to contain both the bug fix " "and the new feature." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch02-tour-merge.xml:24 msgid "" "I frequently work on several different tasks for a single project at once, " "each safely isolated in its own repository. Working this way means that I " "often need to merge one piece of my own work with another." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:30 msgid "" "Because merging is such a common thing to need to do, Mercurial makes it " "easy. Let's walk through the process. We'll begin by cloning yet another " "repository (see how often they spring up?) and making a change in it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:37 msgid "" "We should now have two copies of <filename>hello.c</filename> with different " "contents. The histories of the two repositories have also diverged, as " "illustrated in <xref linkend=\"fig:tour-merge:sep-repos\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><figure><title> #: ../en/ch02-tour-merge.xml:46 msgid "" "Divergent recent histories of the <filename class=\"directory\">my-hello</" "filename> and <filename class=\"directory\">my-new-hello</filename> " "repositories" msgstr "" "<filename class=\"directory\">my-hello</filename> 与 <filename class=" "\"directory\">my-new-hello</filename> 最新的历史分叉" #. type: Content of: <book><chapter><sect1><figure><mediaobject> #: ../en/ch02-tour-merge.xml:51 msgid "" "<imageobject><imagedata fileref=\"figs/tour-merge-sep-repos.png\"/></" "imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:56 msgid "" "We already know that pulling changes from our <filename class=\"directory" "\">my-hello</filename> repository will have no effect on the working " "directory." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:62 msgid "" "However, the <command role=\"hg-cmd\">hg pull</command> command says " "something about <quote>heads</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch02-tour-merge.xml:66 msgid "Head changesets" msgstr "顶点修改集" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:68 msgid "" "A head is a change that has no descendants, or children, as they're also " "known. The tip revision is thus a head, because the newest revision in a " "repository doesn't have any children, but a repository can contain more than " "one head." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch02-tour-merge.xml:75 msgid "" "Repository contents after pulling from <filename class=\"directory\">my-" "hello</filename> into <filename class=\"directory\">my-new-hello</filename>" msgstr "" "从 <filename class=\"directory\">my-hello</filename> 拉到 <filename class=" "\"directory\">my-new-hello</filename> 之后版本库的内容" #. type: Content of: <book><chapter><sect1><sect2><figure> #: ../en/ch02-tour-merge.xml:78 ../en/ch02-tour-merge.xml:125 #: ../en/ch02-tour-merge.xml:250 ../en/ch03-concepts.xml:55 #: ../en/ch03-concepts.xml:104 ../en/ch03-concepts.xml:189 #: ../en/ch03-concepts.xml:344 ../en/ch03-concepts.xml:359 #: ../en/ch03-concepts.xml:400 ../en/ch03-concepts.xml:420 #: ../en/ch03-concepts.xml:461 ../en/ch05-collab.xml:274 #: ../en/ch08-undo.xml:363 ../en/ch08-undo.xml:410 ../en/ch08-undo.xml:475 #: ../en/ch08-undo.xml:513 ../en/ch11-mq.xml:410 msgid " <placeholder type=\"mediaobject\" id=\"0\"/>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch02-tour-merge.xml:79 msgid "" "<imageobject> <imagedata fileref=\"figs/tour-merge-pull.png\"/> </imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:86 msgid "" "In <xref linkend=\"fig:tour-merge:pull\"/>, you can see the effect of the " "pull from <filename class=\"directory\">my-hello</filename> into <filename " "class=\"directory\">my-new-hello</filename>. The history that was already " "present in <filename class=\"directory\">my-new-hello</filename> is " "untouched, but a new revision has been added. By referring to <xref linkend=" "\"fig:tour-merge:sep-repos\"/>, we can see that the <emphasis>changeset ID</" "emphasis> remains the same in the new repository, but the <emphasis>revision " "number</emphasis> has changed. (This, incidentally, is a fine example of why " "it's not safe to use revision numbers when discussing changesets.) We can " "view the heads in a repository using the <command role=\"hg-cmd\">hg heads</" "command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch02-tour-merge.xml:105 msgid "Performing the merge" msgstr "执行合并" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:107 msgid "" "What happens if we try to use the normal <command role=\"hg-cmd\">hg update</" "command> command to update to the new tip?" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:113 msgid "" "Mercurial is telling us that the <command role=\"hg-cmd\">hg update</command> " "command won't do a merge; it won't update the working directory when it " "thinks we might be wanting to do a merge, unless we force it to do so. " "Instead, we use the <command role=\"hg-cmd\">hg merge</command> command to " "merge the two heads." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch02-tour-merge.xml:123 msgid "Working directory and repository during merge, and following commit" msgstr "在合并期间,以及提交之后的工作目录与版本库" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch02-tour-merge.xml:126 msgid "" "<imageobject> <imagedata fileref=\"figs/tour-merge-merge.png\"/> </" "imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:133 msgid "" "This updates the working directory so that it contains changes from " "<emphasis>both</emphasis> heads, which is reflected in both the output of " "<command role=\"hg-cmd\">hg parents</command> and the contents of " "<filename>hello.c</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch02-tour-merge.xml:143 msgid "Committing the results of the merge" msgstr "提交合并结果" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:145 msgid "" "Whenever we've done a merge, <command role=\"hg-cmd\">hg parents</command> " "will display two parents until we <command role=\"hg-cmd\">hg commit</" "command> the results of the merge." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:152 msgid "" "We now have a new tip revision; notice that it has <emphasis>both</emphasis> " "of our former heads as its parents. These are the same revisions that were " "previously displayed by <command role=\"hg-cmd\">hg parents</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:159 msgid "" "In <xref linkend=\"fig:tour-merge:merge\"/>, you can see a representation of " "what happens to the working directory during the merge, and how this affects " "the repository when the commit happens. During the merge, the working " "directory has two parent changesets, and these become the parents of the new " "changeset." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch02-tour-merge.xml:170 msgid "Merging conflicting changes" msgstr "合并有冲突的改变" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:172 msgid "" "Most merges are simple affairs, but sometimes you'll find yourself merging " "changes where each modifies the same portions of the same files. Unless both " "modifications are identical, this results in a <emphasis>conflict</emphasis>, " "where you have to decide how to reconcile the different changes into " "something coherent." msgstr "" #. type: Content of: <book><chapter><sect1><figure><title> #: ../en/ch02-tour-merge.xml:180 msgid "Conflicting changes to a document" msgstr "冲突的修改" #. type: Content of: <book><chapter><sect1><figure><mediaobject> #: ../en/ch02-tour-merge.xml:182 msgid "" "<imageobject><imagedata fileref=\"figs/tour-merge-conflict.png\"/></" "imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:187 msgid "" "<xref linkend=\"fig:tour-merge:conflict\"/> illustrates an instance of two " "conflicting changes to a document. We started with a single version of the " "file; then we made some changes; while someone else made different changes to " "the same text. Our task in resolving the conflicting changes is to decide " "what the file should look like." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:194 msgid "" "Mercurial doesn't have a built-in facility for handling conflicts. Instead, " "it runs an external program called <command>hgmerge</command>. This is a " "shell script that is bundled with Mercurial; you can change it to behave " "however you please. What it does by default is try to find one of several " "different merging tools that are likely to be installed on your system. It " "first tries a few fully automatic merging tools; if these don't succeed " "(because the resolution process requires human guidance) or aren't present, " "the script tries a few different graphical merging tools." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:205 msgid "" "It's also possible to get Mercurial to run another program or script instead " "of <command>hgmerge</command>, by setting the <envar>HGMERGE</envar> " "environment variable to the name of your preferred program." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch02-tour-merge.xml:211 msgid "Using a graphical merge tool" msgstr "使用图形合并工具" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:213 msgid "" "My preferred graphical merge tool is <command>kdiff3</command>, which I'll " "use to describe the features that are common to graphical file merging " "tools. You can see a screenshot of <command>kdiff3</command> in action in " "<xref linkend=\"fig:tour-merge:kdiff3\"/>. The kind of merge it is " "performing is called a <emphasis>three-way merge</emphasis>, because there " "are three different versions of the file of interest to us. The tool thus " "splits the upper portion of the window into three panes:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch02-tour-merge.xml:223 msgid "" "At the left is the <emphasis>base</emphasis> version of the file, i.e. the " "most recent version from which the two versions we're trying to merge are " "descended." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch02-tour-merge.xml:228 msgid "" "In the middle is <quote>our</quote> version of the file, with the contents " "that we modified." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch02-tour-merge.xml:231 msgid "" "On the right is <quote>their</quote> version of the file, the one that from " "the changeset that we're trying to merge with." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:235 msgid "" "In the pane below these is the current <emphasis>result</emphasis> of the " "merge. Our task is to replace all of the red text, which indicates unresolved " "conflicts, with some sensible merger of the <quote>ours</quote> and " "<quote>theirs</quote> versions of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:242 msgid "" "All four of these panes are <emphasis>locked together</emphasis>; if we " "scroll vertically or horizontally in any of them, the others are updated to " "display the corresponding sections of their respective files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch02-tour-merge.xml:248 msgid "Using <command>kdiff3</command> to merge versions of a file" msgstr "使用 <command>kdiff3</command> 合并文件的不同版本" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch02-tour-merge.xml:251 msgid "" "<imageobject> <imagedata width=\"100%\" fileref=\"figs/kdiff3.png\"/></" "imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:259 msgid "" "For each conflicting portion of the file, we can choose to resolve the " "conflict using some combination of text from the base version, ours, or " "theirs. We can also manually edit the merged file at any time, in case we " "need to make further modifications." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:265 msgid "" "There are <emphasis>many</emphasis> file merging tools available, too many to " "cover here. They vary in which platforms they are available for, and in " "their particular strengths and weaknesses. Most are tuned for merging files " "containing plain text, while a few are aimed at specialised file formats " "(generally XML)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch02-tour-merge.xml:274 msgid "A worked example" msgstr "合并实例" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:276 msgid "" "In this example, we will reproduce the file modification history of <xref " "linkend=\"fig:tour-merge:conflict\"/> above. Let's begin by creating a " "repository with a base version of our document." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:283 msgid "We'll clone the repository and make a change to the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:288 msgid "" "And another clone, to simulate someone else making a change to the file. " "(This hints at the idea that it's not all that unusual to merge with yourself " "when you isolate tasks in separate repositories, and indeed to find and " "resolve conflicts while doing so.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:296 msgid "" "Having created two different versions of the file, we'll set up an " "environment suitable for running our merge." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:302 msgid "" "In this example, I won't use Mercurial's normal <command>hgmerge</command> " "program to do the merge, because it would drop my nice automated example-" "running tool into a graphical user interface. Instead, I'll set " "<envar>HGMERGE</envar> to tell Mercurial to use the non-interactive " "<command>merge</command> command. This is bundled with many Unix-like " "systems. If you're following this example on your computer, don't bother " "setting <envar>HGMERGE</envar>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:312 msgid "<emphasis role=\"bold\">XXX FIX THIS EXAMPLE.</emphasis>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:317 msgid "" "Because <command>merge</command> can't resolve the conflicting changes, it " "leaves <emphasis>merge markers</emphasis> inside the file that has conflicts, " "indicating which lines have conflicts, and whether they came from our version " "of the file or theirs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:323 msgid "" "Mercurial can tell from the way <command>merge</command> exits that it wasn't " "able to merge successfully, so it tells us what commands we'll need to run if " "we want to redo the merging operation. This could be useful if, for example, " "we were running a graphical merge tool and quit because we were confused or " "realised we had made a mistake." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch02-tour-merge.xml:330 msgid "" "If automatic or manual merges fail, there's nothing to prevent us from " "<quote>fixing up</quote> the affected files ourselves, and committing the " "results of our merge:" msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch02-tour-merge.xml:339 msgid "Simplifying the pull-merge-commit sequence" msgstr "简化拉-合并-提交程序" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:341 msgid "" "The process of merging changes as outlined above is straightforward, but " "requires running three commands in sequence." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:347 msgid "" "In the case of the final commit, you also need to enter a commit message, " "which is almost always going to be a piece of uninteresting " "<quote>boilerplate</quote> text." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:351 msgid "" "It would be nice to reduce the number of steps needed, if this were " "possible. Indeed, Mercurial is distributed with an extension called <literal " "role=\"hg-ext\">fetch</literal> that does just this." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:356 msgid "" "Mercurial provides a flexible extension mechanism that lets people extend its " "functionality, while keeping the core of Mercurial small and easy to deal " "with. Some extensions add new commands that you can use from the command " "line, while others work <quote>behind the scenes,</quote> for example adding " "capabilities to the server." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:363 msgid "" "The <literal role=\"hg-ext\">fetch</literal> extension adds a new command " "called, not surprisingly, <command role=\"hg-cmd\">hg fetch</command>. This " "extension acts as a combination of <command role=\"hg-cmd\">hg pull</" "command>, <command role=\"hg-cmd\">hg update</command> and <command role=\"hg-" "cmd\">hg merge</command>. It begins by pulling changes from another " "repository into the current repository. If it finds that the changes added a " "new head to the repository, it begins a merge, then commits the result of the " "merge with an automatically-generated commit message. If no new heads were " "added, it updates the working directory to the new tip changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:376 msgid "" "Enabling the <literal role=\"hg-ext\">fetch</literal> extension is easy. " "Edit your <filename role=\"special\">.hgrc</filename>, and either go to the " "<literal role=\"rc-extensions\">extensions</literal> section or create an " "<literal role=\"rc-extensions\">extensions</literal> section. Then add a line " "that simply reads <quote><literal>fetch </literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch02-tour-merge.xml:385 msgid "" "(Normally, on the right-hand side of the <quote><literal>=</literal></quote> " "would appear the location of the extension, but since the <literal role=\"hg-" "ext\">fetch</literal> extension is in the standard distribution, Mercurial " "knows where to search for it.)" msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch03-concepts.xml:5 msgid "Behind the scenes" msgstr "Mercurial 内幕" #. type: Content of: <book><chapter><para> #: ../en/ch03-concepts.xml:7 msgid "" "Unlike many revision control systems, the concepts upon which Mercurial is " "built are simple enough that it's easy to understand how the software really " "works. Knowing this certainly isn't necessary, but I find it useful to have " "a <quote>mental model</quote> of what's going on." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch03-concepts.xml:13 msgid "" "This understanding gives me confidence that Mercurial has been carefully " "designed to be both <emphasis>safe</emphasis> and <emphasis>efficient</" "emphasis>. And just as importantly, if it's easy for me to retain a good " "idea of what the software is doing when I perform a revision control task, " "I'm less likely to be surprised by its behaviour." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch03-concepts.xml:20 msgid "" "In this chapter, we'll initially cover the core concepts behind Mercurial's " "design, then continue to discuss some of the interesting details of its " "implementation." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch03-concepts.xml:25 msgid "Mercurial's historical record" msgstr "Mercurial 的历史记录" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:28 msgid "Tracking the history of a single file" msgstr "跟踪单一文件的历史" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:30 msgid "" "When Mercurial tracks modifications to a file, it stores the history of that " "file in a metadata object called a <emphasis>filelog</emphasis>. Each entry " "in the filelog contains enough information to reconstruct one revision of the " "file that is being tracked. Filelogs are stored as files in the <filename " "role=\"special\" class=\"directory\">.hg/store/data</filename> directory. A " "filelog contains two kinds of information: revision data, and an index to " "help Mercurial to find a revision efficiently." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:41 msgid "" "A file that is large, or has a lot of history, has its filelog stored in " "separate data (<quote><literal>.d</literal></quote> suffix) and index " "(<quote><literal>.i</literal></quote> suffix) files. For small files without " "much history, the revision data and index are combined in a single " "<quote><literal>.i</literal></quote> file. The correspondence between a file " "in the working directory and the filelog that tracks its history in the " "repository is illustrated in <xref linkend=\"fig:concepts:filelog\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:53 msgid "" "Relationships between files in working directory and filelogs in repository" msgstr "工作目录中的文件与版本库中的文件日志之间的关系" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:56 msgid "<imageobject><imagedata fileref=\"figs/filelog.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:63 msgid "Managing tracked files" msgstr "管理跟踪的文件" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:65 msgid "" "Mercurial uses a structure called a <emphasis>manifest</emphasis> to collect " "together information about the files that it tracks. Each entry in the " "manifest contains information about the files present in a single changeset. " "An entry records which files are present in the changeset, the revision of " "each file, and a few other pieces of file metadata." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:75 msgid "Recording changeset information" msgstr "记录修改集信息" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:77 msgid "" "The <emphasis>changelog</emphasis> contains information about each " "changeset. Each revision records who committed a change, the changeset " "comment, other pieces of changeset-related information, and the revision of " "the manifest to use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:85 msgid "Relationships between revisions" msgstr "版本之间的关系" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:87 msgid "" "Within a changelog, a manifest, or a filelog, each revision stores a pointer " "to its immediate parent (or to its two parents, if it's a merge revision). " "As I mentioned above, there are also relationships between revisions " "<emphasis>across</emphasis> these structures, and they are hierarchical in " "nature." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:94 msgid "" "For every changeset in a repository, there is exactly one revision stored in " "the changelog. Each revision of the changelog contains a pointer to a single " "revision of the manifest. A revision of the manifest stores a pointer to a " "single revision of each filelog tracked when that changeset was created. " "These relationships are illustrated in <xref linkend=\"fig:concepts:metadata" "\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:103 msgid "Metadata relationships" msgstr "元数据之间的关系" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:105 msgid "<imageobject><imagedata fileref=\"figs/metadata.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:110 msgid "" "As the illustration shows, there is <emphasis>not</emphasis> a <quote>one to " "one</quote> relationship between revisions in the changelog, manifest, or " "filelog. If the manifest hasn't changed between two changesets, the changelog " "entries for those changesets will point to the same revision of the " "manifest. If a file that Mercurial tracks hasn't changed between two " "changesets, the entry for that file in the two revisions of the manifest will " "point to the same revision of its filelog." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch03-concepts.xml:123 msgid "Safe, efficient storage" msgstr "安全,高效的存储" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:125 msgid "" "The underpinnings of changelogs, manifests, and filelogs are provided by a " "single structure called the <emphasis>revlog</emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:130 msgid "Efficient storage" msgstr "高效存储" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:132 msgid "" "The revlog provides efficient storage of revisions using a <emphasis>delta</" "emphasis> mechanism. Instead of storing a complete copy of a file for each " "revision, it stores the changes needed to transform an older revision into " "the new revision. For many kinds of file data, these deltas are typically a " "fraction of a percent of the size of a full copy of a file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:140 msgid "" "Some obsolete revision control systems can only work with deltas of text " "files. They must either store binary files as complete snapshots or encoded " "into a text representation, both of which are wasteful approaches. Mercurial " "can efficiently handle deltas of files with arbitrary binary contents; it " "doesn't need to treat text as special." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:149 msgid "Safe operation" msgstr "安全操作" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:151 msgid "" "Mercurial only ever <emphasis>appends</emphasis> data to the end of a revlog " "file. It never modifies a section of a file after it has written it. This is " "both more robust and efficient than schemes that need to modify or rewrite " "data." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:157 msgid "" "In addition, Mercurial treats every write as part of a <emphasis>transaction</" "emphasis> that can span a number of files. A transaction is " "<emphasis>atomic</emphasis>: either the entire transaction succeeds and its " "effects are all visible to readers in one go, or the whole thing is undone. " "This guarantee of atomicity means that if you're running two copies of " "Mercurial, where one is reading data and one is writing it, the reader will " "never see a partially written result that might confuse it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:167 msgid "" "The fact that Mercurial only appends to files makes it easier to provide this " "transactional guarantee. The easier it is to do stuff like this, the more " "confident you should be that it's done correctly." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:174 msgid "Fast retrieval" msgstr "快速检索" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:176 msgid "" "Mercurial cleverly avoids a pitfall common to all earlier revision control " "systems: the problem of <emphasis>inefficient retrieval</emphasis>. Most " "revision control systems store the contents of a revision as an incremental " "series of modifications against a <quote>snapshot</quote>. To reconstruct a " "specific revision, you must first read the snapshot, and then every one of " "the revisions between the snapshot and your target revision. The more " "history that a file accumulates, the more revisions you must read, hence the " "longer it takes to reconstruct a particular revision." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:188 msgid "Snapshot of a revlog, with incremental deltas" msgstr "版本日志的快照,以及增量差异" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:190 msgid "<imageobject><imagedata fileref=\"figs/snapshot.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:195 msgid "" "The innovation that Mercurial applies to this problem is simple but " "effective. Once the cumulative amount of delta information stored since the " "last snapshot exceeds a fixed threshold, it stores a new snapshot " "(compressed, of course), instead of another delta. This makes it possible to " "reconstruct <emphasis>any</emphasis> revision of a file quickly. This " "approach works so well that it has since been copied by several other " "revision control systems." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:204 msgid "" "<xref linkend=\"fig:concepts:snapshot\"/> illustrates the idea. In an entry " "in a revlog's index file, Mercurial stores the range of entries from the data " "file that it must read to reconstruct a particular revision." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch03-concepts.xml:210 msgid "Aside: the influence of video compression" msgstr "旁白: 视频压缩的影响" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:212 msgid "" "If you're familiar with video compression or have ever watched a TV feed " "through a digital cable or satellite service, you may know that most video " "compression schemes store each frame of video as a delta against its " "predecessor frame. In addition, these schemes use <quote>lossy</quote> " "compression techniques to increase the compression ratio, so visual errors " "accumulate over the course of a number of inter-frame deltas." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:221 msgid "" "Because it's possible for a video stream to <quote>drop out</quote> " "occasionally due to signal glitches, and to limit the accumulation of " "artefacts introduced by the lossy compression process, video encoders " "periodically insert a complete frame (called a <quote>key frame</quote>) into " "the video stream; the next delta is generated against that frame. This means " "that if the video signal gets interrupted, it will resume once the next key " "frame is received. Also, the accumulation of encoding errors restarts anew " "with each key frame." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:235 msgid "Identification and strong integrity" msgstr "鉴别和强完整性" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:237 msgid "" "Along with delta or snapshot information, a revlog entry contains a " "cryptographic hash of the data that it represents. This makes it difficult " "to forge the contents of a revision, and easy to detect accidental corruption." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:242 msgid "" "Hashes provide more than a mere check against corruption; they are used as " "the identifiers for revisions. The changeset identification hashes that you " "see as an end user are from revisions of the changelog. Although filelogs " "and the manifest also use hashes, Mercurial only uses these behind the scenes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:249 msgid "" "Mercurial verifies that hashes are correct when it retrieves file revisions " "and when it pulls changes from another repository. If it encounters an " "integrity problem, it will complain and stop whatever it's doing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:254 msgid "" "In addition to the effect it has on retrieval efficiency, Mercurial's use of " "periodic snapshots makes it more robust against partial data corruption. If " "a revlog becomes partly corrupted due to a hardware error or system bug, it's " "often possible to reconstruct some or most revisions from the uncorrupted " "sections of the revlog, both before and after the corrupted section. This " "would not be possible with a delta-only storage model." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch03-concepts.xml:266 msgid "Revision history, branching, and merging" msgstr "修订历史,分支与合并" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:268 msgid "" "Every entry in a Mercurial revlog knows the identity of its immediate " "ancestor revision, usually referred to as its <emphasis>parent</emphasis>. " "In fact, a revision contains room for not one parent, but two. Mercurial " "uses a special hash, called the <quote>null ID</quote>, to represent the idea " "<quote>there is no parent here</quote>. This hash is simply a string of " "zeroes." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:276 msgid "" "In <xref linkend=\"fig:concepts:revlog\"/>, you can see an example of the " "conceptual structure of a revlog. Filelogs, manifests, and changelogs all " "have this same structure; they differ only in the kind of data stored in each " "delta or snapshot." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:282 msgid "" "The first revision in a revlog (at the bottom of the image) has the null ID " "in both of its parent slots. For a <quote>normal</quote> revision, its first " "parent slot contains the ID of its parent revision, and its second contains " "the null ID, indicating that the revision has only one real parent. Any two " "revisions that have the same parent ID are branches. A revision that " "represents a merge between branches has two normal revision IDs in its parent " "slots." msgstr "" #. type: Content of: <book><chapter><sect1><figure><title> #: ../en/ch03-concepts.xml:292 msgid "The conceptual structure of a revlog" msgstr "版本日志的设计结构" #. type: Content of: <book><chapter><sect1><figure><mediaobject> #: ../en/ch03-concepts.xml:294 msgid "<imageobject><imagedata fileref=\"figs/revlog.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch03-concepts.xml:301 msgid "The working directory" msgstr "工作目录" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:303 msgid "" "In the working directory, Mercurial stores a snapshot of the files from the " "repository as of a particular changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:306 msgid "" "The working directory <quote>knows</quote> which changeset it contains. When " "you update the working directory to contain a particular changeset, Mercurial " "looks up the appropriate revision of the manifest to find out which files it " "was tracking at the time that changeset was committed, and which revision of " "each file was then current. It then recreates a copy of each of those files, " "with the same contents it had when the changeset was committed." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:315 msgid "" "The <emphasis>dirstate</emphasis> contains Mercurial's knowledge of the " "working directory. This details which changeset the working directory is " "updated to, and all of the files that Mercurial is tracking in the working " "directory." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:321 msgid "" "Just as a revision of a revlog has room for two parents, so that it can " "represent either a normal revision (with one parent) or a merge of two " "earlier revisions, the dirstate has slots for two parents. When you use the " "<command role=\"hg-cmd\">hg update</command> command, the changeset that you " "update to is stored in the <quote>first parent</quote> slot, and the null ID " "in the second. When you <command role=\"hg-cmd\">hg merge</command> with " "another changeset, the first parent remains unchanged, and the second parent " "is filled in with the changeset you're merging with. The <command role=\"hg-" "cmd\">hg parents</command> command tells you what the parents of the dirstate " "are." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:335 msgid "What happens when you commit" msgstr "当你提交时发生的事情" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:337 msgid "" "The dirstate stores parent information for more than just book-keeping " "purposes. Mercurial uses the parents of the dirstate as <emphasis>the " "parents of a new changeset</emphasis> when you perform a commit." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:343 msgid "The working directory can have two parents" msgstr "工作目录可以有两个父亲" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:345 msgid "<imageobject><imagedata fileref=\"figs/wdir.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:350 msgid "" "<xref linkend=\"fig:concepts:wdir\"/> shows the normal state of the working " "directory, where it has a single changeset as parent. That changeset is the " "<emphasis>tip</emphasis>, the newest changeset in the repository that has no " "children." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:357 msgid "The working directory gains new parents after a commit" msgstr "提交之后,工作目录的父亲就改变了" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:360 msgid "" "<imageobject><imagedata fileref=\"figs/wdir-after-commit.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:365 msgid "" "It's useful to think of the working directory as <quote>the changeset I'm " "about to commit</quote>. Any files that you tell Mercurial that you've " "added, removed, renamed, or copied will be reflected in that changeset, as " "will modifications to any files that Mercurial is already tracking; the new " "changeset will have the parents of the working directory as its parents." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:373 msgid "" "After a commit, Mercurial will update the parents of the working directory, " "so that the first parent is the ID of the new changeset, and the second is " "the null ID. This is shown in <xref linkend=\"fig:concepts:wdir-after-commit" "\"/>. Mercurial doesn't touch any of the files in the working directory when " "you commit; it just modifies the dirstate to note its new parents." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:384 msgid "Creating a new head" msgstr "创建新顶点" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:386 msgid "" "It's perfectly normal to update the working directory to a changeset other " "than the current tip. For example, you might want to know what your project " "looked like last Tuesday, or you could be looking through changesets to see " "which one introduced a bug. In cases like this, the natural thing to do is " "update the working directory to the changeset you're interested in, and then " "examine the files in the working directory directly to see their contents as " "they were when you committed that changeset. The effect of this is shown in " "<xref linkend=\"fig:concepts:wdir-pre-branch\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:398 msgid "The working directory, updated to an older changeset" msgstr "同步到旧修改集的工作目录" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:401 msgid "" "<imageobject><imagedata fileref=\"figs/wdir-pre-branch.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:406 msgid "" "Having updated the working directory to an older changeset, what happens if " "you make some changes, and then commit? Mercurial behaves in the same way as " "I outlined above. The parents of the working directory become the parents of " "the new changeset. This new changeset has no children, so it becomes the new " "tip. And the repository now contains two changesets that have no children; " "we call these <emphasis>heads</emphasis>. You can see the structure that " "this creates in <xref linkend=\"fig:concepts:wdir-branch\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:418 msgid "After a commit made while synced to an older changeset" msgstr "对同步到旧修改集的工作目录提交之后" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:421 msgid "<imageobject><imagedata fileref=\"figs/wdir-branch.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch03-concepts.xml:427 msgid "" "If you're new to Mercurial, you should keep in mind a common <quote>error</" "quote>, which is to use the <command role=\"hg-cmd\">hg pull</command> " "command without any options. By default, the <command role=\"hg-cmd\">hg " "pull</command> command <emphasis>does not</emphasis> update the working " "directory, so you'll bring new changesets into your repository, but the " "working directory will stay synced at the same changeset as before the pull. " "If you make some changes and commit afterwards, you'll thus create a new " "head, because your working directory isn't synced to whatever the current tip " "is." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch03-concepts.xml:439 msgid "" "I put the word <quote>error</quote> in quotes because all that you need to do " "to rectify this situation is <command role=\"hg-cmd\">hg merge</command>, " "then <command role=\"hg-cmd\">hg commit</command>. In other words, this " "almost never has negative consequences; it just surprises people. I'll " "discuss other ways to avoid this behaviour, and why Mercurial behaves in this " "initially surprising way, later on." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:451 msgid "Merging heads" msgstr "合并顶点" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:453 msgid "" "When you run the <command role=\"hg-cmd\">hg merge</command> command, " "Mercurial leaves the first parent of the working directory unchanged, and " "sets the second parent to the changeset you're merging with, as shown in " "<xref linkend=\"fig:concepts:wdir-merge\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch03-concepts.xml:460 msgid "Merging two heads" msgstr "合并两个顶点" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch03-concepts.xml:462 msgid "" "<imageobject> <imagedata fileref=\"figs/wdir-merge.png\"/> </imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:469 msgid "" "Mercurial also has to modify the working directory, to merge the files " "managed in the two changesets. Simplified a little, the merging process goes " "like this, for every file in the manifests of both changesets." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:474 msgid "If neither changeset has modified a file, do nothing with that file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:477 msgid "" "If one changeset has modified a file, and the other hasn't, create the " "modified copy of the file in the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:481 msgid "" "If one changeset has removed a file, and the other hasn't (or has also " "deleted it), delete the file from the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:485 msgid "" "If one changeset has removed a file, but the other has modified the file, ask " "the user what to do: keep the modified file, or remove it?" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:489 msgid "" "If both changesets have modified a file, invoke an external merge program to " "choose the new contents for the merged file. This may require input from the " "user." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch03-concepts.xml:494 msgid "" "If one changeset has modified a file, and the other has renamed or copied the " "file, make sure that the changes follow the new name of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:498 msgid "" "There are more details&emdash;merging has plenty of corner cases&emdash;but " "these are the most common choices that are involved in a merge. As you can " "see, most cases are completely automatic, and indeed most merges finish " "automatically, without requiring your input to resolve any conflicts." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:505 msgid "" "When you're thinking about what happens when you commit after a merge, once " "again the working directory is <quote>the changeset I'm about to commit</" "quote>. After the <command role=\"hg-cmd\">hg merge</command> command " "completes, the working directory has two parents; these will become the " "parents of the new changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:512 msgid "" "Mercurial lets you perform multiple merges, but you must commit the results " "of each individual merge as you go. This is necessary because Mercurial only " "tracks two parents for both revisions and the working directory. While it " "would be technically possible to merge multiple changesets at once, the " "prospect of user confusion and making a terrible mess of a merge immediately " "becomes overwhelming." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch03-concepts.xml:523 msgid "Other interesting design features" msgstr "其它有趣的设计特性" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch03-concepts.xml:525 msgid "" "In the sections above, I've tried to highlight some of the most important " "aspects of Mercurial's design, to illustrate that it pays careful attention " "to reliability and performance. However, the attention to detail doesn't " "stop there. There are a number of other aspects of Mercurial's construction " "that I personally find interesting. I'll detail a few of them here, separate " "from the <quote>big ticket</quote> items above, so that if you're interested, " "you can gain a better idea of the amount of thinking that goes into a well-" "designed system." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:536 msgid "Clever compression" msgstr "智能压缩" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:538 msgid "" "When appropriate, Mercurial will store both snapshots and deltas in " "compressed form. It does this by always <emphasis>trying to</emphasis> " "compress a snapshot or delta, but only storing the compressed version if it's " "smaller than the uncompressed version." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:544 msgid "" "This means that Mercurial does <quote>the right thing</quote> when storing a " "file whose native form is compressed, such as a <literal>zip</literal> " "archive or a JPEG image. When these types of files are compressed a second " "time, the resulting file is usually bigger than the once-compressed form, and " "so Mercurial will store the plain <literal>zip</literal> or JPEG." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:552 msgid "" "Deltas between revisions of a compressed file are usually larger than " "snapshots of the file, and Mercurial again does <quote>the right thing</" "quote> in these cases. It finds that such a delta exceeds the threshold at " "which it should store a complete snapshot of the file, so it stores the " "snapshot, again saving space compared to a naive delta-only approach." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch03-concepts.xml:561 msgid "Network recompression" msgstr "网络重新压缩" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:563 msgid "" "When storing revisions on disk, Mercurial uses the <quote>deflate</quote> " "compression algorithm (the same one used by the popular <literal>zip</" "literal> archive format), which balances good speed with a respectable " "compression ratio. However, when transmitting revision data over a network " "connection, Mercurial uncompresses the compressed revision data." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:571 msgid "" "If the connection is over HTTP, Mercurial recompresses the entire stream of " "data using a compression algorithm that gives a better compression ratio (the " "Burrows-Wheeler algorithm from the widely used <literal>bzip2</literal> " "compression package). This combination of algorithm and compression of the " "entire stream (instead of a revision at a time) substantially reduces the " "number of bytes to be transferred, yielding better network performance over " "almost all kinds of network." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:581 msgid "" "(If the connection is over <command>ssh</command>, Mercurial " "<emphasis>doesn't</emphasis> recompress the stream, because <command>ssh</" "command> can already do this itself.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:589 msgid "Read/write ordering and atomicity" msgstr "读写顺序与原子性" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:591 msgid "" "Appending to files isn't the whole story when it comes to guaranteeing that a " "reader won't see a partial write. If you recall <xref linkend=\"fig:concepts:" "metadata\"/>, revisions in the changelog point to revisions in the manifest, " "and revisions in the manifest point to revisions in filelogs. This hierarchy " "is deliberate." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:599 msgid "" "A writer starts a transaction by writing filelog and manifest data, and " "doesn't write any changelog data until those are finished. A reader starts " "by reading changelog data, then manifest data, followed by filelog data." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:604 msgid "" "Since the writer has always finished writing filelog and manifest data before " "it writes to the changelog, a reader will never read a pointer to a partially " "written manifest revision from the changelog, and it will never read a " "pointer to a partially written filelog revision from the manifest." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:612 msgid "Concurrent access" msgstr "并发访问" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:614 msgid "" "The read/write ordering and atomicity guarantees mean that Mercurial never " "needs to <emphasis>lock</emphasis> a repository when it's reading data, even " "if the repository is being written to while the read is occurring. This has a " "big effect on scalability; you can have an arbitrary number of Mercurial " "processes safely reading data from a repository safely all at once, no matter " "whether it's being written to or not." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:623 msgid "" "The lockless nature of reading means that if you're sharing a repository on a " "multi-user system, you don't need to grant other local users permission to " "<emphasis>write</emphasis> to your repository in order for them to be able to " "clone it or pull changes from it; they only need <emphasis>read</emphasis> " "permission. (This is <emphasis>not</emphasis> a common feature among " "revision control systems, so don't take it for granted! Most require readers " "to be able to lock a repository to access it safely, and this requires write " "permission on at least one directory, which of course makes for all kinds of " "nasty and annoying security and administrative problems.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:636 msgid "" "Mercurial uses locks to ensure that only one process can write to a " "repository at a time (the locking mechanism is safe even over filesystems " "that are notoriously hostile to locking, such as NFS). If a repository is " "locked, a writer will wait for a while to retry if the repository becomes " "unlocked, but if the repository remains locked for too long, the process " "attempting to write will time out after a while. This means that your daily " "automated scripts won't get stuck forever and pile up if a system crashes " "unnoticed, for example. (Yes, the timeout is configurable, from zero to " "infinity.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch03-concepts.xml:648 msgid "Safe dirstate access" msgstr "安全的目录状态访问" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch03-concepts.xml:650 msgid "" "As with revision data, Mercurial doesn't take a lock to read the dirstate " "file; it does acquire a lock to write it. To avoid the possibility of " "reading a partially written copy of the dirstate file, Mercurial writes to a " "file with a unique name in the same directory as the dirstate file, then " "renames the temporary file atomically to <filename>dirstate</filename>. The " "file named <filename>dirstate</filename> is thus guaranteed to be complete, " "not partially written." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:663 msgid "Avoiding seeks" msgstr "避免查找" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:665 msgid "" "Critical to Mercurial's performance is the avoidance of seeks of the disk " "head, since any seek is far more expensive than even a comparatively large " "read operation." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:669 msgid "" "This is why, for example, the dirstate is stored in a single file. If there " "were a dirstate file per directory that Mercurial tracked, the disk would " "seek once per directory. Instead, Mercurial reads the entire single dirstate " "file in one step." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:675 msgid "" "Mercurial also uses a <quote>copy on write</quote> scheme when cloning a " "repository on local storage. Instead of copying every revlog file from the " "old repository into the new repository, it makes a <quote>hard link</quote>, " "which is a shorthand way to say <quote>these two names point to the same " "file</quote>. When Mercurial is about to write to one of a revlog's files, " "it checks to see if the number of names pointing at the file is greater than " "one. If it is, more than one repository is using the file, so Mercurial " "makes a new copy of the file that is private to this repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:686 msgid "" "A few revision control developers have pointed out that this idea of making a " "complete private copy of a file is not very efficient in its use of storage. " "While this is true, storage is cheap, and this method gives the highest " "performance while deferring most book-keeping to the operating system. An " "alternative scheme would most likely reduce performance and increase the " "complexity of the software, each of which is much more important to the " "<quote>feel</quote> of day-to-day use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch03-concepts.xml:698 msgid "Other contents of the dirstate" msgstr "目录状态的其它内容" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:700 msgid "" "Because Mercurial doesn't force you to tell it when you're modifying a file, " "it uses the dirstate to store some extra information so it can determine " "efficiently whether you have modified a file. For each file in the working " "directory, it stores the time that it last modified the file itself, and the " "size of the file at that time." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:707 msgid "" "When you explicitly <command role=\"hg-cmd\">hg add</command>, <command role=" "\"hg-cmd\">hg remove</command>, <command role=\"hg-cmd\">hg rename</command> " "or <command role=\"hg-cmd\">hg copy</command> files, Mercurial updates the " "dirstate so that it knows what to do with those files when you commit." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch03-concepts.xml:714 msgid "" "When Mercurial is checking the states of files in the working directory, it " "first checks a file's modification time. If that has not changed, the file " "must not have been modified. If the file's size has changed, the file must " "have been modified. If the modification time has changed, but the size has " "not, only then does Mercurial need to read the actual contents of the file to " "see if they've changed. Storing these few extra pieces of information " "dramatically reduces the amount of data that Mercurial needs to read, which " "yields large performance improvements compared to other revision control " "systems." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch04-daily.xml:5 msgid "Mercurial in daily use" msgstr "Mercurial 的日常使用" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch04-daily.xml:8 msgid "Telling Mercurial which files to track" msgstr "告诉 Mercurial 要跟踪哪些文件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:10 msgid "" "Mercurial does not work with files in your repository unless you tell it to " "manage them. The <command role=\"hg-cmd\">hg status</command> command will " "tell you which files Mercurial doesn't know about; it uses a <quote><literal>?" "</literal></quote> to display such files." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:17 msgid "" "To tell Mercurial to track a file, use the <command role=\"hg-cmd\">hg add</" "command> command. Once you have added a file, the entry in the output of " "<command role=\"hg-cmd\">hg status</command> for that file changes from " "<quote><literal>?</literal></quote> to <quote><literal>A</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:26 msgid "" "After you run a <command role=\"hg-cmd\">hg commit</command>, the files that " "you added before the commit will no longer be listed in the output of " "<command role=\"hg-cmd\">hg status</command>. The reason for this is that " "<command role=\"hg-cmd\">hg status</command> only tells you about " "<quote>interesting</quote> files&emdash;those that you have modified or told " "Mercurial to do something with&emdash;by default. If you have a repository " "that contains thousands of files, you will rarely want to know about files " "that Mercurial is tracking, but that have not changed. (You can still get " "this information; we'll return to this later.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:38 msgid "" "Once you add a file, Mercurial doesn't do anything with it immediately. " "Instead, it will take a snapshot of the file's state the next time you " "perform a commit. It will then continue to track the changes you make to the " "file every time you commit, until you remove the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:45 msgid "Explicit versus implicit file naming" msgstr "明确与隐含文件命名" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:47 msgid "" "A useful behaviour that Mercurial has is that if you pass the name of a " "directory to a command, every Mercurial command will treat this as <quote>I " "want to operate on every file in this directory and its subdirectories</" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:54 msgid "" "Notice in this example that Mercurial printed the names of the files it " "added, whereas it didn't do so when we added the file named <filename>a</" "filename> in the earlier example." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:59 msgid "" "What's going on is that in the former case, we explicitly named the file to " "add on the command line, so the assumption that Mercurial makes in such cases " "is that you know what you were doing, and it doesn't print any output." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:64 msgid "" "However, when we <emphasis>imply</emphasis> the names of files by giving the " "name of a directory, Mercurial takes the extra step of printing the name of " "each file that it does something with. This makes it more clear what is " "happening, and reduces the likelihood of a silent and nasty surprise. This " "behaviour is common to most Mercurial commands." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:73 msgid "Aside: Mercurial tracks files, not directories" msgstr "旁白: Mercurial 只跟踪文件,不跟踪目录" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:75 msgid "" "Mercurial does not track directory information. Instead, it tracks the path " "to a file. Before creating a file, it first creates any missing directory " "components of the path. After it deletes a file, it then deletes any empty " "directories that were in the deleted file's path. This sounds like a trivial " "distinction, but it has one minor practical consequence: it is not possible " "to represent a completely empty directory in Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:84 msgid "" "Empty directories are rarely useful, and there are unintrusive workarounds " "that you can use to achieve an appropriate effect. The developers of " "Mercurial thus felt that the complexity that would be required to manage " "empty directories was not worth the limited benefit this feature would bring." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:91 msgid "" "If you need an empty directory in your repository, there are a few ways to " "achieve this. One is to create a directory, then <command role=\"hg-cmd\">hg " "add</command> a <quote>hidden</quote> file to that directory. On Unix-like " "systems, any file name that begins with a period (<quote><literal>.</" "literal></quote>) is treated as hidden by most commands and GUI tools. This " "approach is illustrated below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:102 msgid "" "Another way to tackle a need for an empty directory is to simply create one " "in your automated build scripts before they will need it." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch04-daily.xml:109 msgid "How to stop tracking a file" msgstr "如何停止跟踪文件" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:111 msgid "" "Once you decide that a file no longer belongs in your repository, use the " "<command role=\"hg-cmd\">hg remove</command> command; this deletes the file, " "and tells Mercurial to stop tracking it. A removed file is represented in " "the output of <command role=\"hg-cmd\">hg status</command> with a " "<quote><literal>R</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:120 msgid "" "After you <command role=\"hg-cmd\">hg remove</command> a file, Mercurial will " "no longer track changes to that file, even if you recreate a file with the " "same name in your working directory. If you do recreate a file with the same " "name and want Mercurial to track the new file, simply <command role=\"hg-cmd" "\">hg add</command> it. Mercurial will know that the newly added file is not " "related to the old file of the same name." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:129 msgid "Removing a file does not affect its history" msgstr "删除文件不影响历史" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:131 msgid "It is important to understand that removing a file has only two effects." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch04-daily.xml:134 msgid "It removes the current version of the file from the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch04-daily.xml:137 msgid "" "It stops Mercurial from tracking changes to the file, from the time of the " "next commit." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:140 msgid "" "Removing a file <emphasis>does not</emphasis> in any way alter the " "<emphasis>history</emphasis> of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:143 msgid "" "If you update the working directory to a changeset in which a file that you " "have removed was still tracked, it will reappear in the working directory, " "with the contents it had when you committed that changeset. If you then " "update the working directory to a later changeset, in which the file had been " "removed, Mercurial will once again remove the file from the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:153 msgid "Missing files" msgstr "丢失的文件" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:155 msgid "" "Mercurial considers a file that you have deleted, but not used <command role=" "\"hg-cmd\">hg remove</command> to delete, to be <emphasis>missing</" "emphasis>. A missing file is represented with <quote><literal>!</literal></" "quote> in the output of <command role=\"hg-cmd\">hg status</command>. " "Mercurial commands will not generally do anything with missing files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:165 msgid "" "If your repository contains a file that <command role=\"hg-cmd\">hg status</" "command> reports as missing, and you want the file to stay gone, you can run " "<command role=\"hg-cmd\">hg remove <option role=\"hg-opt-remove\">--after</" "option></command> at any time later on, to tell Mercurial that you really did " "mean to remove the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:175 msgid "" "On the other hand, if you deleted the missing file by accident, give <command " "role=\"hg-cmd\">hg revert</command> the name of the file to recover. It will " "reappear, in unmodified form." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:184 msgid "Aside: why tell Mercurial explicitly to remove a file?" msgstr "旁白: 为什么要明确告诉 Mercurial 删除文件?" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:187 msgid "" "You might wonder why Mercurial requires you to explicitly tell it that you " "are deleting a file. Early during the development of Mercurial, it let you " "delete a file however you pleased; Mercurial would notice the absence of the " "file automatically when you next ran a <command role=\"hg-cmd\">hg commit</" "command>, and stop tracking the file. In practice, this made it too easy to " "accidentally remove a file without noticing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:198 msgid "Useful shorthand&emdash;adding and removing files in one step" msgstr "有用的速记—一个步骤添加和删除文件" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:201 msgid "" "Mercurial offers a combination command, <command role=\"hg-cmd\">hg " "addremove</command>, that adds untracked files and marks missing files as " "removed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:207 msgid "" "The <command role=\"hg-cmd\">hg commit</command> command also provides a " "<option role=\"hg-opt-commit\">-A</option> option that performs this same add-" "and-remove, immediately followed by a commit." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch04-daily.xml:217 msgid "Copying files" msgstr "复制文件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:219 msgid "" "Mercurial provides a <command role=\"hg-cmd\">hg copy</command> command that " "lets you make a new copy of a file. When you copy a file using this command, " "Mercurial makes a record of the fact that the new file is a copy of the " "original file. It treats these copied files specially when you merge your " "work with someone else's." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:227 msgid "The results of copying during a merge" msgstr "合并期间的复制结果" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:229 msgid "" "What happens during a merge is that changes <quote>follow</quote> a copy. To " "best illustrate what this means, let's create an example. We'll start with " "the usual tiny repository that contains a single file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:236 msgid "" "We need to do some work in parallel, so that we'll have something to merge. " "So let's clone our repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:242 msgid "" "Back in our initial repository, let's use the <command role=\"hg-cmd\">hg " "copy</command> command to make a copy of the first file we created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:248 msgid "" "If we look at the output of the <command role=\"hg-cmd\">hg status</command> " "command afterwards, the copied file looks just like a normal added file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:254 msgid "" "But if we pass the <option role=\"hg-opt-status\">-C</option> option to " "<command role=\"hg-cmd\">hg status</command>, it prints another line of " "output: this is the file that our newly-added file was copied <emphasis>from</" "emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:262 msgid "" "Now, back in the repository we cloned, let's make a change in parallel. " "We'll add a line of content to the original file that we created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:268 msgid "" "Now we have a modified <filename>file</filename> in this repository. When we " "pull the changes from the first repository, and merge the two heads, " "Mercurial will propagate the changes that we made locally to <filename>file</" "filename> into its copy, <filename>new-file</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:278 msgid "Why should changes follow copies?" msgstr "为什么复制后需要后续修改?" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:280 msgid "" "This behaviour, of changes to a file propagating out to copies of the file, " "might seem esoteric, but in most cases it's highly desirable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:284 msgid "" "First of all, remember that this propagation <emphasis>only</emphasis> " "happens when you merge. So if you <command role=\"hg-cmd\">hg copy</command> " "a file, and subsequently modify the original file during the normal course of " "your work, nothing will happen." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:290 msgid "" "The second thing to know is that modifications will only propagate across a " "copy as long as the repository that you're pulling changes from " "<emphasis>doesn't know</emphasis> about the copy." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:295 msgid "" "The reason that Mercurial does this is as follows. Let's say I make an " "important bug fix in a source file, and commit my changes. Meanwhile, you've " "decided to <command role=\"hg-cmd\">hg copy</command> the file in your " "repository, without knowing about the bug or having seen the fix, and you " "have started hacking on your copy of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:302 msgid "" "If you pulled and merged my changes, and Mercurial <emphasis>didn't</" "emphasis> propagate changes across copies, your source file would now contain " "the bug, and unless you remembered to propagate the bug fix by hand, the bug " "would <emphasis>remain</emphasis> in your copy of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:308 msgid "" "By automatically propagating the change that fixed the bug from the original " "file to the copy, Mercurial prevents this class of problem. To my knowledge, " "Mercurial is the <emphasis>only</emphasis> revision control system that " "propagates changes across copies like this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:314 msgid "" "Once your change history has a record that the copy and subsequent merge " "occurred, there's usually no further need to propagate changes from the " "original file to the copied file, and that's why Mercurial only propagates " "changes across copies until this point, and no further." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:322 msgid "How to make changes <emphasis>not</emphasis> follow a copy" msgstr "如何让复制后<emphasis>不</emphasis>修改?" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:325 msgid "" "If, for some reason, you decide that this business of automatically " "propagating changes across copies is not for you, simply use your system's " "normal file copy command (on Unix-like systems, that's <command>cp</command>) " "to make a copy of a file, then <command role=\"hg-cmd\">hg add</command> the " "new copy by hand. Before you do so, though, please do reread <xref linkend=" "\"sec:daily:why-copy\"/>, and make an informed decision that this behaviour " "is not appropriate to your specific case." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:338 msgid "Behaviour of the <command role=\"hg-cmd\">hg copy</command> command" msgstr "命令 <command role=\"hg-cmd\">hg copy</command> 的特性" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:341 msgid "" "When you use the <command role=\"hg-cmd\">hg copy</command> command, " "Mercurial makes a copy of each source file as it currently stands in the " "working directory. This means that if you make some modifications to a file, " "then <command role=\"hg-cmd\">hg copy</command> it without first having " "committed those changes, the new copy will also contain the modifications you " "have made up until that point. (I find this behaviour a little " "counterintuitive, which is why I mention it here.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:351 msgid "" "The <command role=\"hg-cmd\">hg copy</command> command acts similarly to the " "Unix <command>cp</command> command (you can use the <command role=\"hg-cmd" "\">hg cp</command> alias if you prefer). The last argument is the " "<emphasis>destination</emphasis>, and all prior arguments are " "<emphasis>sources</emphasis>. If you pass it a single file as the source, " "and the destination does not exist, it creates a new file with that name." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:362 msgid "" "If the destination is a directory, Mercurial copies its sources into that " "directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:367 msgid "" "Copying a directory is recursive, and preserves the directory structure of " "the source." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:373 msgid "" "If the source and destination are both directories, the source tree is " "recreated in the destination directory." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:378 msgid "" "As with the <command role=\"hg-cmd\">hg rename</command> command, if you copy " "a file manually and then want Mercurial to know that you've copied the file, " "simply use the <option role=\"hg-opt-copy\">--after</option> option to " "<command role=\"hg-cmd\">hg copy</command>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch04-daily.xml:389 msgid "Renaming files" msgstr "改名文件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:391 msgid "" "It's rather more common to need to rename a file than to make a copy of it. " "The reason I discussed the <command role=\"hg-cmd\">hg copy</command> command " "before talking about renaming files is that Mercurial treats a rename in " "essentially the same way as a copy. Therefore, knowing what Mercurial does " "when you copy a file tells you what to expect when you rename a file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:399 msgid "" "When you use the <command role=\"hg-cmd\">hg rename</command> command, " "Mercurial makes a copy of each source file, then deletes it and marks the " "file as removed." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:405 msgid "" "The <command role=\"hg-cmd\">hg status</command> command shows the newly " "copied file as added, and the copied-from file as removed." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:411 msgid "" "As with the results of a <command role=\"hg-cmd\">hg copy</command>, we must " "use the <option role=\"hg-opt-status\">-C</option> option to <command role=" "\"hg-cmd\">hg status</command> to see that the added file is really being " "tracked by Mercurial as a copy of the original, now removed, file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:420 msgid "" "As with <command role=\"hg-cmd\">hg remove</command> and <command role=\"hg-" "cmd\">hg copy</command>, you can tell Mercurial about a rename after the fact " "using the <option role=\"hg-opt-rename\">--after</option> option. In most " "other respects, the behaviour of the <command role=\"hg-cmd\">hg rename</" "command> command, and the options it accepts, are similar to the <command " "role=\"hg-cmd\">hg copy</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:430 msgid "Renaming files and merging changes" msgstr "改名文件与合并修改" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:432 msgid "" "Since Mercurial's rename is implemented as copy-and-remove, the same " "propagation of changes happens when you merge after a rename as after a copy." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:436 msgid "" "If I modify a file, and you rename it to a new name, and then we merge our " "respective changes, my modifications to the file under its original name will " "be propagated into the file under its new name. (This is something you might " "expect to <quote>simply work,</quote> but not all revision control systems " "actually do this.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:443 msgid "" "Whereas having changes follow a copy is a feature where you can perhaps nod " "and say <quote>yes, that might be useful,</quote> it should be clear that " "having them follow a rename is definitely important. Without this facility, " "it would simply be too easy for changes to become orphaned when files are " "renamed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:452 msgid "Divergent renames and merging" msgstr "改名与合并的分歧" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:454 msgid "" "The case of diverging names occurs when two developers start with a " "file&emdash;let's call it <filename>foo</filename>&emdash;in their respective " "repositories." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:461 msgid "Anne renames the file to <filename>bar</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:465 msgid "Meanwhile, Bob renames it to <filename>quux</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:470 msgid "" "I like to think of this as a conflict because each developer has expressed " "different intentions about what the file ought to be named." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:474 msgid "" "What do you think should happen when they merge their work? Mercurial's " "actual behaviour is that it always preserves <emphasis>both</emphasis> names " "when it merges changesets that contain divergent renames." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:481 msgid "" "Notice that Mercurial does warn about the divergent renames, but it leaves it " "up to you to do something about the divergence after the merge." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:487 msgid "Convergent renames and merging" msgstr "收敛改名与合并" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:489 msgid "" "Another kind of rename conflict occurs when two people choose to rename " "different <emphasis>source</emphasis> files to the same " "<emphasis>destination</emphasis>. In this case, Mercurial runs its normal " "merge machinery, and lets you guide it to a suitable resolution." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch04-daily.xml:497 msgid "Other name-related corner cases" msgstr "其它名称相关的角落" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch04-daily.xml:499 msgid "" "Mercurial has a longstanding bug in which it fails to handle a merge where " "one side has a file with a given name, while another has a directory with the " "same name. This is documented as <ulink role=\"hg-bug\" url=\"http://www." "selenic.com/mercurial/bts/issue29\">issue 29</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch04-daily.xml:511 msgid "Recovering from mistakes" msgstr "从错误恢复" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:513 msgid "" "Mercurial has some useful commands that will help you to recover from some " "common mistakes." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:516 msgid "" "The <command role=\"hg-cmd\">hg revert</command> command lets you undo " "changes that you have made to your working directory. For example, if you " "<command role=\"hg-cmd\">hg add</command> a file by accident, just run " "<command role=\"hg-cmd\">hg revert</command> with the name of the file you " "added, and while the file won't be touched in any way, it won't be tracked " "for adding by Mercurial any longer, either. You can also use <command role=" "\"hg-cmd\">hg revert</command> to get rid of erroneous changes to a file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:526 msgid "" "It's useful to remember that the <command role=\"hg-cmd\">hg revert</command> " "command is useful for changes that you have not yet committed. Once you've " "committed a change, if you decide it was a mistake, you can still do " "something about it, though your options may be more limited." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch04-daily.xml:532 msgid "" "For more information about the <command role=\"hg-cmd\">hg revert</command> " "command, and details about how to deal with changes you have already " "committed, see <xref linkend=\"chap:undo\"/>." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch05-collab.xml:5 msgid "Collaborating with other people" msgstr "团体协作" #. type: Content of: <book><chapter><para> #: ../en/ch05-collab.xml:7 msgid "" "As a completely decentralised tool, Mercurial doesn't impose any policy on " "how people ought to work with each other. However, if you're new to " "distributed revision control, it helps to have some tools and examples in " "mind when you're thinking about possible workflow models." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:14 msgid "Mercurial's web interface" msgstr "Mercurial 的 web 接口" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:16 msgid "" "Mercurial has a powerful web interface that provides several useful " "capabilities." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:19 msgid "" "For interactive use, the web interface lets you browse a single repository or " "a collection of repositories. You can view the history of a repository, " "examine each change (comments and diffs), and view the contents of each " "directory and file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:24 msgid "" "Also for human consumption, the web interface provides an RSS feed of the " "changes in a repository. This lets you <quote>subscribe</quote> to a " "repository using your favourite feed reader, and be automatically notified of " "activity in that repository as soon as it happens. I find this capability " "much more convenient than the model of subscribing to a mailing list to which " "notifications are sent, as it requires no additional configuration on the " "part of whoever is serving the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:34 msgid "" "The web interface also lets remote users clone a repository, pull changes " "from it, and (when the server is configured to permit it) push changes back " "to it. Mercurial's HTTP tunneling protocol aggressively compresses data, so " "that it works efficiently even over low-bandwidth network connections." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:40 msgid "" "The easiest way to get started with the web interface is to use your web " "browser to visit an existing repository, such as the master Mercurial " "repository at <ulink url=\"http://www.selenic.com/repo/hg?style=gitweb" "\">http://www.selenic.com/repo/hg?style=gitweb</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:45 msgid "" "If you're interested in providing a web interface to your own repositories, " "Mercurial provides two ways to do this. The first is using the <command role=" "\"hg-cmd\">hg serve</command> command, which is best suited to short-term " "<quote>lightweight</quote> serving. See <xref linkend=\"sec:collab:serve\"/> " "below for details of how to use this command. If you have a long-lived " "repository that you'd like to make permanently available, Mercurial has built-" "in support for the CGI (Common Gateway Interface) standard, which all common " "web servers support. See <xref linkend=\"sec:collab:cgi\"/> for details of " "CGI configuration." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:60 msgid "Collaboration models" msgstr "协作模型" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:62 msgid "" "With a suitably flexible tool, making decisions about workflow is much more " "of a social engineering challenge than a technical one. Mercurial imposes few " "limitations on how you can structure the flow of work in a project, so it's " "up to you and your group to set up and live with a model that matches your " "own particular needs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:70 msgid "Factors to keep in mind" msgstr "要牢记的因素" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:72 msgid "" "The most important aspect of any model that you must keep in mind is how well " "it matches the needs and capabilities of the people who will be using it. " "This might seem self-evident; even so, you still can't afford to forget it " "for a moment." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:78 msgid "" "I once put together a workflow model that seemed to make perfect sense to me, " "but that caused a considerable amount of consternation and strife within my " "development team. In spite of my attempts to explain why we needed a complex " "set of branches, and how changes ought to flow between them, a few team " "members revolted. Even though they were smart people, they didn't want to " "pay attention to the constraints we were operating under, or face the " "consequences of those constraints in the details of the model that I was " "advocating." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:88 msgid "" "Don't sweep foreseeable social or technical problems under the rug. Whatever " "scheme you put into effect, you should plan for mistakes and problem " "scenarios. Consider adding automated machinery to prevent, or quickly " "recover from, trouble that you can anticipate. As an example, if you intend " "to have a branch with not-for-release changes in it, you'd do well to think " "early about the possibility that someone might accidentally merge those " "changes into a release branch. You could avoid this particular problem by " "writing a hook that prevents changes from being merged from an inappropriate " "branch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:102 msgid "Informal anarchy" msgstr "无政府状态" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:104 msgid "" "I wouldn't suggest an <quote>anything goes</quote> approach as something " "sustainable, but it's a model that's easy to grasp, and it works perfectly " "well in a few unusual situations." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:109 msgid "" "As one example, many projects have a loose-knit group of collaborators who " "rarely physically meet each other. Some groups like to overcome the " "isolation of working at a distance by organising occasional <quote>sprints</" "quote>. In a sprint, a number of people get together in a single location (a " "company's conference room, a hotel meeting room, that kind of place) and " "spend several days more or less locked in there, hacking intensely on a " "handful of projects." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:118 msgid "" "A sprint is the perfect place to use the <command role=\"hg-cmd\">hg serve</" "command> command, since <command role=\"hg-cmd\">hg serve</command> does not " "require any fancy server infrastructure. You can get started with <command " "role=\"hg-cmd\">hg serve</command> in moments, by reading <xref linkend=\"sec:" "collab:serve\"/> below. Then simply tell the person next to you that you're " "running a server, send the URL to them in an instant message, and you " "immediately have a quick-turnaround way to work together. They can type your " "URL into their web browser and quickly review your changes; or they can pull " "a bugfix from you and verify it; or they can clone a branch containing a new " "feature and try it out." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:132 msgid "" "The charm, and the problem, with doing things in an ad hoc fashion like this " "is that only people who know about your changes, and where they are, can see " "them. Such an informal approach simply doesn't scale beyond a handful " "people, because each individual needs to know about $n$ different " "repositories to pull from." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:141 msgid "A single central repository" msgstr "单一中央版本库" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:143 msgid "" "For smaller projects migrating from a centralised revision control tool, " "perhaps the easiest way to get started is to have changes flow through a " "single shared central repository. This is also the most common " "<quote>building block</quote> for more ambitious workflow schemes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:149 msgid "" "Contributors start by cloning a copy of this repository. They can pull " "changes from it whenever they need to, and some (perhaps all) developers have " "permission to push a change back when they're ready for other people to see " "it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:154 msgid "" "Under this model, it can still often make sense for people to pull changes " "directly from each other, without going through the central repository. " "Consider a case in which I have a tentative bug fix, but I am worried that if " "I were to publish it to the central repository, it might subsequently break " "everyone else's trees as they pull it. To reduce the potential for damage, I " "can ask you to clone my repository into a temporary repository of your own " "and test it. This lets us put off publishing the potentially unsafe change " "until it has had a little testing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:165 msgid "" "In this kind of scenario, people usually use the <command>ssh</command> " "protocol to securely push changes to the central repository, as documented in " "<xref linkend=\"sec:collab:ssh\"/>. It's also usual to publish a read-only " "copy of the repository over HTTP using CGI, as in <xref linkend=\"sec:collab:" "cgi\"/>. Publishing over HTTP satisfies the needs of people who don't have " "push access, and those who want to use web browsers to browse the " "repository's history." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:177 msgid "Working with multiple branches" msgstr "使用多个分支工作" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:179 msgid "" "Projects of any significant size naturally tend to make progress on several " "fronts simultaneously. In the case of software, it's common for a project to " "go through periodic official releases. A release might then go into " "<quote>maintenance mode</quote> for a while after its first publication; " "maintenance releases tend to contain only bug fixes, not new features. In " "parallel with these maintenance releases, one or more future releases may be " "under development. People normally use the word <quote>branch</quote> to " "refer to one of these many slightly different directions in which development " "is proceeding." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:192 msgid "" "Mercurial is particularly well suited to managing a number of simultaneous, " "but not identical, branches. Each <quote>development direction</quote> can " "live in its own central repository, and you can merge changes from one to " "another as the need arises. Because repositories are independent of each " "other, unstable changes in a development branch will never affect a stable " "branch unless someone explicitly merges those changes in." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:201 msgid "" "Here's an example of how this can work in practice. Let's say you have one " "<quote>main branch</quote> on a central server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:207 msgid "People clone it, make changes locally, test them, and push them back." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:210 msgid "" "Once the main branch reaches a release milestone, you can use the <command " "role=\"hg-cmd\">hg tag</command> command to give a permanent name to the " "milestone revision." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:216 msgid "Let's say some ongoing development occurs on the main branch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:221 msgid "" "Using the tag that was recorded at the milestone, people who clone that " "repository at any time in the future can use <command role=\"hg-cmd\">hg " "update</command> to get a copy of the working directory exactly as it was " "when that tagged revision was committed." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:229 msgid "" "In addition, immediately after the main branch is tagged, someone can then " "clone the main branch on the server to a new <quote>stable</quote> branch, " "also on the server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:235 msgid "" "Someone who needs to make a change to the stable branch can then clone " "<emphasis>that</emphasis> repository, make their changes, commit, and push " "their changes back there." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:241 msgid "" "Because Mercurial repositories are independent, and Mercurial doesn't move " "changes around automatically, the stable and main branches are " "<emphasis>isolated</emphasis> from each other. The changes that you made on " "the main branch don't <quote>leak</quote> to the stable branch, and vice " "versa." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:248 msgid "" "You'll often want all of your bugfixes on the stable branch to show up on the " "main branch, too. Rather than rewrite a bugfix on the main branch, you can " "simply pull and merge changes from the stable to the main branch, and " "Mercurial will bring those bugfixes in for you." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:256 msgid "" "The main branch will still contain changes that are not on the stable branch, " "but it will also contain all of the bugfixes from the stable branch. The " "stable branch remains unaffected by these changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch05-collab.xml:263 ../en/ch05-collab.xml:273 msgid "Feature branches" msgstr "特性分支" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:265 msgid "" "For larger projects, an effective way to manage change is to break up a team " "into smaller groups. Each group has a shared branch of its own, cloned from " "a single <quote>master</quote> branch used by the entire project. People " "working on an individual branch are typically quite isolated from " "developments on other branches." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch05-collab.xml:275 msgid "" "<imageobject><imagedata width=\"100%\" fileref=\"figs/feature-branches.png\"/" "></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:280 msgid "" "When a particular feature is deemed to be in suitable shape, someone on that " "feature team pulls and merges from the master branch into the feature branch, " "then pushes back up to the master branch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:287 msgid "The release train" msgstr "发布列车" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:289 msgid "" "Some projects are organised on a <quote>train</quote> basis: a release is " "scheduled to happen every few months, and whatever features are ready when " "the <quote>train</quote> is ready to leave are allowed in." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:294 msgid "" "This model resembles working with feature branches. The difference is that " "when a feature branch misses a train, someone on the feature team pulls and " "merges the changes that went out on that train release into the feature " "branch, and the team continues its work on top of that release so that their " "feature can make the next release." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:303 msgid "The Linux kernel model" msgstr "Linux 内核模型" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:305 msgid "" "The development of the Linux kernel has a shallow hierarchical structure, " "surrounded by a cloud of apparent chaos. Because most Linux developers use " "<command>git</command>, a distributed revision control tool with capabilities " "similar to Mercurial, it's useful to describe the way work flows in that " "environment; if you like the ideas, the approach translates well across tools." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:313 msgid "" "At the center of the community sits Linus Torvalds, the creator of Linux. He " "publishes a single source repository that is considered the " "<quote>authoritative</quote> current tree by the entire developer community. " "Anyone can clone Linus's tree, but he is very choosy about whose trees he " "pulls from." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:320 msgid "" "Linus has a number of <quote>trusted lieutenants</quote>. As a general rule, " "he pulls whatever changes they publish, in most cases without even reviewing " "those changes. Some of those lieutenants are generally agreed to be " "<quote>maintainers</quote>, responsible for specific subsystems within the " "kernel. If a random kernel hacker wants to make a change to a subsystem that " "they want to end up in Linus's tree, they must find out who the subsystem's " "maintainer is, and ask that maintainer to take their change. If the " "maintainer reviews their changes and agrees to take them, they'll pass them " "along to Linus in due course." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:332 msgid "" "Individual lieutenants have their own approaches to reviewing, accepting, and " "publishing changes; and for deciding when to feed them to Linus. In " "addition, there are several well known branches that people use for different " "purposes. For example, a few people maintain <quote>stable</quote> " "repositories of older versions of the kernel, to which they apply critical " "fixes as needed. Some maintainers publish multiple trees: one for " "experimental changes; one for changes that they are about to feed upstream; " "and so on. Others just publish a single tree." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:343 msgid "" "This model has two notable features. The first is that it's <quote>pull " "only</quote>. You have to ask, convince, or beg another developer to take a " "change from you, because there are almost no trees to which more than one " "person can push, and there's no way to push changes into a tree that someone " "else controls." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:350 msgid "" "The second is that it's based on reputation and acclaim. If you're an " "unknown, Linus will probably ignore changes from you without even " "responding. But a subsystem maintainer will probably review them, and will " "likely take them if they pass their criteria for suitability. The more " "<quote>good</quote> changes you contribute to a maintainer, the more likely " "they are to trust your judgment and accept your changes. If you're well-" "known and maintain a long-lived branch for something Linus hasn't yet " "accepted, people with similar interests may pull your changes regularly to " "keep up with your work." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:361 msgid "" "Reputation and acclaim don't necessarily cross subsystem or <quote>people</" "quote> boundaries. If you're a respected but specialised storage hacker, and " "you try to fix a networking bug, that change will receive a level of scrutiny " "from a network maintainer comparable to a change from a complete stranger." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:368 msgid "" "To people who come from more orderly project backgrounds, the comparatively " "chaotic Linux kernel development process often seems completely insane. It's " "subject to the whims of individuals; people make sweeping changes whenever " "they deem it appropriate; and the pace of development is astounding. And yet " "Linux is a highly successful, well-regarded piece of software." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:378 msgid "Pull-only versus shared-push collaboration" msgstr "只读与共享写协作" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:380 msgid "" "A perpetual source of heat in the open source community is whether a " "development model in which people only ever pull changes from others is " "<quote>better than</quote> one in which multiple people can push changes to a " "shared repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:386 msgid "" "Typically, the backers of the shared-push model use tools that actively " "enforce this approach. If you're using a centralised revision control tool " "such as Subversion, there's no way to make a choice over which model you'll " "use: the tool gives you shared-push, and if you want to do anything else, " "you'll have to roll your own approach on top (such as applying a patch by " "hand)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:394 msgid "" "A good distributed revision control tool, such as Mercurial, will support " "both models. You and your collaborators can then structure how you work " "together based on your own needs and preferences, not on what contortions " "your tools force you into." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:402 msgid "Where collaboration meets branch management" msgstr "协作与分支管理" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:404 msgid "" "Once you and your team set up some shared repositories and start propagating " "changes back and forth between local and shared repos, you begin to face a " "related, but slightly different challenge: that of managing the multiple " "directions in which your team may be moving at once. Even though this " "subject is intimately related to how your team collaborates, it's dense " "enough to merit treatment of its own, in <xref linkend=\"chap:branch\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:416 msgid "The technical side of sharing" msgstr "共享的技术因素" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:418 msgid "" "The remainder of this chapter is devoted to the question of serving data to " "your collaborators." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:423 msgid "Informal sharing with <command role=\"hg-cmd\">hg serve</command>" msgstr "使用 <command role=\"hg-cmd\">hg serve</command> 进行非正式共享" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:426 msgid "" "Mercurial's <command role=\"hg-cmd\">hg serve</command> command is " "wonderfully suited to small, tight-knit, and fast-paced group environments. " "It also provides a great way to get a feel for using Mercurial commands over " "a network." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:431 msgid "" "Run <command role=\"hg-cmd\">hg serve</command> inside a repository, and in " "under a second it will bring up a specialised HTTP server; this will accept " "connections from any client, and serve up data for that repository until you " "terminate it. Anyone who knows the URL of the server you just started, and " "can talk to your computer over the network, can then use a web browser or " "Mercurial to read data from that repository. A URL for a <command role=\"hg-" "cmd\">hg serve</command> instance running on a laptop is likely to look " "something like <literal>http://my-laptop.local:8000/</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:442 msgid "" "The <command role=\"hg-cmd\">hg serve</command> command is <emphasis>not</" "emphasis> a general-purpose web server. It can do only two things:" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:446 msgid "" "Allow people to browse the history of the repository it's serving, from their " "normal web browsers." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:450 msgid "" "Speak Mercurial's wire protocol, so that people can <command role=\"hg-cmd" "\">hg clone</command> or <command role=\"hg-cmd\">hg pull</command> changes " "from that repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:455 msgid "" "In particular, <command role=\"hg-cmd\">hg serve</command> won't allow remote " "users to <emphasis>modify</emphasis> your repository. It's intended for read-" "only use." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:459 msgid "" "If you're getting started with Mercurial, there's nothing to prevent you from " "using <command role=\"hg-cmd\">hg serve</command> to serve up a repository on " "your own computer, then use commands like <command role=\"hg-cmd\">hg clone</" "command>, <command role=\"hg-cmd\">hg incoming</command>, and so on to talk " "to that server as if the repository was hosted remotely. This can help you to " "quickly get acquainted with using commands on network-hosted repositories." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:469 msgid "A few things to keep in mind" msgstr "要牢记的几件事" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:471 msgid "" "Because it provides unauthenticated read access to all clients, you should " "only use <command role=\"hg-cmd\">hg serve</command> in an environment where " "you either don't care, or have complete control over, who can access your " "network and pull data from your repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:477 msgid "" "The <command role=\"hg-cmd\">hg serve</command> command knows nothing about " "any firewall software you might have installed on your system or network. It " "cannot detect or control your firewall software. If other people are unable " "to talk to a running <command role=\"hg-cmd\">hg serve</command> instance, " "the second thing you should do (<emphasis>after</emphasis> you make sure that " "they're using the correct URL) is check your firewall configuration." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:486 msgid "" "By default, <command role=\"hg-cmd\">hg serve</command> listens for incoming " "connections on port 8000. If another process is already listening on the " "port you want to use, you can specify a different port to listen on using the " "<option role=\"hg-opt-serve\">-p</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:492 msgid "" "Normally, when <command role=\"hg-cmd\">hg serve</command> starts, it prints " "no output, which can be a bit unnerving. If you'd like to confirm that it is " "indeed running correctly, and find out what URL you should send to your " "collaborators, start it with the <option role=\"hg-opt-global\">-v</option> " "option." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:502 msgid "Using the Secure Shell (ssh) protocol" msgstr "使用 ssh 协议" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:504 msgid "" "You can pull and push changes securely over a network connection using the " "Secure Shell (<literal>ssh</literal>) protocol. To use this successfully, " "you may have to do a little bit of configuration on the client or server " "sides." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:509 msgid "" "If you're not familiar with ssh, it's a network protocol that lets you " "securely communicate with another computer. To use it with Mercurial, you'll " "be setting up one or more user accounts on a server so that remote users can " "log in and execute commands." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:515 msgid "" "(If you <emphasis>are</emphasis> familiar with ssh, you'll probably find some " "of the material that follows to be elementary in nature.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:520 msgid "How to read and write ssh URLs" msgstr "如何读写 ssh 路径" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:522 msgid "An ssh URL tends to look like this:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:525 msgid "" "The <quote><literal>ssh://</literal></quote> part tells Mercurial to use the " "ssh protocol." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:528 msgid "" "The <quote><literal>bos@</literal></quote> component indicates what username " "to log into the server as. You can leave this out if the remote username is " "the same as your local username." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:533 msgid "" "The <quote><literal>hg.serpentine.com</literal></quote> gives the hostname of " "the server to log into." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:537 msgid "" "The <quote>:22</quote> identifies the port number to connect to the server " "on. The default port is 22, so you only need to specify a colon and port " "number if you're <emphasis>not</emphasis> using port 22." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:542 msgid "" "The remainder of the URL is the local path to the repository on the server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:546 msgid "" "There's plenty of scope for confusion with the path component of ssh URLs, as " "there is no standard way for tools to interpret it. Some programs behave " "differently than others when dealing with these paths. This isn't an ideal " "situation, but it's unlikely to change. Please read the following paragraphs " "carefully." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:553 msgid "" "Mercurial treats the path to a repository on the server as relative to the " "remote user's home directory. For example, if user <literal>foo</literal> on " "the server has a home directory of <filename class=\"directory\">/home/foo</" "filename>, then an ssh URL that contains a path component of <filename class=" "\"directory\">bar</filename> <emphasis>really</emphasis> refers to the " "directory <filename class=\"directory\">/home/foo/bar</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:562 msgid "" "If you want to specify a path relative to another user's home directory, you " "can use a path that starts with a tilde character followed by the user's name " "(let's call them <literal>otheruser</literal>), like this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:568 msgid "" "And if you really want to specify an <emphasis>absolute</emphasis> path on " "the server, begin the path component with two slashes, as in this example." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:575 msgid "Finding an ssh client for your system" msgstr "为你的系统寻找 ssh 客户端" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:577 msgid "" "Almost every Unix-like system comes with OpenSSH preinstalled. If you're " "using such a system, run <literal>which ssh</literal> to find out if the " "<command>ssh</command> command is installed (it's usually in <filename class=" "\"directory\">/usr/bin</filename>). In the unlikely event that it isn't " "present, take a look at your system documentation to figure out how to " "install it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:585 msgid "" "On Windows, you'll first need to download a suitable ssh client. There are " "two alternatives." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:588 msgid "" "Simon Tatham's excellent PuTTY package <citation>web:putty</citation> " "provides a complete suite of ssh client commands." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:592 msgid "" "If you have a high tolerance for pain, you can use the Cygwin port of OpenSSH." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:595 msgid "" "In either case, you'll need to edit your <filename role=\"special\">hg.ini</" "filename> file to tell Mercurial where to find the actual client command. " "For example, if you're using PuTTY, you'll need to use the <command>plink</" "command> command as a command-line ssh client." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch05-collab.xml:605 msgid "" "The path to <command>plink</command> shouldn't contain any whitespace " "characters, or Mercurial may not be able to run it correctly (so putting it " "in <filename class=\"directory\">C:\\Program Files</filename> is probably not " "a good idea)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:614 msgid "Generating a key pair" msgstr "产生密钥对" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:616 msgid "" "To avoid the need to repetitively type a password every time you need to use " "your ssh client, I recommend generating a key pair. On a Unix-like system, " "the <command>ssh-keygen</command> command will do the trick. On Windows, if " "you're using PuTTY, the <command>puttygen</command> command is what you'll " "need." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:624 msgid "" "When you generate a key pair, it's usually <emphasis>highly</emphasis> " "advisable to protect it with a passphrase. (The only time that you might not " "want to do this is when you're using the ssh protocol for automated tasks on " "a secure network.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:630 msgid "" "Simply generating a key pair isn't enough, however. You'll need to add the " "public key to the set of authorised keys for whatever user you're logging in " "remotely as. For servers using OpenSSH (the vast majority), this will mean " "adding the public key to a list in a file called <filename role=\"special" "\">authorized_keys</filename> in their <filename role=\"special\" class=" "\"directory\">.ssh</filename> directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:639 msgid "" "On a Unix-like system, your public key will have a <filename>.pub</filename> " "extension. If you're using <command>puttygen</command> on Windows, you can " "save the public key to a file of your choosing, or paste it from the window " "it's displayed in straight into the <filename role=\"special" "\">authorized_keys</filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:648 msgid "Using an authentication agent" msgstr "使用认证代理" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:650 msgid "" "An authentication agent is a daemon that stores passphrases in memory (so it " "will forget passphrases if you log out and log back in again). An ssh client " "will notice if it's running, and query it for a passphrase. If there's no " "authentication agent running, or the agent doesn't store the necessary " "passphrase, you'll have to type your passphrase every time Mercurial tries to " "communicate with a server on your behalf (e.g. whenever you pull or push " "changes)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:659 msgid "" "The downside of storing passphrases in an agent is that it's possible for a " "well-prepared attacker to recover the plain text of your passphrases, in some " "cases even if your system has been power-cycled. You should make your own " "judgment as to whether this is an acceptable risk. It certainly saves a lot " "of repeated typing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:666 msgid "" "On Unix-like systems, the agent is called <command>ssh-agent</command>, and " "it's often run automatically for you when you log in. You'll need to use the " "<command>ssh-add</command> command to add passphrases to the agent's store. " "On Windows, if you're using PuTTY, the <command>pageant</command> command " "acts as the agent. It adds an icon to your system tray that will let you " "manage stored passphrases." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:677 msgid "Configuring the server side properly" msgstr "正确配置服务器端" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:679 msgid "" "Because ssh can be fiddly to set up if you're new to it, there's a variety of " "things that can go wrong. Add Mercurial on top, and there's plenty more " "scope for head-scratching. Most of these potential problems occur on the " "server side, not the client side. The good news is that once you've gotten a " "configuration working, it will usually continue to work indefinitely." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:687 msgid "" "Before you try using Mercurial to talk to an ssh server, it's best to make " "sure that you can use the normal <command>ssh</command> or <command>putty</" "command> command to talk to the server first. If you run into problems with " "using these commands directly, Mercurial surely won't work. Worse, it will " "obscure the underlying problem. Any time you want to debug ssh-related " "Mercurial problems, you should drop back to making sure that plain ssh client " "commands work first, <emphasis>before</emphasis> you worry about whether " "there's a problem with Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:698 msgid "" "The first thing to be sure of on the server side is that you can actually log " "in from another machine at all. If you can't use <command>ssh</command> or " "<command>putty</command> to log in, the error message you get may give you a " "few hints as to what's wrong. The most common problems are as follows." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:705 msgid "" "If you get a <quote>connection refused</quote> error, either there isn't an " "SSH daemon running on the server at all, or it's inaccessible due to firewall " "configuration." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:710 msgid "" "If you get a <quote>no route to host</quote> error, you either have an " "incorrect address for the server or a seriously locked down firewall that " "won't admit its existence at all." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:715 msgid "" "If you get a <quote>permission denied</quote> error, you may have mistyped " "the username on the server, or you could have mistyped your key's passphrase " "or the remote user's password." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:720 msgid "" "In summary, if you're having trouble talking to the server's ssh daemon, " "first make sure that one is running at all. On many systems it will be " "installed, but disabled, by default. Once you're done with this step, you " "should then check that the server's firewall is configured to allow incoming " "connections on the port the ssh daemon is listening on (usually 22). Don't " "worry about more exotic possibilities for misconfiguration until you've " "checked these two first." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:730 msgid "" "If you're using an authentication agent on the client side to store " "passphrases for your keys, you ought to be able to log into the server " "without being prompted for a passphrase or a password. If you're prompted " "for a passphrase, there are a few possible culprits." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:736 msgid "" "You might have forgotten to use <command>ssh-add</command> or " "<command>pageant</command> to store the passphrase." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:740 msgid "You might have stored the passphrase for the wrong key." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:743 msgid "" "If you're being prompted for the remote user's password, there are another " "few possible problems to check." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:746 msgid "" "Either the user's home directory or their <filename role=\"special\" class=" "\"directory\">.ssh</filename> directory might have excessively liberal " "permissions. As a result, the ssh daemon will not trust or read their " "<filename role=\"special\">authorized_keys</filename> file. For example, a " "group-writable home or <filename role=\"special\" class=\"directory\">.ssh</" "filename> directory will often cause this symptom." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:755 msgid "" "The user's <filename role=\"special\">authorized_keys</filename> file may " "have a problem. If anyone other than the user owns or can write to that file, " "the ssh daemon will not trust or read it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:762 msgid "" "In the ideal world, you should be able to run the following command " "successfully, and it should print exactly one line of output, the current " "date and time." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:767 msgid "" "If, on your server, you have login scripts that print banners or other junk " "even when running non-interactive commands like this, you should fix them " "before you continue, so that they only print output if they're run " "interactively. Otherwise these banners will at least clutter up Mercurial's " "output. Worse, they could potentially cause problems with running Mercurial " "commands remotely. Mercurial makes tries to detect and ignore banners in non-" "interactive <command>ssh</command> sessions, but it is not foolproof. (If " "you're editing your login scripts on your server, the usual way to see if a " "login script is running in an interactive shell is to check the return code " "from the command <literal>tty -s</literal>.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:781 msgid "" "Once you've verified that plain old ssh is working with your server, the next " "step is to ensure that Mercurial runs on the server. The following command " "should run successfully:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:788 msgid "" "If you see an error message instead of normal <command role=\"hg-cmd\">hg " "version</command> output, this is usually because you haven't installed " "Mercurial to <filename class=\"directory\">/usr/bin</filename>. Don't worry " "if this is the case; you don't need to do that. But you should check for a " "few possible problems." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:795 msgid "" "Is Mercurial really installed on the server at all? I know this sounds " "trivial, but it's worth checking!" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:799 msgid "" "Maybe your shell's search path (usually set via the <envar>PATH</envar> " "environment variable) is simply misconfigured." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:803 msgid "" "Perhaps your <envar>PATH</envar> environment variable is only being set to " "point to the location of the <command>hg</command> executable if the login " "session is interactive. This can happen if you're setting the path in the " "wrong shell login script. See your shell's documentation for details." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:810 msgid "" "The <envar>PYTHONPATH</envar> environment variable may need to contain the " "path to the Mercurial Python modules. It might not be set at all; it could " "be incorrect; or it may be set only if the login is interactive." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:817 msgid "" "If you can run <command role=\"hg-cmd\">hg version</command> over an ssh " "connection, well done! You've got the server and client sorted out. You " "should now be able to use Mercurial to access repositories hosted by that " "username on that server. If you run into problems with Mercurial and ssh at " "this point, try using the <option role=\"hg-opt-global\">--debug</option> " "option to get a clearer picture of what's going on." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:827 msgid "Using compression with ssh" msgstr "通过 ssh 使用压缩" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:829 msgid "" "Mercurial does not compress data when it uses the ssh protocol, because the " "ssh protocol can transparently compress data. However, the default behaviour " "of ssh clients is <emphasis>not</emphasis> to request compression." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:834 msgid "" "Over any network other than a fast LAN (even a wireless network), using " "compression is likely to significantly speed up Mercurial's network " "operations. For example, over a WAN, someone measured compression as " "reducing the amount of time required to clone a particularly large repository " "from 51 minutes to 17 minutes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:841 msgid "" "Both <command>ssh</command> and <command>plink</command> accept a <option " "role=\"cmd-opt-ssh\">-C</option> option which turns on compression. You can " "easily edit your <filename role=\"special\">~/.hgrc</filename> to enable " "compression for all of Mercurial's uses of the ssh protocol." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:849 msgid "" "If you use <command>ssh</command>, you can configure it to always use " "compression when talking to your server. To do this, edit your <filename " "role=\"special\">.ssh/config</filename> file (which may not yet exist), as " "follows." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:857 msgid "" "This defines an alias, <literal>hg</literal>. When you use it on the " "<command>ssh</command> command line or in a Mercurial <literal>ssh</literal>-" "protocol URL, it will cause <command>ssh</command> to connect to <literal>hg." "example.com</literal> and use compression. This gives you both a shorter " "name to type and compression, each of which is a good thing in its own right." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch05-collab.xml:868 msgid "Serving over HTTP using CGI" msgstr "使用 CGI 通过 HTTP 提供服务" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:870 msgid "" "Depending on how ambitious you are, configuring Mercurial's CGI interface can " "take anything from a few moments to several hours." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch05-collab.xml:874 msgid "" "We'll begin with the simplest of examples, and work our way towards a more " "complex configuration. Even for the most basic case, you're almost certainly " "going to need to read and modify your web server's configuration." msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch05-collab.xml:880 msgid "" "Configuring a web server is a complex, fiddly, and highly system-dependent " "activity. I can't possibly give you instructions that will cover anything " "like all of the cases you will encounter. Please use your discretion and " "judgment in following the sections below. Be prepared to make plenty of " "mistakes, and to spend a lot of time reading your server's error logs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:890 msgid "Web server configuration checklist" msgstr "Web 服务器配置检查表" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:892 msgid "" "Before you continue, do take a few moments to check a few aspects of your " "system's setup." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:896 msgid "" "Do you have a web server installed at all? Mac OS X ships with Apache, but " "many other systems may not have a web server installed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:900 msgid "" "If you have a web server installed, is it actually running? On most systems, " "even if one is present, it will be disabled by default." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch05-collab.xml:904 msgid "" "Is your server configured to allow you to run CGI programs in the directory " "where you plan to do so? Most servers default to explicitly disabling the " "ability to run CGI programs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:910 msgid "" "If you don't have a web server installed, and don't have substantial " "experience configuring Apache, you should consider using the " "<literal>lighttpd</literal> web server instead of Apache. Apache has a well-" "deserved reputation for baroque and confusing configuration. While " "<literal>lighttpd</literal> is less capable in some ways than Apache, most of " "these capabilities are not relevant to serving Mercurial repositories. And " "<literal>lighttpd</literal> is undeniably <emphasis>much</emphasis> easier to " "get started with than Apache." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:923 msgid "Basic CGI configuration" msgstr "基本 CGI 配置" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:925 msgid "" "On Unix-like systems, it's common for users to have a subdirectory named " "something like <filename class=\"directory\">public_html</filename> in their " "home directory, from which they can serve up web pages. A file named " "<filename>foo</filename> in this directory will be accessible at a URL of the " "form <literal>http://www.example.com/username/foo</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:933 msgid "" "To get started, find the <filename role=\"special\">hgweb.cgi</filename> " "script that should be present in your Mercurial installation. If you can't " "quickly find a local copy on your system, simply download one from the master " "Mercurial repository at <ulink url=\"http://www.selenic.com/repo/hg/raw-file/" "tip/hgweb.cgi\">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:940 ../en/ch05-collab.xml:1109 msgid "" "You'll need to copy this script into your <filename class=\"directory" "\">public_html</filename> directory, and ensure that it's executable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:945 msgid "" "The <literal>755</literal> argument to <command>chmod</command> is a little " "more general than just making the script executable: it ensures that the " "script is executable by anyone, and that <quote>group</quote> and " "<quote>other</quote> write permissions are <emphasis>not</emphasis> set. If " "you were to leave those write permissions enabled, Apache's <literal>suexec</" "literal> subsystem would likely refuse to execute the script. In fact, " "<literal>suexec</literal> also insists that the <emphasis>directory</" "emphasis> in which the script resides must not be writable by others." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:959 msgid "What could <emphasis>possibly</emphasis> go wrong?" msgstr "什么<emphasis>可能</emphasis>会出错?" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:962 msgid "" "Once you've copied the CGI script into place, go into a web browser, and try " "to open the URL <ulink url=\"http://myhostname/ myuser/hgweb.cgi\">http://" "myhostname/ myuser/hgweb.cgi</ulink>, <emphasis>but</emphasis> brace yourself " "for instant failure. There's a high probability that trying to visit this " "URL will fail, and there are many possible reasons for this. In fact, you're " "likely to stumble over almost every one of the possible errors below, so " "please read carefully. The following are all of the problems I ran into on a " "system running Fedora 7, with a fresh installation of Apache, and a user " "account that I created specially to perform this exercise." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:976 msgid "" "Your web server may have per-user directories disabled. If you're using " "Apache, search your config file for a <literal>UserDir</literal> directive. " "If there's none present, per-user directories will be disabled. If one " "exists, but its value is <literal>disabled</literal>, then per-user " "directories will be disabled. Otherwise, the string after <literal>UserDir</" "literal> gives the name of the subdirectory that Apache will look in under " "your home directory, for example <filename class=\"directory\">public_html</" "filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:987 msgid "" "Your file access permissions may be too restrictive. The web server must be " "able to traverse your home directory and directories under your <filename " "class=\"directory\">public_html</filename> directory, and read files under " "the latter too. Here's a quick recipe to help you to make your permissions " "more appropriate." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:997 msgid "" "The other possibility with permissions is that you might get a completely " "empty window when you try to load the script. In this case, it's likely that " "your access permissions are <emphasis>too permissive</emphasis>. Apache's " "<literal>suexec</literal> subsystem won't execute a script that's group- or " "world-writable, for example." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1004 msgid "" "Your web server may be configured to disallow execution of CGI programs in " "your per-user web directory. Here's Apache's default per-user configuration " "from my Fedora system." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1011 msgid "" "If you find a similar-looking <literal>Directory</literal> group in your " "Apache configuration, the directive to look at inside it is <literal>Options</" "literal>. Add <literal>ExecCGI</literal> to the end of this list if it's " "missing, and restart the web server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1018 msgid "" "If you find that Apache serves you the text of the CGI script instead of " "executing it, you may need to either uncomment (if already present) or add a " "directive like this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1024 msgid "" "The next possibility is that you might be served with a colourful Python " "backtrace claiming that it can't import a <literal>mercurial</literal>-" "related module. This is actually progress! The server is now capable of " "executing your CGI script. This error is only likely to occur if you're " "running a private installation of Mercurial, instead of a system-wide " "version. Remember that the web server runs the CGI program without any of " "the environment variables that you take for granted in an interactive " "session. If this error happens to you, edit your copy of <filename role=" "\"special\">hgweb.cgi</filename> and follow the directions inside it to " "correctly set your <envar>PYTHONPATH</envar> environment variable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1038 msgid "" "Finally, you are <emphasis>certain</emphasis> to by served with another " "colourful Python backtrace: this one will complain that it can't find " "<filename class=\"directory\">/path/to/repository</filename>. Edit your " "<filename role=\"special\">hgweb.cgi</filename> script and replace the " "<filename class=\"directory\">/path/to/repository</filename> string with the " "complete path to the repository you want to serve up." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1048 msgid "" "At this point, when you try to reload the page, you should be presented with " "a nice HTML view of your repository's history. Whew!" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:1054 msgid "Configuring lighttpd" msgstr "配置 lighttpd" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1056 msgid "" "To be exhaustive in my experiments, I tried configuring the increasingly " "popular <literal>lighttpd</literal> web server to serve the same repository " "as I described with Apache above. I had already overcome all of the problems " "I outlined with Apache, many of which are not server-specific. As a result, " "I was fairly sure that my file and directory permissions were good, and that " "my <filename role=\"special\">hgweb.cgi</filename> script was properly edited." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1066 msgid "" "Once I had Apache running, getting <literal>lighttpd</literal> to serve the " "repository was a snap (in other words, even if you're trying to use " "<literal>lighttpd</literal>, you should read the Apache section). I first " "had to edit the <literal>mod_access</literal> section of its config file to " "enable <literal>mod_cgi</literal> and <literal>mod_userdir</literal>, both of " "which were disabled by default on my system. I then added a few lines to the " "end of the config file, to configure these modules." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1078 msgid "" "With this done, <literal>lighttpd</literal> ran immediately for me. If I had " "configured <literal>lighttpd</literal> before Apache, I'd almost certainly " "have run into many of the same system-level configuration problems as I did " "with Apache. However, I found <literal>lighttpd</literal> to be noticeably " "easier to configure than Apache, even though I've used Apache for over a " "decade, and this was my first exposure to <literal>lighttpd</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:1091 msgid "Sharing multiple repositories with one CGI script" msgstr "使用一个 CGI 脚本共享多个版本库" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1093 msgid "" "The <filename role=\"special\">hgweb.cgi</filename> script only lets you " "publish a single repository, which is an annoying restriction. If you want " "to publish more than one without wracking yourself with multiple copies of " "the same script, each with different names, a better choice is to use the " "<filename role=\"special\">hgwebdir.cgi</filename> script." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1101 msgid "" "The procedure to configure <filename role=\"special\">hgwebdir.cgi</filename> " "is only a little more involved than for <filename role=\"special\">hgweb.cgi</" "filename>. First, you must obtain a copy of the script. If you don't have " "one handy, you can download a copy from the master Mercurial repository at " "<ulink url=\"http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi" "\">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1116 msgid "" "With basic configuration out of the way, try to visit <ulink url=\"http://" "myhostname/ myuser/hgwebdir.cgi\">http://myhostname/ myuser/hgwebdir.cgi</" "ulink> in your browser. It should display an empty list of repositories. If " "you get a blank window or error message, try walking through the list of " "potential problems in <xref linkend=\"sec:collab:wtf\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1125 msgid "" "The <filename role=\"special\">hgwebdir.cgi</filename> script relies on an " "external configuration file. By default, it searches for a file named " "<filename role=\"special\">hgweb.config</filename> in the same directory as " "itself. You'll need to create this file, and make it world-readable. The " "format of the file is similar to a Windows <quote>ini</quote> file, as " "understood by Python's <literal>ConfigParser</literal> <citation>web:" "configparser</citation> module." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1135 msgid "" "The easiest way to configure <filename role=\"special\">hgwebdir.cgi</" "filename> is with a section named <literal>collections</literal>. This will " "automatically publish <emphasis>every</emphasis> repository under the " "directories you name. The section should look like this:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1143 msgid "" "Mercurial interprets this by looking at the directory name on the " "<emphasis>right</emphasis> hand side of the <quote><literal>=</literal></" "quote> sign; finding repositories in that directory hierarchy; and using the " "text on the <emphasis>left</emphasis> to strip off matching text from the " "names it will actually list in the web interface. The remaining component of " "a path after this stripping has occurred is called a <quote>virtual path</" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1152 msgid "" "Given the example above, if we have a repository whose local path is " "<filename class=\"directory\">/my/root/this/repo</filename>, the CGI script " "will strip the leading <filename class=\"directory\">/my/root</filename> from " "the name, and publish the repository with a virtual path of <filename class=" "\"directory\">this/repo</filename>. If the base URL for our CGI script is " "<ulink url=\"http://myhostname/ myuser/hgwebdir.cgi\">http://myhostname/ " "myuser/hgwebdir.cgi</ulink>, the complete URL for that repository will be " "<ulink url=\"http://myhostname/ myuser/hgwebdir.cgi/this/repo\">http://" "myhostname/ myuser/hgwebdir.cgi/this/repo</ulink>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1166 msgid "" "If we replace <filename class=\"directory\">/my/root</filename> on the left " "hand side of this example with <filename class=\"directory\">/my</filename>, " "then <filename role=\"special\">hgwebdir.cgi</filename> will only strip off " "<filename class=\"directory\">/my</filename> from the repository name, and " "will give us a virtual path of <filename class=\"directory\">root/this/repo</" "filename> instead of <filename class=\"directory\">this/repo</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1176 msgid "" "The <filename role=\"special\">hgwebdir.cgi</filename> script will " "recursively search each directory listed in the <literal>collections</" "literal> section of its configuration file, but it will <literal>not</" "literal> recurse into the repositories it finds." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1182 msgid "" "The <literal>collections</literal> mechanism makes it easy to publish many " "repositories in a <quote>fire and forget</quote> manner. You only need to " "set up the CGI script and configuration file one time. Afterwards, you can " "publish or unpublish a repository at any time by simply moving it into, or " "out of, the directory hierarchy in which you've configured <filename role=" "\"special\">hgwebdir.cgi</filename> to look." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:1192 msgid "Explicitly specifying which repositories to publish" msgstr "明确指出要发布的版本库" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1195 msgid "" "In addition to the <literal>collections</literal> mechanism, the <filename " "role=\"special\">hgwebdir.cgi</filename> script allows you to publish a " "specific list of repositories. To do so, create a <literal>paths</literal> " "section, with contents of the following form." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1204 msgid "" "In this case, the virtual path (the component that will appear in a URL) is " "on the left hand side of each definition, while the path to the repository is " "on the right. Notice that there does not need to be any relationship between " "the virtual path you choose and the location of a repository in your " "filesystem." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1211 msgid "" "If you wish, you can use both the <literal>collections</literal> and " "<literal>paths</literal> mechanisms simultaneously in a single configuration " "file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><note><para> #: ../en/ch05-collab.xml:1217 msgid "" "If multiple repositories have the same virtual path, <filename role=\"special" "\">hgwebdir.cgi</filename> will not report an error. Instead, it will behave " "unpredictably." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:1226 msgid "Downloading source archives" msgstr "下载源代码档案包" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1228 msgid "" "Mercurial's web interface lets users download an archive of any revision. " "This archive will contain a snapshot of the working directory as of that " "revision, but it will not contain a copy of the repository data." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1233 msgid "" "By default, this feature is not enabled. To enable it, you'll need to add an " "<envar role=\"rc-item-web\">allow_archive</envar> item to the <literal role=" "\"rc-web\">web</literal> section of your <filename role=\"special\">~/.hgrc</" "filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch05-collab.xml:1241 msgid "Web configuration options" msgstr "Web 配置选项" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1243 msgid "" "Mercurial's web interfaces (the <command role=\"hg-cmd\">hg serve</command> " "command, and the <filename role=\"special\">hgweb.cgi</filename> and " "<filename role=\"special\">hgwebdir.cgi</filename> scripts) have a number of " "configuration options that you can set. These belong in a section named " "<literal role=\"rc-web\">web</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1251 msgid "" "<envar role=\"rc-item-web\">allow_archive</envar>: Determines which (if any) " "archive download mechanisms Mercurial supports. If you enable this feature, " "users of the web interface will be able to download an archive of whatever " "revision of a repository they are viewing. To enable the archive feature, " "this item must take the form of a sequence of words drawn from the list below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1260 msgid "" "<literal>bz2</literal>: A <command>tar</command> archive, compressed using " "<literal>bzip2</literal> compression. This has the best compression ratio, " "but uses the most CPU time on the server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1266 msgid "" "<literal>gz</literal>: A <command>tar</command> archive, compressed using " "<literal>gzip</literal> compression." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1270 msgid "" "<literal>zip</literal>: A <command>zip</command> archive, compressed using " "LZW compression. This format has the worst compression ratio, but is widely " "used in the Windows world." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1276 msgid "" "If you provide an empty list, or don't have an <envar role=\"rc-item-web" "\">allow_archive</envar> entry at all, this feature will be disabled. Here " "is an example of how to enable all three supported formats." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1283 msgid "" "<envar role=\"rc-item-web\">allowpull</envar>: Boolean. Determines whether " "the web interface allows remote users to <command role=\"hg-cmd\">hg pull</" "command> and <command role=\"hg-cmd\">hg clone</command> this repository over " "HTTP. If set to <literal>no</literal> or <literal>false</literal>, only the " "<quote>human-oriented</quote> portion of the web interface is available." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1292 msgid "" "<envar role=\"rc-item-web\">contact</envar>: String. A free-form (but " "preferably brief) string identifying the person or group in charge of the " "repository. This often contains the name and email address of a person or " "mailing list. It often makes sense to place this entry in a repository's own " "<filename role=\"special\">.hg/hgrc</filename> file, but it can make sense to " "use in a global <filename role=\"special\">~/.hgrc</filename> if every " "repository has a single maintainer." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1303 msgid "" "<envar role=\"rc-item-web\">maxchanges</envar>: Integer. The default maximum " "number of changesets to display in a single page of output." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1307 msgid "" "<envar role=\"rc-item-web\">maxfiles</envar>: Integer. The default maximum " "number of modified files to display in a single page of output." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1311 msgid "" "<envar role=\"rc-item-web\">stripes</envar>: Integer. If the web interface " "displays alternating <quote>stripes</quote> to make it easier to visually " "align rows when you are looking at a table, this number controls the number " "of rows in each stripe." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1317 msgid "" "<envar role=\"rc-item-web\">style</envar>: Controls the template Mercurial " "uses to display the web interface. Mercurial ships with two web templates, " "named <literal>default</literal> and <literal>gitweb</literal> (the latter is " "much more visually attractive). You can also specify a custom template of " "your own; see <xref linkend=\"chap:template\"/> for details. Here, you can " "see how to enable the <literal>gitweb</literal> style." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1330 msgid "" "<envar role=\"rc-item-web\">templates</envar>: Path. The directory in which " "to search for template files. By default, Mercurial searches in the " "directory in which it was installed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch05-collab.xml:1335 msgid "" "If you are using <filename role=\"special\">hgwebdir.cgi</filename>, you can " "place a few configuration items in a <literal role=\"rc-web\">web</literal> " "section of the <filename role=\"special\">hgweb.config</filename> file " "instead of a <filename role=\"special\">~/.hgrc</filename> file, for " "convenience. These items are <envar role=\"rc-item-web\">motd</envar> and " "<envar role=\"rc-item-web\">style</envar>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:1346 msgid "Options specific to an individual repository" msgstr "针对单个版本库的选项" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1348 msgid "" "A few <literal role=\"rc-web\">web</literal> configuration items ought to be " "placed in a repository's local <filename role=\"special\">.hg/hgrc</" "filename>, rather than a user's or global <filename role=\"special\">~/.hgrc</" "filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1353 msgid "" "<envar role=\"rc-item-web\">description</envar>: String. A free-form (but " "preferably brief) string that describes the contents or purpose of the " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1358 msgid "" "<envar role=\"rc-item-web\">name</envar>: String. The name to use for the " "repository in the web interface. This overrides the default name, which is " "the last component of the repository's path." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:1366 msgid "" "Options specific to the <command role=\"hg-cmd\">hg serve</command> command" msgstr "命令 <command role=\"hg-cmd\">hg serve</command> 的选项" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1369 msgid "" "Some of the items in the <literal role=\"rc-web\">web</literal> section of a " "<filename role=\"special\">~/.hgrc</filename> file are only for use with the " "<command role=\"hg-cmd\">hg serve</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1375 msgid "" "<envar role=\"rc-item-web\">accesslog</envar>: Path. The name of a file into " "which to write an access log. By default, the <command role=\"hg-cmd\">hg " "serve</command> command writes this information to standard output, not to a " "file. Log entries are written in the standard <quote>combined</quote> file " "format used by almost all web servers." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1383 msgid "" "<envar role=\"rc-item-web\">address</envar>: String. The local address on " "which the server should listen for incoming connections. By default, the " "server listens on all addresses." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1388 msgid "" "<envar role=\"rc-item-web\">errorlog</envar>: Path. The name of a file into " "which to write an error log. By default, the <command role=\"hg-cmd\">hg " "serve</command> command writes this information to standard error, not to a " "file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1394 msgid "" "<envar role=\"rc-item-web\">ipv6</envar>: Boolean. Whether to use the IPv6 " "protocol. By default, IPv6 is not used." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch05-collab.xml:1398 msgid "" "<envar role=\"rc-item-web\">port</envar>: Integer. The TCP port number on " "which the server should listen. The default port number used is 8000." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch05-collab.xml:1405 msgid "" "Choosing the right <filename role=\"special\">~/.hgrc</filename> file to add " "<literal role=\"rc-web\">web</literal> items to" msgstr "" "选择正确的 <filename role=\"special\"> ~/.hgrc</filename> 文件增加到 <literal " "role=\"rc-web\">web</literal> 条目" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1409 msgid "" "It is important to remember that a web server like Apache or " "<literal>lighttpd</literal> will run under a user ID that is different to " "yours. CGI scripts run by your server, such as <filename role=\"special" "\">hgweb.cgi</filename>, will usually also run under that user ID." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch05-collab.xml:1416 msgid "" "If you add <literal role=\"rc-web\">web</literal> items to your own personal " "<filename role=\"special\">~/.hgrc</filename> file, CGI scripts won't read " "that <filename role=\"special\">~/.hgrc</filename> file. Those settings will " "thus only affect the behaviour of the <command role=\"hg-cmd\">hg serve</" "command> command when you run it. To cause CGI scripts to see your settings, " "either create a <filename role=\"special\">~/.hgrc</filename> file in the " "home directory of the user ID that runs your web server, or add those " "settings to a system-wide <filename role=\"special\">~/.hgrc</filename> file." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch06-filenames.xml:5 msgid "File names and pattern matching" msgstr "文件名称与模式匹配" #. type: Content of: <book><chapter><para> #: ../en/ch06-filenames.xml:7 msgid "" "Mercurial provides mechanisms that let you work with file names in a " "consistent and expressive way." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:11 msgid "Simple file naming" msgstr "简单文件名称" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:13 msgid "" "Mercurial uses a unified piece of machinery <quote>under the hood</quote> to " "handle file names. Every command behaves uniformly with respect to file " "names. The way in which commands work with file names is as follows." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:18 msgid "" "If you explicitly name real files on the command line, Mercurial works with " "exactly those files, as you would expect. &interaction.filenames.files;" msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:22 msgid "" "When you provide a directory name, Mercurial will interpret this as " "<quote>operate on every file in this directory and its subdirectories</" "quote>. Mercurial traverses the files and subdirectories in a directory in " "alphabetical order. When it encounters a subdirectory, it will traverse that " "subdirectory before continuing with the current directory." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:33 msgid "Running commands without any file names" msgstr "不提供文件名称的执行命令" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:35 msgid "" "Mercurial's commands that work with file names have useful default behaviours " "when you invoke them without providing any file names or patterns. What kind " "of behaviour you should expect depends on what the command does. Here are a " "few rules of thumb you can use to predict what a command is likely to do if " "you don't give it any names to work with." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:42 msgid "" "Most commands will operate on the entire working directory. This is what the " "<command role=\"hg-cmd\">hg add</command> command does, for example." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:46 msgid "" "If the command has effects that are difficult or impossible to reverse, it " "will force you to explicitly provide at least one name or pattern (see " "below). This protects you from accidentally deleting files by running " "<command role=\"hg-cmd\">hg remove</command> with no arguments, for example." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:54 msgid "" "It's easy to work around these default behaviours if they don't suit you. If " "a command normally operates on the whole working directory, you can invoke it " "on just the current directory and its subdirectories by giving it the name " "<quote><filename class=\"directory\">.</filename></quote>." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:62 msgid "" "Along the same lines, some commands normally print file names relative to the " "root of the repository, even if you're invoking them from a subdirectory. " "Such a command will print file names relative to your subdirectory if you " "give it explicit names. Here, we're going to run <command role=\"hg-cmd\">hg " "status</command> from a subdirectory, and get it to operate on the entire " "working directory while printing file names relative to our subdirectory, by " "passing it the output of the <command role=\"hg-cmd\">hg root</command> " "command." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:76 msgid "Telling you what's going on" msgstr "告诉你正在做什么" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:78 msgid "" "The <command role=\"hg-cmd\">hg add</command> example in the preceding " "section illustrates something else that's helpful about Mercurial commands. " "If a command operates on a file that you didn't name explicitly on the " "command line, it will usually print the name of the file, so that you will " "not be surprised what's going on." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:85 msgid "" "The principle here is of <emphasis>least surprise</emphasis>. If you've " "exactly named a file on the command line, there's no point in repeating it " "back at you. If Mercurial is acting on a file <emphasis>implicitly</" "emphasis>, because you provided no names, or a directory, or a pattern (see " "below), it's safest to tell you what it's doing." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:92 msgid "" "For commands that behave this way, you can silence them using the <option " "role=\"hg-opt-global\">-q</option> option. You can also get them to print " "the name of every file, even those you've named explicitly, using the <option " "role=\"hg-opt-global\">-v</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:100 msgid "Using patterns to identify files" msgstr "使用模式标识文件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:102 msgid "" "In addition to working with file and directory names, Mercurial lets you use " "<emphasis>patterns</emphasis> to identify files. Mercurial's pattern " "handling is expressive." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:106 msgid "" "On Unix-like systems (Linux, MacOS, etc.), the job of matching file names to " "patterns normally falls to the shell. On these systems, you must explicitly " "tell Mercurial that a name is a pattern. On Windows, the shell does not " "expand patterns, so Mercurial will automatically identify names that are " "patterns, and expand them for you." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:113 msgid "" "To provide a pattern in place of a regular name on the command line, the " "mechanism is simple:" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:116 msgid "" "That is, a pattern is identified by a short text string that says what kind " "of pattern this is, followed by a colon, followed by the actual pattern." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:120 msgid "" "Mercurial supports two kinds of pattern syntax. The most frequently used is " "called <literal>glob</literal>; this is the same kind of pattern matching " "used by the Unix shell, and should be familiar to Windows command prompt " "users, too." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:125 msgid "" "When Mercurial does automatic pattern matching on Windows, it uses " "<literal>glob</literal> syntax. You can thus omit the <quote><literal>glob:</" "literal></quote> prefix on Windows, but it's safe to use it, too." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:130 msgid "" "The <literal>re</literal> syntax is more powerful; it lets you specify " "patterns using regular expressions, also known as regexps." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:134 msgid "" "By the way, in the examples that follow, notice that I'm careful to wrap all " "of my patterns in quote characters, so that they won't get expanded by the " "shell before Mercurial sees them." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch06-filenames.xml:140 msgid "Shell-style <literal>glob</literal> patterns" msgstr "外壳风格的 <literal>glob</literal> 模式" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:142 msgid "" "This is an overview of the kinds of patterns you can use when you're matching " "on glob patterns." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:145 msgid "" "The <quote><literal>*</literal></quote> character matches any string, within " "a single directory." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:150 msgid "" "The <quote><literal>**</literal></quote> pattern matches any string, and " "crosses directory boundaries. It's not a standard Unix glob token, but it's " "accepted by several popular Unix shells, and is very useful." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:157 msgid "" "The <quote><literal>?</literal></quote> pattern matches any single character." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:162 msgid "" "The <quote><literal>[</literal></quote> character begins a " "<emphasis>character class</emphasis>. This matches any single character " "within the class. The class ends with a <quote><literal>]</literal></quote> " "character. A class may contain multiple <emphasis>range</emphasis>s of the " "form <quote><literal>a-f</literal></quote>, which is shorthand for " "<quote><literal>abcdef</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:172 msgid "" "If the first character after the <quote><literal>[</literal></quote> in a " "character class is a <quote><literal>!</literal></quote>, it " "<emphasis>negates</emphasis> the class, making it match any single character " "not in the class." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:178 msgid "" "A <quote><literal>{</literal></quote> begins a group of subpatterns, where " "the whole group matches if any subpattern in the group matches. The " "<quote><literal>,</literal></quote> character separates subpatterns, and " "<quote><literal>}</literal></quote> ends the group." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch06-filenames.xml:187 msgid "Watch out!" msgstr "千万小心!" # #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch06-filenames.xml:189 msgid "" "Don't forget that if you want to match a pattern in any directory, you should " "not be using the <quote><literal>*</literal></quote> match-any token, as this " "will only match within one directory. Instead, use the <quote><literal>**</" "literal></quote> token. This small example illustrates the difference " "between the two." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch06-filenames.xml:201 msgid "Regular expression matching with <literal>re</literal> patterns" msgstr "使用 <literal>re</literal> 模式的正则表达式匹配" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:204 msgid "" "Mercurial accepts the same regular expression syntax as the Python " "programming language (it uses Python's regexp engine internally). This is " "based on the Perl language's regexp syntax, which is the most popular dialect " "in use (it's also used in Java, for example)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:210 msgid "" "I won't discuss Mercurial's regexp dialect in any detail here, as regexps are " "not often used. Perl-style regexps are in any case already exhaustively " "documented on a multitude of web sites, and in many books. Instead, I will " "focus here on a few things you should know if you find yourself needing to " "use regexps with Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:217 msgid "" "A regexp is matched against an entire file name, relative to the root of the " "repository. In other words, even if you're already in subbdirectory " "<filename class=\"directory\">foo</filename>, if you want to match files " "under this directory, your pattern must start with <quote><literal>foo/</" "literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:224 msgid "" "One thing to note, if you're familiar with Perl-style regexps, is that " "Mercurial's are <emphasis>rooted</emphasis>. That is, a regexp starts " "matching against the beginning of a string; it doesn't look for a match " "anywhere within the string. To match anywhere in a string, start your " "pattern with <quote><literal>.*</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:234 msgid "Filtering files" msgstr "过滤文件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:236 msgid "" "Not only does Mercurial give you a variety of ways to specify files; it lets " "you further winnow those files using <emphasis>filters</emphasis>. Commands " "that work with file names accept two filtering options." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:241 msgid "" "<option role=\"hg-opt-global\">-I</option>, or <option role=\"hg-opt-global" "\">--include</option>, lets you specify a pattern that file names must match " "in order to be processed." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:246 msgid "" "<option role=\"hg-opt-global\">-X</option>, or <option role=\"hg-opt-global" "\">--exclude</option>, gives you a way to <emphasis>avoid</emphasis> " "processing files, if they match this pattern." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:251 msgid "" "You can provide multiple <option role=\"hg-opt-global\">-I</option> and " "<option role=\"hg-opt-global\">-X</option> options on the command line, and " "intermix them as you please. Mercurial interprets the patterns you provide " "using glob syntax by default (but you can use regexps if you need to)." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:258 msgid "" "You can read a <option role=\"hg-opt-global\">-I</option> filter as " "<quote>process only the files that match this filter</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:264 msgid "" "The <option role=\"hg-opt-global\">-X</option> filter is best read as " "<quote>process only the files that don't match this pattern</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:272 msgid "Ignoring unwanted files and directories" msgstr "忽略不需要的文件和目录" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:274 msgid "XXX." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch06-filenames.xml:278 msgid "Case sensitivity" msgstr "大小写敏感性" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:280 msgid "" "If you're working in a mixed development environment that contains both Linux " "(or other Unix) systems and Macs or Windows systems, you should keep in the " "back of your mind the knowledge that they treat the case (<quote>N</quote> " "versus <quote>n</quote>) of file names in incompatible ways. This is not " "very likely to affect you, and it's easy to deal with if it does, but it " "could surprise you if you don't know about it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:289 msgid "" "Operating systems and filesystems differ in the way they handle the " "<emphasis>case</emphasis> of characters in file and directory names. There " "are three common ways to handle case in names." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:294 msgid "" "Completely case insensitive. Uppercase and lowercase versions of a letter " "are treated as identical, both when creating a file and during subsequent " "accesses. This is common on older DOS-based systems." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:299 msgid "" "Case preserving, but insensitive. When a file or directory is created, the " "case of its name is stored, and can be retrieved and displayed by the " "operating system. When an existing file is being looked up, its case is " "ignored. This is the standard arrangement on Windows and MacOS. The names " "<filename>foo</filename> and <filename>FoO</filename> identify the same " "file. This treatment of uppercase and lowercase letters as interchangeable " "is also referred to as <emphasis>case folding</emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch06-filenames.xml:310 msgid "" "Case sensitive. The case of a name is significant at all times. The names " "<filename>foo</filename> and {FoO} identify different files. This is the way " "Linux and Unix systems normally work." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch06-filenames.xml:316 msgid "" "On Unix-like systems, it is possible to have any or all of the above ways of " "handling case in action at once. For example, if you use a USB thumb drive " "formatted with a FAT32 filesystem on a Linux system, Linux will handle names " "on that filesystem in a case preserving, but insensitive, way." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch06-filenames.xml:323 msgid "Safe, portable repository storage" msgstr "安全,可移植的版本库存储" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:325 msgid "" "Mercurial's repository storage mechanism is <emphasis>case safe</emphasis>. " "It translates file names so that they can be safely stored on both case " "sensitive and case insensitive filesystems. This means that you can use " "normal file copying tools to transfer a Mercurial repository onto, for " "example, a USB thumb drive, and safely move that drive and repository back " "and forth between a Mac, a PC running Windows, and a Linux box." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch06-filenames.xml:336 msgid "Detecting case conflicts" msgstr "检测大小写冲突" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:338 msgid "" "When operating in the working directory, Mercurial honours the naming policy " "of the filesystem where the working directory is located. If the filesystem " "is case preserving, but insensitive, Mercurial will treat names that differ " "only in case as the same." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:344 msgid "" "An important aspect of this approach is that it is possible to commit a " "changeset on a case sensitive (typically Linux or Unix) filesystem that will " "cause trouble for users on case insensitive (usually Windows and MacOS) " "users. If a Linux user commits changes to two files, one named " "<filename>myfile.c</filename> and the other named <filename>MyFile.C</" "filename>, they will be stored correctly in the repository. And in the " "working directories of other Linux users, they will be correctly represented " "as separate files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:355 msgid "" "If a Windows or Mac user pulls this change, they will not initially have a " "problem, because Mercurial's repository storage mechanism is case safe. " "However, once they try to <command role=\"hg-cmd\">hg update</command> the " "working directory to that changeset, or <command role=\"hg-cmd\">hg merge</" "command> with that changeset, Mercurial will spot the conflict between the " "two file names that the filesystem would treat as the same, and forbid the " "update or merge from occurring." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch06-filenames.xml:367 msgid "Fixing a case conflict" msgstr "修正大小写冲突" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:369 msgid "" "If you are using Windows or a Mac in a mixed environment where some of your " "collaborators are using Linux or Unix, and Mercurial reports a case folding " "conflict when you try to <command role=\"hg-cmd\">hg update</command> or " "<command role=\"hg-cmd\">hg merge</command>, the procedure to fix the problem " "is simple." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:376 msgid "" "Just find a nearby Linux or Unix box, clone the problem repository onto it, " "and use Mercurial's <command role=\"hg-cmd\">hg rename</command> command to " "change the names of any offending files or directories so that they will no " "longer cause case folding conflicts. Commit this change, <command role=\"hg-" "cmd\">hg pull</command> or <command role=\"hg-cmd\">hg push</command> it " "across to your Windows or MacOS system, and <command role=\"hg-cmd\">hg " "update</command> to the revision with the non-conflicting names." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch06-filenames.xml:386 msgid "" "The changeset with case-conflicting names will remain in your project's " "history, and you still won't be able to <command role=\"hg-cmd\">hg update</" "command> your working directory to that changeset on a Windows or MacOS " "system, but you can continue development unimpeded." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch06-filenames.xml:393 msgid "" "Prior to version 0.9.3, Mercurial did not use a case safe repository storage " "mechanism, and did not detect case folding conflicts. If you are using an " "older version of Mercurial on Windows or MacOS, I strongly recommend that you " "upgrade." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch07-branch.xml:5 msgid "Managing releases and branchy development" msgstr "发布管理与分支开发" #. type: Content of: <book><chapter><para> #: ../en/ch07-branch.xml:7 msgid "" "Mercurial provides several mechanisms for you to manage a project that is " "making progress on multiple fronts at once. To understand these mechanisms, " "let's first take a brief look at a fairly normal software project structure." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch07-branch.xml:12 msgid "" "Many software projects issue periodic <quote>major</quote> releases that " "contain substantial new features. In parallel, they may issue <quote>minor</" "quote> releases. These are usually identical to the major releases off which " "they're based, but with a few bugs fixed." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch07-branch.xml:18 msgid "" "In this chapter, we'll start by talking about how to keep records of project " "milestones such as releases. We'll then continue on to talk about the flow " "of work between different phases of a project, and how Mercurial can help you " "to isolate and manage this work." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:25 msgid "Giving a persistent name to a revision" msgstr "给版本指定一个永久的名称" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:27 msgid "" "Once you decide that you'd like to call a particular revision a " "<quote>release</quote>, it's a good idea to record the identity of that " "revision. This will let you reproduce that release at a later date, for " "whatever purpose you might need at the time (reproducing a bug, porting to a " "new platform, etc). &interaction.tag.init;" msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:34 msgid "" "Mercurial lets you give a permanent name to any revision using the <command " "role=\"hg-cmd\">hg tag</command> command. Not surprisingly, these names are " "called <quote>tags</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:40 msgid "" "A tag is nothing more than a <quote>symbolic name</quote> for a revision. " "Tags exist purely for your convenience, so that you have a handy permanent " "way to refer to a revision; Mercurial doesn't interpret the tag names you use " "in any way. Neither does Mercurial place any restrictions on the name of a " "tag, beyond a few that are necessary to ensure that a tag can be parsed " "unambiguously. A tag name cannot contain any of the following characters:" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch07-branch.xml:49 msgid "Colon (ASCII 58, <quote><literal>:</literal></quote>)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch07-branch.xml:52 msgid "Carriage return (ASCII 13, <quote><literal>\\r</literal></quote>)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch07-branch.xml:55 msgid "Newline (ASCII 10, <quote><literal>\\n</literal></quote>)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:59 msgid "" "You can use the <command role=\"hg-cmd\">hg tags</command> command to display " "the tags present in your repository. In the output, each tagged revision is " "identified first by its name, then by revision number, and finally by the " "unique hash of the revision." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:67 msgid "" "Notice that <literal>tip</literal> is listed in the output of <command role=" "\"hg-cmd\">hg tags</command>. The <literal>tip</literal> tag is a special " "<quote>floating</quote> tag, which always identifies the newest revision in " "the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:73 msgid "" "In the output of the <command role=\"hg-cmd\">hg tags</command> command, tags " "are listed in reverse order, by revision number. This usually means that " "recent tags are listed before older tags. It also means that <literal>tip</" "literal> is always going to be the first tag listed in the output of <command " "role=\"hg-cmd\">hg tags</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:80 msgid "" "When you run <command role=\"hg-cmd\">hg log</command>, if it displays a " "revision that has tags associated with it, it will print those tags." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:86 msgid "" "Any time you need to provide a revision ID to a Mercurial command, the " "command will accept a tag name in its place. Internally, Mercurial will " "translate your tag name into the corresponding revision ID, then use that." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:93 msgid "" "There's no limit on the number of tags you can have in a repository, or on " "the number of tags that a single revision can have. As a practical matter, " "it's not a great idea to have <quote>too many</quote> (a number which will " "vary from project to project), simply because tags are supposed to help you " "to find revisions. If you have lots of tags, the ease of using them to " "identify revisions diminishes rapidly." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:101 msgid "" "For example, if your project has milestones as frequent as every few days, " "it's perfectly reasonable to tag each one of those. But if you have a " "continuous build system that makes sure every revision can be built cleanly, " "you'd be introducing a lot of noise if you were to tag every clean build. " "Instead, you could tag failed builds (on the assumption that they're rare!), " "or simply not use tags to track buildability." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:109 msgid "" "If you want to remove a tag that you no longer want, use <command role=\"hg-" "cmd\">hg tag --remove</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:114 msgid "" "You can also modify a tag at any time, so that it identifies a different " "revision, by simply issuing a new <command role=\"hg-cmd\">hg tag</command> " "command. You'll have to use the <option role=\"hg-opt-tag\">-f</option> " "option to tell Mercurial that you <emphasis>really</emphasis> want to update " "the tag." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:123 msgid "" "There will still be a permanent record of the previous identity of the tag, " "but Mercurial will no longer use it. There's thus no penalty to tagging the " "wrong revision; all you have to do is turn around and tag the correct " "revision once you discover your error." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:129 msgid "" "Mercurial stores tags in a normal revision-controlled file in your " "repository. If you've created any tags, you'll find them in a file named " "<filename role=\"special\">.hgtags</filename>. When you run the <command " "role=\"hg-cmd\">hg tag</command> command, Mercurial modifies this file, then " "automatically commits the change to it. This means that every time you run " "<command role=\"hg-cmd\">hg tag</command>, you'll see a corresponding " "changeset in the output of <command role=\"hg-cmd\">hg log</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch07-branch.xml:142 msgid "Handling tag conflicts during a merge" msgstr "在合并期间处理标签冲突" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:144 msgid "" "You won't often need to care about the <filename role=\"special\">.hgtags</" "filename> file, but it sometimes makes its presence known during a merge. " "The format of the file is simple: it consists of a series of lines. Each " "line starts with a changeset hash, followed by a space, followed by the name " "of a tag." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:151 msgid "" "If you're resolving a conflict in the <filename role=\"special\">.hgtags</" "filename> file during a merge, there's one twist to modifying the <filename " "role=\"special\">.hgtags</filename> file: when Mercurial is parsing the tags " "in a repository, it <emphasis>never</emphasis> reads the working copy of the " "<filename role=\"special\">.hgtags</filename> file. Instead, it reads the " "<emphasis>most recently committed</emphasis> revision of the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:161 msgid "" "An unfortunate consequence of this design is that you can't actually verify " "that your merged <filename role=\"special\">.hgtags</filename> file is " "correct until <emphasis>after</emphasis> you've committed a change. So if " "you find yourself resolving a conflict on <filename role=\"special\">.hgtags</" "filename> during a merge, be sure to run <command role=\"hg-cmd\">hg tags</" "command> after you commit. If it finds an error in the <filename role=" "\"special\">.hgtags</filename> file, it will report the location of the " "error, which you can then fix and commit. You should then run <command role=" "\"hg-cmd\">hg tags</command> again, just to be sure that your fix is correct." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch07-branch.xml:176 msgid "Tags and cloning" msgstr "标签与克隆" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:178 msgid "" "You may have noticed that the <command role=\"hg-cmd\">hg clone</command> " "command has a <option role=\"hg-opt-clone\">-r</option> option that lets you " "clone an exact copy of the repository as of a particular changeset. The new " "clone will not contain any project history that comes after the revision you " "specified. This has an interaction with tags that can surprise the unwary." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:186 msgid "" "Recall that a tag is stored as a revision to the <filename role=\"special\">." "hgtags</filename> file, so that when you create a tag, the changeset in which " "it's recorded necessarily refers to an older changeset. When you run " "<command role=\"hg-cmd\">hg clone -r foo</command> to clone a repository as " "of tag <literal>foo</literal>, the new clone <emphasis>will not contain the " "history that created the tag</emphasis> that you used to clone the " "repository. The result is that you'll get exactly the right subset of the " "project's history in the new repository, but <emphasis>not</emphasis> the tag " "you might have expected." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch07-branch.xml:201 msgid "When permanent tags are too much" msgstr "当永久标签太多的时候" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:203 msgid "" "Since Mercurial's tags are revision controlled and carried around with a " "project's history, everyone you work with will see the tags you create. But " "giving names to revisions has uses beyond simply noting that revision " "<literal>4237e45506ee</literal> is really <literal>v2.0.2</literal>. If " "you're trying to track down a subtle bug, you might want a tag to remind you " "of something like <quote>Anne saw the symptoms with this revision</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch07-branch.xml:213 msgid "" "For cases like this, what you might want to use are <emphasis>local</" "emphasis> tags. You can create a local tag with the <option role=\"hg-opt-tag" "\">-l</option> option to the <command role=\"hg-cmd\">hg tag</command> " "command. This will store the tag in a file called <filename role=\"special" "\">.hg/localtags</filename>. Unlike <filename role=\"special\">.hgtags</" "filename>, <filename role=\"special\">.hg/localtags</filename> is not " "revision controlled. Any tags you create using <option role=\"hg-opt-tag\">-" "l</option> remain strictly local to the repository you're currently working " "in." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:228 msgid "The flow of changes&emdash;big picture vs. little" msgstr "修改流程—宏观与微观" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:230 msgid "" "To return to the outline I sketched at the beginning of a chapter, let's " "think about a project that has multiple concurrent pieces of work under " "development at once." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:234 msgid "" "There might be a push for a new <quote>main</quote> release; a new minor " "bugfix release to the last main release; and an unexpected <quote>hot fix</" "quote> to an old release that is now in maintenance mode." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:239 msgid "" "The usual way people refer to these different concurrent directions of " "development is as <quote>branches</quote>. However, we've already seen " "numerous times that Mercurial treats <emphasis>all of history</emphasis> as a " "series of branches and merges. Really, what we have here is two ideas that " "are peripherally related, but which happen to share a name." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch07-branch.xml:246 msgid "" "<quote>Big picture</quote> branches represent the sweep of a project's " "evolution; people give them names, and talk about them in conversation." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch07-branch.xml:250 msgid "" "<quote>Little picture</quote> branches are artefacts of the day-to-day " "activity of developing and merging changes. They expose the narrative of how " "the code was developed." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:258 msgid "Managing big-picture branches in repositories" msgstr "在版本库中管理分支" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:260 msgid "" "The easiest way to isolate a <quote>big picture</quote> branch in Mercurial " "is in a dedicated repository. If you have an existing shared " "repository&emdash;let's call it <literal>myproject</literal>&emdash;that " "reaches a <quote>1.0</quote> milestone, you can start to prepare for future " "maintenance releases on top of version 1.0 by tagging the revision from which " "you prepared the 1.0 release." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:270 msgid "" "You can then clone a new shared <literal>myproject-1.0.1</literal> repository " "as of that tag." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:276 msgid "" "Afterwards, if someone needs to work on a bug fix that ought to go into an " "upcoming 1.0.1 minor release, they clone the <literal>myproject-1.0.1</" "literal> repository, make their changes, and push them back." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:283 msgid "" "Meanwhile, development for the next major release can continue, isolated and " "unabated, in the <literal>myproject</literal> repository." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:291 msgid "Don't repeat yourself: merging across branches" msgstr "不要重复劳动:在分支间合并" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:293 msgid "" "In many cases, if you have a bug to fix on a maintenance branch, the chances " "are good that the bug exists on your project's main branch (and possibly " "other maintenance branches, too). It's a rare developer who wants to fix the " "same bug multiple times, so let's look at a few ways that Mercurial can help " "you to manage these bugfixes without duplicating your work." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:301 msgid "" "In the simplest instance, all you need to do is pull changes from your " "maintenance branch into your local clone of the target branch." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:307 msgid "" "You'll then need to merge the heads of the two branches, and push back to the " "main branch." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:314 msgid "Naming branches within one repository" msgstr "版本库中的命名分支" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:316 msgid "" "In most instances, isolating branches in repositories is the right approach. " "Its simplicity makes it easy to understand; and so it's hard to make " "mistakes. There's a one-to-one relationship between branches you're working " "in and directories on your system. This lets you use normal (non-Mercurial-" "aware) tools to work on files within a branch/repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:323 msgid "" "If you're more in the <quote>power user</quote> category (<emphasis>and</" "emphasis> your collaborators are too), there is an alternative way of " "handling branches that you can consider. I've already mentioned the human-" "level distinction between <quote>small picture</quote> and <quote>big " "picture</quote> branches. While Mercurial works with multiple <quote>small " "picture</quote> branches in a repository all the time (for example after you " "pull changes in, but before you merge them), it can <emphasis>also</emphasis> " "work with multiple <quote>big picture</quote> branches." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:334 msgid "" "The key to working this way is that Mercurial lets you assign a persistent " "<emphasis>name</emphasis> to a branch. There always exists a branch named " "<literal>default</literal>. Even before you start naming branches yourself, " "you can find traces of the <literal>default</literal> branch if you look for " "them." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:341 msgid "" "As an example, when you run the <command role=\"hg-cmd\">hg commit</command> " "command, and it pops up your editor so that you can enter a commit message, " "look for a line that contains the text <quote><literal>HG: branch default</" "literal></quote> at the bottom. This is telling you that your commit will " "occur on the branch named <literal>default</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:348 msgid "" "To start working with named branches, use the <command role=\"hg-cmd\">hg " "branches</command> command. This command lists the named branches already " "present in your repository, telling you which changeset is the tip of each." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:355 msgid "" "Since you haven't created any named branches yet, the only one that exists is " "<literal>default</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:358 msgid "" "To find out what the <quote>current</quote> branch is, run the <command role=" "\"hg-cmd\">hg branch</command> command, giving it no arguments. This tells " "you what branch the parent of the current changeset is on." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:365 msgid "" "To create a new branch, run the <command role=\"hg-cmd\">hg branch</command> " "command again. This time, give it one argument: the name of the branch you " "want to create." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:371 msgid "" "After you've created a branch, you might wonder what effect the <command role=" "\"hg-cmd\">hg branch</command> command has had. What do the <command role=" "\"hg-cmd\">hg status</command> and <command role=\"hg-cmd\">hg tip</command> " "commands report?" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:378 msgid "" "Nothing has changed in the working directory, and there's been no new history " "created. As this suggests, running the <command role=\"hg-cmd\">hg branch</" "command> command has no permanent effect; it only tells Mercurial what branch " "name to use the <emphasis>next</emphasis> time you commit a changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:385 msgid "" "When you commit a change, Mercurial records the name of the branch on which " "you committed. Once you've switched from the <literal>default</literal> " "branch to another and committed, you'll see the name of the new branch show " "up in the output of <command role=\"hg-cmd\">hg log</command>, <command role=" "\"hg-cmd\">hg tip</command>, and other commands that display the same kind of " "output." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:395 msgid "" "The <command role=\"hg-cmd\">hg log</command>-like commands will print the " "branch name of every changeset that's not on the <literal>default</literal> " "branch. As a result, if you never use named branches, you'll never see this " "information." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:400 msgid "" "Once you've named a branch and committed a change with that name, every " "subsequent commit that descends from that change will inherit the same branch " "name. You can change the name of a branch at any time, using the <command " "role=\"hg-cmd\">hg branch</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:408 msgid "" "In practice, this is something you won't do very often, as branch names tend " "to have fairly long lifetimes. (This isn't a rule, just an observation.)" msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:414 msgid "Dealing with multiple named branches in a repository" msgstr "在版本库中处理多个命名分支" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:417 msgid "" "If you have more than one named branch in a repository, Mercurial will " "remember the branch that your working directory on when you start a command " "like <command role=\"hg-cmd\">hg update</command> or <command role=\"hg-cmd" "\">hg pull -u</command>. It will update the working directory to the tip of " "this branch, no matter what the <quote>repo-wide</quote> tip is. To update " "to a revision that's on a different named branch, you may need to use the " "<option role=\"hg-opt-update\">-C</option> option to <command role=\"hg-cmd" "\">hg update</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:427 msgid "" "This behaviour is a little subtle, so let's see it in action. First, let's " "remind ourselves what branch we're currently on, and what branches are in our " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:433 msgid "" "We're on the <literal>bar</literal> branch, but there also exists an older " "<command role=\"hg-cmd\">hg foo</command> branch." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:437 msgid "" "We can <command role=\"hg-cmd\">hg update</command> back and forth between " "the tips of the <literal>foo</literal> and <literal>bar</literal> branches " "without needing to use the <option role=\"hg-opt-update\">-C</option> option, " "because this only involves going backwards and forwards linearly through our " "change history." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:446 msgid "" "If we go back to the <literal>foo</literal> branch and then run <command role=" "\"hg-cmd\">hg update</command>, it will keep us on <literal>foo</literal>, " "not move us to the tip of <literal>bar</literal>." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:453 msgid "" "Committing a new change on the <literal>foo</literal> branch introduces a new " "head." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:460 msgid "Branch names and merging" msgstr "分支名称与合并" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:462 msgid "" "As you've probably noticed, merges in Mercurial are not symmetrical. Let's " "say our repository has two heads, 17 and 23. If I <command role=\"hg-cmd" "\">hg update</command> to 17 and then <command role=\"hg-cmd\">hg merge</" "command> with 23, Mercurial records 17 as the first parent of the merge, and " "23 as the second. Whereas if I <command role=\"hg-cmd\">hg update</command> " "to 23 and then <command role=\"hg-cmd\">hg merge</command> with 17, it " "records 23 as the first parent, and 17 as the second." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:472 msgid "" "This affects Mercurial's choice of branch name when you merge. After a " "merge, Mercurial will retain the branch name of the first parent when you " "commit the result of the merge. If your first parent's branch name is " "<literal>foo</literal>, and you merge with <literal>bar</literal>, the branch " "name will still be <literal>foo</literal> after you merge." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:479 msgid "" "It's not unusual for a repository to contain multiple heads, each with the " "same branch name. Let's say I'm working on the <literal>foo</literal> " "branch, and so are you. We commit different changes; I pull your changes; I " "now have two heads, each claiming to be on the <literal>foo</literal> " "branch. The result of a merge will be a single head on the <literal>foo</" "literal> branch, as you might hope." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:487 msgid "" "But if I'm working on the <literal>bar</literal> branch, and I merge work " "from the <literal>foo</literal> branch, the result will remain on the " "<literal>bar</literal> branch." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:493 msgid "" "To give a more concrete example, if I'm working on the <literal>bleeding-" "edge</literal> branch, and I want to bring in the latest fixes from the " "<literal>stable</literal> branch, Mercurial will choose the <quote>right</" "quote> (<literal>bleeding-edge</literal>) branch name when I pull and merge " "from <literal>stable</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch07-branch.xml:502 msgid "Branch naming is generally useful" msgstr "分支名称通常都很有用" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:504 msgid "" "You shouldn't think of named branches as applicable only to situations where " "you have multiple long-lived branches cohabiting in a single repository. " "They're very useful even in the one-branch-per-repository case." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:509 msgid "" "In the simplest case, giving a name to each branch gives you a permanent " "record of which branch a changeset originated on. This gives you more " "context when you're trying to follow the history of a long-lived branchy " "project." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch07-branch.xml:514 msgid "" "If you're working with shared repositories, you can set up a <literal role=" "\"hook\">pretxnchangegroup</literal> hook on each that will block incoming " "changes that have the <quote>wrong</quote> branch name. This provides a " "simple, but effective, defence against people accidentally pushing changes " "from a <quote>bleeding edge</quote> branch to a <quote>stable</quote> " "branch. Such a hook might look like this inside the shared repo's <filename " "role=\"special\"> /.hgrc</filename>." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch08-undo.xml:5 msgid "Finding and fixing mistakes" msgstr "查找和修改错误" #. type: Content of: <book><chapter><para> #: ../en/ch08-undo.xml:7 msgid "" "To err might be human, but to really handle the consequences well takes a top-" "notch revision control system. In this chapter, we'll discuss some of the " "techniques you can use when you find that a problem has crept into your " "project. Mercurial has some highly capable features that will help you to " "isolate the sources of problems, and to handle them appropriately." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:15 msgid "Erasing local history" msgstr "销毁本地历史" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:18 msgid "The accidental commit" msgstr "意外的提交" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:20 msgid "" "I have the occasional but persistent problem of typing rather more quickly " "than I can think, which sometimes results in me committing a changeset that " "is either incomplete or plain wrong. In my case, the usual kind of " "incomplete changeset is one in which I've created a new source file, but " "forgotten to <command role=\"hg-cmd\">hg add</command> it. A <quote>plain " "wrong</quote> changeset is not as common, but no less annoying." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:31 msgid "Rolling back a transaction" msgstr "回滚一个事务" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:33 msgid "" "In <xref linkend=\"sec:concepts:txn\"/>, I mentioned that Mercurial treats " "each modification of a repository as a <emphasis>transaction</emphasis>. " "Every time you commit a changeset or pull changes from another repository, " "Mercurial remembers what you did. You can undo, or <emphasis>roll back</" "emphasis>, exactly one of these actions using the <command role=\"hg-cmd\">hg " "rollback</command> command. (See <xref linkend=\"sec:undo:rollback-after-push" "\"/> for an important caveat about the use of this command.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:43 msgid "" "Here's a mistake that I often find myself making: committing a change in " "which I've created a new file, but forgotten to <command role=\"hg-cmd\">hg " "add</command> it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:50 msgid "" "Looking at the output of <command role=\"hg-cmd\">hg status</command> after " "the commit immediately confirms the error." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:56 msgid "" "The commit captured the changes to the file <filename>a</filename>, but not " "the new file <filename>b</filename>. If I were to push this changeset to a " "repository that I shared with a colleague, the chances are high that " "something in <filename>a</filename> would refer to <filename>b</filename>, " "which would not be present in their repository when they pulled my changes. " "I would thus become the object of some indignation." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:65 msgid "" "However, luck is with me&emdash;I've caught my error before I pushed the " "changeset. I use the <command role=\"hg-cmd\">hg rollback</command> command, " "and Mercurial makes that last changeset vanish." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:72 msgid "" "Notice that the changeset is no longer present in the repository's history, " "and the working directory once again thinks that the file <filename>a</" "filename> is modified. The commit and rollback have left the working " "directory exactly as it was prior to the commit; the changeset has been " "completely erased. I can now safely <command role=\"hg-cmd\">hg add</" "command> the file <filename>b</filename>, and rerun my commit." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:85 msgid "The erroneous pull" msgstr "错误的抓取" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:87 msgid "" "It's common practice with Mercurial to maintain separate development branches " "of a project in different repositories. Your development team might have one " "shared repository for your project's <quote>0.9</quote> release, and another, " "containing different changes, for the <quote>1.0</quote> release." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:94 msgid "" "Given this, you can imagine that the consequences could be messy if you had a " "local <quote>0.9</quote> repository, and accidentally pulled changes from the " "shared <quote>1.0</quote> repository into it. At worst, you could be paying " "insufficient attention, and push those changes into the shared <quote>0.9</" "quote> tree, confusing your entire team (but don't worry, we'll return to " "this horror scenario later). However, it's more likely that you'll notice " "immediately, because Mercurial will display the URL it's pulling from, or you " "will see it pull a suspiciously large number of changes into the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:106 msgid "" "The <command role=\"hg-cmd\">hg rollback</command> command will work nicely " "to expunge all of the changesets that you just pulled. Mercurial groups all " "changes from one <command role=\"hg-cmd\">hg pull</command> into a single " "transaction, so one <command role=\"hg-cmd\">hg rollback</command> is all you " "need to undo this mistake." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:115 msgid "Rolling back is useless once you've pushed" msgstr "当完成推送后,回滚是无效的" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:117 msgid "" "The value of the <command role=\"hg-cmd\">hg rollback</command> command drops " "to zero once you've pushed your changes to another repository. Rolling back " "a change makes it disappear entirely, but <emphasis>only</emphasis> in the " "repository in which you perform the <command role=\"hg-cmd\">hg rollback</" "command>. Because a rollback eliminates history, there's no way for the " "disappearance of a change to propagate between repositories." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:126 msgid "" "If you've pushed a change to another repository&emdash;particularly if it's a " "shared repository&emdash;it has essentially <quote>escaped into the wild,</" "quote> and you'll have to recover from your mistake in a different way. What " "will happen if you push a changeset somewhere, then roll it back, then pull " "from the repository you pushed to, is that the changeset will reappear in " "your repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:135 msgid "" "(If you absolutely know for sure that the change you want to roll back is the " "most recent change in the repository that you pushed to, <emphasis>and</" "emphasis> you know that nobody else could have pulled it from that " "repository, you can roll back the changeset there, too, but you really should " "really not rely on this working reliably. If you do this, sooner or later a " "change really will make it into a repository that you don't directly control " "(or have forgotten about), and come back to bite you.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:147 msgid "You can only roll back once" msgstr "你只能回滚一次" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:149 msgid "" "Mercurial stores exactly one transaction in its transaction log; that " "transaction is the most recent one that occurred in the repository. This " "means that you can only roll back one transaction. If you expect to be able " "to roll back one transaction, then its predecessor, this is not the behaviour " "you will get." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:158 msgid "" "Once you've rolled back one transaction in a repository, you can't roll back " "again in that repository until you perform another commit or pull." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:165 msgid "Reverting the mistaken change" msgstr "撤销错误的修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:167 msgid "" "If you make a modification to a file, and decide that you really didn't want " "to change the file at all, and you haven't yet committed your changes, the " "<command role=\"hg-cmd\">hg revert</command> command is the one you'll need. " "It looks at the changeset that's the parent of the working directory, and " "restores the contents of the file to their state as of that changeset. " "(That's a long-winded way of saying that, in the normal case, it undoes your " "modifications.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:176 msgid "" "Let's illustrate how the <command role=\"hg-cmd\">hg revert</command> command " "works with yet another small example. We'll begin by modifying a file that " "Mercurial is already tracking." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:183 msgid "" "If we don't want that change, we can simply <command role=\"hg-cmd\">hg " "revert</command> the file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:189 msgid "" "The <command role=\"hg-cmd\">hg revert</command> command provides us with an " "extra degree of safety by saving our modified file with a <filename>.orig</" "filename> extension." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:196 msgid "" "Here is a summary of the cases that the <command role=\"hg-cmd\">hg revert</" "command> command can deal with. We will describe each of these in more " "detail in the section that follows." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:201 msgid "If you modify a file, it will restore the file to its unmodified state." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:204 msgid "" "If you <command role=\"hg-cmd\">hg add</command> a file, it will undo the " "<quote>added</quote> state of the file, but leave the file itself untouched." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:208 msgid "" "If you delete a file without telling Mercurial, it will restore the file to " "its unmodified contents." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:211 msgid "" "If you use the <command role=\"hg-cmd\">hg remove</command> command to remove " "a file, it will undo the <quote>removed</quote> state of the file, and " "restore the file to its unmodified contents." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:218 msgid "File management errors" msgstr "文件管理错误" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:220 msgid "" "The <command role=\"hg-cmd\">hg revert</command> command is useful for more " "than just modified files. It lets you reverse the results of all of " "Mercurial's file management commands&emdash;<command role=\"hg-cmd\">hg add</" "command>, <command role=\"hg-cmd\">hg remove</command>, and so on." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:226 msgid "" "If you <command role=\"hg-cmd\">hg add</command> a file, then decide that in " "fact you don't want Mercurial to track it, use <command role=\"hg-cmd\">hg " "revert</command> to undo the add. Don't worry; Mercurial will not modify the " "file in any way. It will just <quote>unmark</quote> the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:234 msgid "" "Similarly, if you ask Mercurial to <command role=\"hg-cmd\">hg remove</" "command> a file, you can use <command role=\"hg-cmd\">hg revert</command> to " "restore it to the contents it had as of the parent of the working directory. " "&interaction.daily.revert.remove; This works just as well for a file that you " "deleted by hand, without telling Mercurial (recall that in Mercurial " "terminology, this kind of file is called <quote>missing</quote>)." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:245 msgid "" "If you revert a <command role=\"hg-cmd\">hg copy</command>, the copied-to " "file remains in your working directory afterwards, untracked. Since a copy " "doesn't affect the copied-from file in any way, Mercurial doesn't do anything " "with the copied-from file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch08-undo.xml:254 msgid "A slightly special case: reverting a rename" msgstr "一个稍微特别的案例:撤销改名" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:256 msgid "" "If you <command role=\"hg-cmd\">hg rename</command> a file, there is one " "small detail that you should remember. When you <command role=\"hg-cmd\">hg " "revert</command> a rename, it's not enough to provide the name of the renamed-" "to file, as you can see here." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:264 msgid "" "As you can see from the output of <command role=\"hg-cmd\">hg status</" "command>, the renamed-to file is no longer identified as added, but the " "renamed-<emphasis>from</emphasis> file is still removed! This is counter-" "intuitive (at least to me), but at least it's easy to deal with." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:273 msgid "" "So remember, to revert a <command role=\"hg-cmd\">hg rename</command>, you " "must provide <emphasis>both</emphasis> the source and destination names." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:278 msgid "% TODO: the output doesn't look like it will be removed!" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:281 msgid "" "(By the way, if you rename a file, then modify the renamed-to file, then " "revert both components of the rename, when Mercurial restores the file that " "was removed as part of the rename, it will be unmodified. If you need the " "modifications in the renamed-to file to show up in the renamed-from file, " "don't forget to copy them over.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:288 msgid "" "These fiddly aspects of reverting a rename arguably constitute a small bug in " "Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:295 msgid "Dealing with committed changes" msgstr "处理已经提交的修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:297 msgid "" "Consider a case where you have committed a change $a$, and another change $b$ " "on top of it; you then realise that change $a$ was incorrect. Mercurial lets " "you <quote>back out</quote> an entire changeset automatically, and building " "blocks that let you reverse part of a changeset by hand." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:303 msgid "" "Before you read this section, here's something to keep in mind: the <command " "role=\"hg-cmd\">hg backout</command> command undoes changes by " "<emphasis>adding</emphasis> history, not by modifying or erasing it. It's " "the right tool to use if you're fixing bugs, but not if you're trying to undo " "some change that has catastrophic consequences. To deal with those, see " "<xref linkend=\"sec:undo:aaaiiieee\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:312 msgid "Backing out a changeset" msgstr "恢复一个修改集" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:314 msgid "" "The <command role=\"hg-cmd\">hg backout</command> command lets you " "<quote>undo</quote> the effects of an entire changeset in an automated " "fashion. Because Mercurial's history is immutable, this command " "<emphasis>does not</emphasis> get rid of the changeset you want to undo. " "Instead, it creates a new changeset that <emphasis>reverses</emphasis> the " "effect of the to-be-undone changeset." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:323 msgid "" "The operation of the <command role=\"hg-cmd\">hg backout</command> command is " "a little intricate, so let's illustrate it with some examples. First, we'll " "create a repository with some simple changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:330 msgid "" "The <command role=\"hg-cmd\">hg backout</command> command takes a single " "changeset ID as its argument; this is the changeset to back out. Normally, " "<command role=\"hg-cmd\">hg backout</command> will drop you into a text " "editor to write a commit message, so you can record why you're backing the " "change out. In this example, we provide a commit message on the command line " "using the <option role=\"hg-opt-backout\">-m</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:341 msgid "Backing out the tip changeset" msgstr "恢复顶点修改集" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:343 msgid "We're going to start by backing out the last changeset we committed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:348 msgid "" "You can see that the second line from <filename>myfile</filename> is no " "longer present. Taking a look at the output of <command role=\"hg-cmd\">hg " "log</command> gives us an idea of what the <command role=\"hg-cmd\">hg " "backout</command> command has done. &interaction.backout.simple.log; Notice " "that the new changeset that <command role=\"hg-cmd\">hg backout</command> has " "created is a child of the changeset we backed out. It's easier to see this " "in <xref linkend=\"fig:undo:backout\"/>, which presents a graphical view of " "the change history. As you can see, the history is nice and linear." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch08-undo.xml:361 ../en/ch08-undo.xml:473 msgid "" "Backing out a change using the <command role=\"hg-cmd\">hg backout</command> " "command" msgstr "使用 <command role=\"hg-cmd\">hg backout</command> 恢复一个修改" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch08-undo.xml:364 msgid "<imageobject><imagedata fileref=\"figs/undo-simple.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:371 msgid "Backing out a non-tip change" msgstr "恢复非顶点的修改" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:373 msgid "" "If you want to back out a change other than the last one you committed, pass " "the <option role=\"hg-opt-backout\">--merge</option> option to the <command " "role=\"hg-cmd\">hg backout</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:380 msgid "" "This makes backing out any changeset a <quote>one-shot</quote> operation " "that's usually simple and fast." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:386 msgid "" "If you take a look at the contents of <filename>myfile</filename> after the " "backout finishes, you'll see that the first and third changes are present, " "but not the second." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:393 msgid "" "As the graphical history in <xref linkend=\"fig:undo:backout-non-tip\"/> " "illustrates, Mercurial actually commits <emphasis>two</emphasis> changes in " "this kind of situation (the box-shaped nodes are the ones that Mercurial " "commits automatically). Before Mercurial begins the backout process, it " "first remembers what the current parent of the working directory is. It then " "backs out the target changeset, and commits that as a changeset. Finally, it " "merges back to the previous parent of the working directory, and commits the " "result of the merge." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:404 msgid "" "% TODO: to me it looks like mercurial doesn't commit the second merge " "automatically!" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch08-undo.xml:408 msgid "" "Automated backout of a non-tip change using the <command role=\"hg-cmd\">hg " "backout</command> command" msgstr "使用 <command role=\"hg-cmd\">hg backout</command> 自动恢复非顶点的修改" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch08-undo.xml:411 msgid "" "<imageobject><imagedata fileref=\"figs/undo-non-tip.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:416 msgid "" "The result is that you end up <quote>back where you were</quote>, only with " "some extra history that undoes the effect of the changeset you wanted to back " "out." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch08-undo.xml:421 msgid "Always use the <option role=\"hg-opt-backout\">--merge</option> option" msgstr "始终使用选项 <option role=\"hg-opt-backout\">--merge</option>" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch08-undo.xml:424 msgid "" "In fact, since the <option role=\"hg-opt-backout\">--merge</option> option " "will do the <quote>right thing</quote> whether or not the changeset you're " "backing out is the tip (i.e. it won't try to merge if it's backing out the " "tip, since there's no need), you should <emphasis>always</emphasis> use this " "option when you run the <command role=\"hg-cmd\">hg backout</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:435 msgid "Gaining more control of the backout process" msgstr "在恢复处理中获得更多控制" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:437 msgid "" "While I've recommended that you always use the <option role=\"hg-opt-backout" "\">--merge</option> option when backing out a change, the <command role=\"hg-" "cmd\">hg backout</command> command lets you decide how to merge a backout " "changeset. Taking control of the backout process by hand is something you " "will rarely need to do, but it can be useful to understand what the <command " "role=\"hg-cmd\">hg backout</command> command is doing for you automatically. " "To illustrate this, let's clone our first repository, but omit the backout " "change that it contains." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:450 msgid "" "As with our earlier example, We'll commit a third changeset, then back out " "its parent, and see what happens." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:456 msgid "" "Our new changeset is again a descendant of the changeset we backout out; it's " "thus a new head, <emphasis>not</emphasis> a descendant of the changeset that " "was the tip. The <command role=\"hg-cmd\">hg backout</command> command was " "quite explicit in telling us this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:464 msgid "" "Again, it's easier to see what has happened by looking at a graph of the " "revision history, in <xref linkend=\"fig:undo:backout-manual\"/>. This makes " "it clear that when we use <command role=\"hg-cmd\">hg backout</command> to " "back out a change other than the tip, Mercurial adds a new head to the " "repository (the change it committed is box-shaped)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch08-undo.xml:476 msgid "<imageobject><imagedata fileref=\"figs/undo-manual.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:481 msgid "" "After the <command role=\"hg-cmd\">hg backout</command> command has " "completed, it leaves the new <quote>backout</quote> changeset as the parent " "of the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:488 msgid "Now we have two isolated sets of changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:492 msgid "" "Let's think about what we expect to see as the contents of <filename>myfile</" "filename> now. The first change should be present, because we've never " "backed it out. The second change should be missing, as that's the change we " "backed out. Since the history graph shows the third change as a separate " "head, we <emphasis>don't</emphasis> expect to see the third change present in " "<filename>myfile</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:502 msgid "" "To get the third change back into the file, we just do a normal merge of our " "two heads." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:507 msgid "" "Afterwards, the graphical history of our repository looks like <xref linkend=" "\"fig:undo:backout-manual-merge\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch08-undo.xml:512 msgid "Manually merging a backout change" msgstr "手工合并恢复修改" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch08-undo.xml:514 msgid "" "<imageobject><imagedata fileref=\"figs/undo-manual-merge.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:521 msgid "Why <command role=\"hg-cmd\">hg backout</command> works as it does" msgstr "<command role=\"hg-cmd\">hg backout</command> 的内幕" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:524 msgid "" "Here's a brief description of how the <command role=\"hg-cmd\">hg backout</" "command> command works." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:527 msgid "" "It ensures that the working directory is <quote>clean</quote>, i.e. that the " "output of <command role=\"hg-cmd\">hg status</command> would be empty." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:531 msgid "" "It remembers the current parent of the working directory. Let's call this " "changeset <literal>orig</literal>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:535 msgid "" "It does the equivalent of a <command role=\"hg-cmd\">hg update</command> to " "sync the working directory to the changeset you want to back out. Let's call " "this changeset <literal>backout</literal>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:540 msgid "" "It finds the parent of that changeset. Let's call that changeset " "<literal>parent</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:543 msgid "" "For each file that the <literal>backout</literal> changeset affected, it does " "the equivalent of a <command role=\"hg-cmd\">hg revert -r parent</command> on " "that file, to restore it to the contents it had before that changeset was " "committed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:550 msgid "" "It commits the result as a new changeset. This changeset has " "<literal>backout</literal> as its parent." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:554 msgid "" "If you specify <option role=\"hg-opt-backout\">--merge</option> on the " "command line, it merges with <literal>orig</literal>, and commits the result " "of the merge." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:560 msgid "" "An alternative way to implement the <command role=\"hg-cmd\">hg backout</" "command> command would be to <command role=\"hg-cmd\">hg export</command> the " "to-be-backed-out changeset as a diff, then use the <option role=\"cmd-opt-" "patch\">--reverse</option> option to the <command>patch</command> command to " "reverse the effect of the change without fiddling with the working " "directory. This sounds much simpler, but it would not work nearly as well." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:570 msgid "" "The reason that <command role=\"hg-cmd\">hg backout</command> does an update, " "a commit, a merge, and another commit is to give the merge machinery the best " "chance to do a good job when dealing with all the changes <emphasis>between</" "emphasis> the change you're backing out and the current tip." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:577 msgid "" "If you're backing out a changeset that's 100 revisions back in your project's " "history, the chances that the <command>patch</command> command will be able " "to apply a reverse diff cleanly are not good, because intervening changes are " "likely to have <quote>broken the context</quote> that <command>patch</" "command> uses to determine whether it can apply a patch (if this sounds like " "gibberish, see <xref linkend=\"sec:mq:patch\"/> for a discussion of the " "<command>patch</command> command). Also, Mercurial's merge machinery will " "handle files and directories being renamed, permission changes, and " "modifications to binary files, none of which <command>patch</command> can " "deal with." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:594 msgid "Changes that should never have been" msgstr "不该发生的修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:596 msgid "" "Most of the time, the <command role=\"hg-cmd\">hg backout</command> command " "is exactly what you need if you want to undo the effects of a change. It " "leaves a permanent record of exactly what you did, both when committing the " "original changeset and when you cleaned up after it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:602 msgid "" "On rare occasions, though, you may find that you've committed a change that " "really should not be present in the repository at all. For example, it would " "be very unusual, and usually considered a mistake, to commit a software " "project's object files as well as its source files. Object files have almost " "no intrinsic value, and they're <emphasis>big</emphasis>, so they increase " "the size of the repository and the amount of time it takes to clone or pull " "changes." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:611 msgid "" "Before I discuss the options that you have if you commit a <quote>brown paper " "bag</quote> change (the kind that's so bad that you want to pull a brown " "paper bag over your head), let me first discuss some approaches that probably " "won't work." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:616 msgid "" "Since Mercurial treats history as accumulative&emdash;every change builds on " "top of all changes that preceded it&emdash;you generally can't just make " "disastrous changes disappear. The one exception is when you've just " "committed a change, and it hasn't been pushed or pulled into another " "repository. That's when you can safely use the <command role=\"hg-cmd\">hg " "rollback</command> command, as I detailed in <xref linkend=\"sec:undo:rollback" "\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:625 msgid "" "After you've pushed a bad change to another repository, you <emphasis>could</" "emphasis> still use <command role=\"hg-cmd\">hg rollback</command> to make " "your local copy of the change disappear, but it won't have the consequences " "you want. The change will still be present in the remote repository, so it " "will reappear in your local repository the next time you pull." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:633 msgid "" "If a situation like this arises, and you know which repositories your bad " "change has propagated into, you can <emphasis>try</emphasis> to get rid of " "the changeefrom <emphasis>every</emphasis> one of those repositories. This " "is, of course, not a satisfactory solution: if you miss even a single " "repository while you're expunging, the change is still <quote>in the wild</" "quote>, and could propagate further." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:641 msgid "" "If you've committed one or more changes <emphasis>after</emphasis> the change " "that you'd like to see disappear, your options are further reduced. Mercurial " "doesn't provide a way to <quote>punch a hole</quote> in history, leaving " "changesets intact." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:647 msgid "" "XXX This needs filling out. The <literal>hg-replay</literal> script in the " "<literal>examples</literal> directory works, but doesn't handle merge " "changesets. Kind of an important omission." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:653 msgid "Protect yourself from <quote>escaped</quote> changes" msgstr "使用<quote>校验</quote>修改来保护你自己" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:656 msgid "" "If you've committed some changes to your local repository and they've been " "pushed or pulled somewhere else, this isn't necessarily a disaster. You can " "protect yourself ahead of time against some classes of bad changeset. This " "is particularly easy if your team usually pulls changes from a central " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:663 msgid "" "By configuring some hooks on that repository to validate incoming changesets " "(see chapter <xref linkend=\"chap:hook\"/>), you can automatically prevent " "some kinds of bad changeset from being pushed to the central repository at " "all. With such a configuration in place, some kinds of bad changeset will " "naturally tend to <quote>die out</quote> because they can't propagate into " "the central repository. Better yet, this happens without any need for " "explicit intervention." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:673 msgid "" "For instance, an incoming change hook that verifies that a changeset will " "actually compile can prevent people from inadvertantly <quote>breaking the " "build</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:680 msgid "Finding the source of a bug" msgstr "查找问题的根源" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:682 msgid "" "While it's all very well to be able to back out a changeset that introduced a " "bug, this requires that you know which changeset to back out. Mercurial " "provides an invaluable command, called <command role=\"hg-cmd\">hg bisect</" "command>, that helps you to automate this process and accomplish it very " "efficiently." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:689 msgid "" "The idea behind the <command role=\"hg-cmd\">hg bisect</command> command is " "that a changeset has introduced some change of behaviour that you can " "identify with a simple binary test. You don't know which piece of code " "introduced the change, but you know how to test for the presence of the bug. " "The <command role=\"hg-cmd\">hg bisect</command> command uses your test to " "direct its search for the changeset that introduced the code that caused the " "bug." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:698 msgid "" "Here are a few scenarios to help you understand how you might apply this " "command." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:701 msgid "" "The most recent version of your software has a bug that you remember wasn't " "present a few weeks ago, but you don't know when it was introduced. Here, " "your binary test checks for the presence of that bug." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:706 msgid "" "You fixed a bug in a rush, and now it's time to close the entry in your " "team's bug database. The bug database requires a changeset ID when you close " "an entry, but you don't remember which changeset you fixed the bug in. Once " "again, your binary test checks for the presence of the bug." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:713 msgid "" "Your software works correctly, but runs 15% slower than the last time you " "measured it. You want to know which changeset introduced the performance " "regression. In this case, your binary test measures the performance of your " "software, to see whether it's <quote>fast</quote> or <quote>slow</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:720 msgid "" "The sizes of the components of your project that you ship exploded recently, " "and you suspect that something changed in the way you build your project." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:725 msgid "" "From these examples, it should be clear that the <command role=\"hg-cmd\">hg " "bisect</command> command is not useful only for finding the sources of bugs. " "You can use it to find any <quote>emergent property</quote> of a repository " "(anything that you can't find from a simple text search of the files in the " "tree) for which you can write a binary test." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:732 msgid "" "We'll introduce a little bit of terminology here, just to make it clear which " "parts of the search process are your responsibility, and which are " "Mercurial's. A <emphasis>test</emphasis> is something that <emphasis>you</" "emphasis> run when <command role=\"hg-cmd\">hg bisect</command> chooses a " "changeset. A <emphasis>probe</emphasis> is what <command role=\"hg-cmd\">hg " "bisect</command> runs to tell whether a revision is good. Finally, we'll use " "the word <quote>bisect</quote>, as both a noun and a verb, to stand in for " "the phrase <quote>search using the <command role=\"hg-cmd\">hg bisect</" "command> command</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:745 msgid "" "One simple way to automate the searching process would be simply to probe " "every changeset. However, this scales poorly. If it took ten minutes to " "test a single changeset, and you had 10,000 changesets in your repository, " "the exhaustive approach would take on average 35 <emphasis>days</emphasis> to " "find the changeset that introduced a bug. Even if you knew that the bug was " "introduced by one of the last 500 changesets, and limited your search to " "those, you'd still be looking at over 40 hours to find the changeset that " "introduced your bug." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:755 msgid "" "What the <command role=\"hg-cmd\">hg bisect</command> command does is use its " "knowledge of the <quote>shape</quote> of your project's revision history to " "perform a search in time proportional to the <emphasis>logarithm</emphasis> " "of the number of changesets to check (the kind of search it performs is " "called a dichotomic search). With this approach, searching through 10,000 " "changesets will take less than three hours, even at ten minutes per test (the " "search will require about 14 tests). Limit your search to the last hundred " "changesets, and it will take only about an hour (roughly seven tests)." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch08-undo.xml:766 msgid "" "The <command role=\"hg-cmd\">hg bisect</command> command is aware of the " "<quote>branchy</quote> nature of a Mercurial project's revision history, so " "it has no problems dealing with branches, merges, or multiple heads in a " "repository. It can prune entire branches of history with a single probe, " "which is how it operates so efficiently." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:774 msgid "Using the <command role=\"hg-cmd\">hg bisect</command> command" msgstr "使用命令 <command role=\"hg-cmd\">hg bisect</command>" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:777 msgid "" "Here's an example of <command role=\"hg-cmd\">hg bisect</command> in action." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch08-undo.xml:781 msgid "" "In versions 0.9.5 and earlier of Mercurial, <command role=\"hg-cmd\">hg " "bisect</command> was not a core command: it was distributed with Mercurial as " "an extension. This section describes the built-in command, not the old " "extension." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:788 msgid "" "Now let's create a repository, so that we can try out the <command role=\"hg-" "cmd\">hg bisect</command> command in isolation." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:794 msgid "" "We'll simulate a project that has a bug in it in a simple-minded way: create " "trivial changes in a loop, and nominate one specific change that will have " "the <quote>bug</quote>. This loop creates 35 changesets, each adding a " "single file to the repository. We'll represent our <quote>bug</quote> with a " "file that contains the text <quote>i have a gub</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:804 msgid "" "The next thing that we'd like to do is figure out how to use the <command " "role=\"hg-cmd\">hg bisect</command> command. We can use Mercurial's normal " "built-in help mechanism for this." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:811 msgid "" "The <command role=\"hg-cmd\">hg bisect</command> command works in steps. " "Each step proceeds as follows." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:814 msgid "You run your binary test." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:816 msgid "" "If the test succeeded, you tell <command role=\"hg-cmd\">hg bisect</command> " "by running the <command role=\"hg-cmd\">hg bisect good</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:821 msgid "" "If it failed, run the <command role=\"hg-cmd\">hg bisect bad</command> " "command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:825 msgid "" "The command uses your information to decide which changeset to test next." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><orderedlist><listitem><para> #: ../en/ch08-undo.xml:828 msgid "" "It updates the working directory to that changeset, and the process begins " "again." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:831 msgid "" "The process ends when <command role=\"hg-cmd\">hg bisect</command> identifies " "a unique changeset that marks the point where your test transitioned from " "<quote>succeeding</quote> to <quote>failing</quote>." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:836 msgid "" "To start the search, we must run the <command role=\"hg-cmd\">hg bisect --" "reset</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:841 msgid "" "In our case, the binary test we use is simple: we check to see if any file in " "the repository contains the string <quote>i have a gub</quote>. If it does, " "this changeset contains the change that <quote>caused the bug</quote>. By " "convention, a changeset that has the property we're searching for is " "<quote>bad</quote>, while one that doesn't is <quote>good</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:849 msgid "" "Most of the time, the revision to which the working directory is synced " "(usually the tip) already exhibits the problem introduced by the buggy " "change, so we'll mark it as <quote>bad</quote>." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:856 msgid "" "Our next task is to nominate a changeset that we know <emphasis>doesn't</" "emphasis> have the bug; the <command role=\"hg-cmd\">hg bisect</command> " "command will <quote>bracket</quote> its search between the first pair of good " "and bad changesets. In our case, we know that revision 10 didn't have the " "bug. (I'll have more words about choosing the first <quote>good</quote> " "changeset later.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:866 msgid "Notice that this command printed some output." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:868 msgid "" "It told us how many changesets it must consider before it can identify the " "one that introduced the bug, and how many tests that will require." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:872 msgid "" "It updated the working directory to the next changeset to test, and told us " "which changeset it's testing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:877 msgid "" "We now run our test in the working directory. We use the <command>grep</" "command> command to see if our <quote>bad</quote> file is present in the " "working directory. If it is, this revision is bad; if not, this revision is " "good. &interaction.bisect.search.step1;" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:883 msgid "" "This test looks like a perfect candidate for automation, so let's turn it " "into a shell function." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:887 msgid "" "We can now run an entire test step with a single command, <literal>mytest</" "literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:892 msgid "A few more invocations of our canned test step command, and we're done." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:897 msgid "" "Even though we had 40 changesets to search through, the <command role=\"hg-cmd" "\">hg bisect</command> command let us find the changeset that introduced our " "<quote>bug</quote> with only five tests. Because the number of tests that " "the <command role=\"hg-cmd\">hg bisect</command> command performs grows " "logarithmically with the number of changesets to search, the advantage that " "it has over the <quote>brute force</quote> search approach increases with " "every changeset you add." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:908 msgid "Cleaning up after your search" msgstr "搜索后的清理" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:910 msgid "" "When you're finished using the <command role=\"hg-cmd\">hg bisect</command> " "command in a repository, you can use the <command role=\"hg-cmd\">hg bisect " "reset</command> command to drop the information it was using to drive your " "search. The command doesn't use much space, so it doesn't matter if you " "forget to run this command. However, <command role=\"hg-cmd\">hg bisect</" "command> won't let you start a new search in that repository until you do a " "<command role=\"hg-cmd\">hg bisect reset</command>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch08-undo.xml:925 msgid "Tips for finding bugs effectively" msgstr "有效查找问题的技巧" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:928 msgid "Give consistent input" msgstr "给出一致的输入" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:930 msgid "" "The <command role=\"hg-cmd\">hg bisect</command> command requires that you " "correctly report the result of every test you perform. If you tell it that a " "test failed when it really succeeded, it <emphasis>might</emphasis> be able " "to detect the inconsistency. If it can identify an inconsistency in your " "reports, it will tell you that a particular changeset is both good and bad. " "However, it can't do this perfectly; it's about as likely to report the wrong " "changeset as the source of the bug." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:942 msgid "Automate as much as possible" msgstr "尽量自动" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:944 msgid "" "When I started using the <command role=\"hg-cmd\">hg bisect</command> " "command, I tried a few times to run my tests by hand, on the command line. " "This is an approach that I, at least, am not suited to. After a few tries, I " "found that I was making enough mistakes that I was having to restart my " "searches several times before finally getting correct results." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:952 msgid "" "My initial problems with driving the <command role=\"hg-cmd\">hg bisect</" "command> command by hand occurred even with simple searches on small " "repositories; if the problem you're looking for is more subtle, or the number " "of tests that <command role=\"hg-cmd\">hg bisect</command> must perform " "increases, the likelihood of operator error ruining the search is much " "higher. Once I started automating my tests, I had much better results." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:961 msgid "The key to automated testing is twofold:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:963 msgid "always test for the same symptom, and" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:965 msgid "" "always feed consistent input to the <command role=\"hg-cmd\">hg bisect</" "command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:968 msgid "" "In my tutorial example above, the <command>grep</command> command tests for " "the symptom, and the <literal>if</literal> statement takes the result of this " "check and ensures that we always feed the same input to the <command role=" "\"hg-cmd\">hg bisect</command> command. The <literal>mytest</literal> " "function marries these together in a reproducible way, so that every test is " "uniform and consistent." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:978 msgid "Check your results" msgstr "检查你的结果" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:980 msgid "" "Because the output of a <command role=\"hg-cmd\">hg bisect</command> search " "is only as good as the input you give it, don't take the changeset it reports " "as the absolute truth. A simple way to cross-check its report is to manually " "run your test at each of the following changesets:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:986 msgid "" "The changeset that it reports as the first bad revision. Your test should " "still report this as bad." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:990 msgid "" "The parent of that changeset (either parent, if it's a merge). Your test " "should report this changeset as good." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch08-undo.xml:994 msgid "" "A child of that changeset. Your test should report this changeset as bad." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:1000 msgid "Beware interference between bugs" msgstr "谨防问题之间的冲突" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1002 msgid "" "It's possible that your search for one bug could be disrupted by the presence " "of another. For example, let's say your software crashes at revision 100, " "and worked correctly at revision 50. Unknown to you, someone else introduced " "a different crashing bug at revision 60, and fixed it at revision 80. This " "could distort your results in one of several ways." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1010 msgid "" "It is possible that this other bug completely <quote>masks</quote> yours, " "which is to say that it occurs before your bug has a chance to manifest " "itself. If you can't avoid that other bug (for example, it prevents your " "project from building), and so can't tell whether your bug is present in a " "particular changeset, the <command role=\"hg-cmd\">hg bisect</command> " "command cannot help you directly. Instead, you can mark a changeset as " "untested by running <command role=\"hg-cmd\">hg bisect --skip</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1020 msgid "" "A different problem could arise if your test for a bug's presence is not " "specific enough. If you check for <quote>my program crashes</quote>, then " "both your crashing bug and an unrelated crashing bug that masks it will look " "like the same thing, and mislead <command role=\"hg-cmd\">hg bisect</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1027 msgid "" "Another useful situation in which to use <command role=\"hg-cmd\">hg bisect --" "skip</command> is if you can't test a revision because your project was in a " "broken and hence untestable state at that revision, perhaps because someone " "checked in a change that prevented the project from building." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch08-undo.xml:1036 msgid "Bracket your search lazily" msgstr "减少你的查找工作" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1038 msgid "" "Choosing the first <quote>good</quote> and <quote>bad</quote> changesets that " "will mark the end points of your search is often easy, but it bears a little " "discussion nevertheless. From the perspective of <command role=\"hg-cmd\">hg " "bisect</command>, the <quote>newest</quote> changeset is conventionally " "<quote>bad</quote>, and the older changeset is <quote>good</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1046 msgid "" "If you're having trouble remembering when a suitable <quote>good</quote> " "change was, so that you can tell <command role=\"hg-cmd\">hg bisect</" "command>, you could do worse than testing changesets at random. Just " "remember to eliminate contenders that can't possibly exhibit the bug (perhaps " "because the feature with the bug isn't present yet) and those where another " "problem masks the bug (as I discussed above)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch08-undo.xml:1055 msgid "" "Even if you end up <quote>early</quote> by thousands of changesets or months " "of history, you will only add a handful of tests to the total number that " "<command role=\"hg-cmd\">hg bisect</command> must perform, thanks to its " "logarithmic behaviour." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch09-hook.xml:5 msgid "Handling repository events with hooks" msgstr "使用钩子处理版本库事件" #. type: Content of: <book><chapter><para> #: ../en/ch09-hook.xml:7 msgid "" "Mercurial offers a powerful mechanism to let you perform automated actions in " "response to events that occur in a repository. In some cases, you can even " "control Mercurial's response to those events." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch09-hook.xml:12 msgid "" "The name Mercurial uses for one of these actions is a <emphasis>hook</" "emphasis>. Hooks are called <quote>triggers</quote> in some revision control " "systems, but the two names refer to the same idea." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:18 msgid "An overview of hooks in Mercurial" msgstr "Mercurial 钩子概述" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:20 msgid "" "Here is a brief list of the hooks that Mercurial supports. We will revisit " "each of these hooks in more detail later, in <xref linkend=\"sec:hook:ref\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:25 msgid "" "<literal role=\"hook\">changegroup</literal>: This is run after a group of " "changesets has been brought into the repository from elsewhere." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:29 msgid "" "<literal role=\"hook\">commit</literal>: This is run after a new changeset " "has been created in the local repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:33 msgid "" "<literal role=\"hook\">incoming</literal>: This is run once for each new " "changeset that is brought into the repository from elsewhere. Notice the " "difference from <literal role=\"hook\">changegroup</literal>, which is run " "once per <emphasis>group</emphasis> of changesets brought in." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:40 msgid "" "<literal role=\"hook\">outgoing</literal>: This is run after a group of " "changesets has been transmitted from this repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:44 msgid "" "<literal role=\"hook\">prechangegroup</literal>: This is run before starting " "to bring a group of changesets into the repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:49 msgid "" "<literal role=\"hook\">precommit</literal>: Controlling. This is run before " "starting a commit." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:53 msgid "" "<literal role=\"hook\">preoutgoing</literal>: Controlling. This is run before " "starting to transmit a group of changesets from this repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:58 msgid "" "<literal role=\"hook\">pretag</literal>: Controlling. This is run before " "creating a tag." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:62 msgid "" "<literal role=\"hook\">pretxnchangegroup</literal>: Controlling. This is run " "after a group of changesets has been brought into the local repository from " "another, but before the transaction completes that will make the changes " "permanent in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:70 msgid "" "<literal role=\"hook\">pretxncommit</literal>: Controlling. This is run after " "a new changeset has been created in the local repository, but before the " "transaction completes that will make it permanent." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:76 msgid "" "<literal role=\"hook\">preupdate</literal>: Controlling. This is run before " "starting an update or merge of the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:81 msgid "" "<literal role=\"hook\">tag</literal>: This is run after a tag is created." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:85 msgid "" "<literal role=\"hook\">update</literal>: This is run after an update or merge " "of the working directory has finished." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:90 msgid "" "Each of the hooks whose description begins with the word <quote>Controlling</" "quote> has the ability to determine whether an activity can proceed. If the " "hook succeeds, the activity may proceed; if it fails, the activity is either " "not permitted or undone, depending on the hook." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:99 msgid "Hooks and security" msgstr "钩子与安全性" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:102 msgid "Hooks are run with your privileges" msgstr "钩子以你的特权执行" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:104 msgid "" "When you run a Mercurial command in a repository, and the command causes a " "hook to run, that hook runs on <emphasis>your</emphasis> system, under " "<emphasis>your</emphasis> user account, with <emphasis>your</emphasis> " "privilege level. Since hooks are arbitrary pieces of executable code, you " "should treat them with an appropriate level of suspicion. Do not install a " "hook unless you are confident that you know who created it and what it does." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:115 msgid "" "In some cases, you may be exposed to hooks that you did not install " "yourself. If you work with Mercurial on an unfamiliar system, Mercurial will " "run hooks defined in that system's global <filename role=\"special\">~/.hgrc</" "filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:122 msgid "" "If you are working with a repository owned by another user, Mercurial can run " "hooks defined in that user's repository, but it will still run them as " "<quote>you</quote>. For example, if you <command role=\"hg-cmd\">hg pull</" "command> from that repository, and its <filename role=\"special\">.hg/hgrc</" "filename> defines a local <literal role=\"hook\">outgoing</literal> hook, " "that hook will run under your user account, even though you don't own that " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch09-hook.xml:134 msgid "" "This only applies if you are pulling from a repository on a local or network " "filesystem. If you're pulling over http or ssh, any <literal role=\"hook" "\">outgoing</literal> hook will run under whatever account is executing the " "server process, on the server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:142 msgid "" "XXX To see what hooks are defined in a repository, use the <command role=\"hg-" "cmd\">hg config hooks</command> command. If you are working in one " "repository, but talking to another that you do not own (e.g. using <command " "role=\"hg-cmd\">hg pull</command> or <command role=\"hg-cmd\">hg incoming</" "command>), remember that it is the other repository's hooks you should be " "checking, not your own." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:153 msgid "Hooks do not propagate" msgstr "钩子不会传播" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:155 msgid "" "In Mercurial, hooks are not revision controlled, and do not propagate when " "you clone, or pull from, a repository. The reason for this is simple: a hook " "is a completely arbitrary piece of executable code. It runs under your user " "identity, with your privilege level, on your machine." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:162 msgid "" "It would be extremely reckless for any distributed revision control system to " "implement revision-controlled hooks, as this would offer an easily " "exploitable way to subvert the accounts of users of the revision control " "system." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:168 msgid "" "Since Mercurial does not propagate hooks, if you are collaborating with other " "people on a common project, you should not assume that they are using the " "same Mercurial hooks as you are, or that theirs are correctly configured. " "You should document the hooks you expect people to use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:175 msgid "" "In a corporate intranet, this is somewhat easier to control, as you can for " "example provide a <quote>standard</quote> installation of Mercurial on an NFS " "filesystem, and use a site-wide <filename role=\"special\">~/.hgrc</filename> " "file to define hooks that all users will see. However, this too has its " "limits; see below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:184 msgid "Hooks can be overridden" msgstr "钩子可以被覆盖" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:186 msgid "" "Mercurial allows you to override a hook definition by redefining the hook. " "You can disable it by setting its value to the empty string, or change its " "behaviour as you wish." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:191 msgid "" "If you deploy a system- or site-wide <filename role=\"special\">~/.hgrc</" "filename> file that defines some hooks, you should thus understand that your " "users can disable or override those hooks." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:199 msgid "Ensuring that critical hooks are run" msgstr "确保关键钩子的执行" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:201 msgid "" "Sometimes you may want to enforce a policy that you do not want others to be " "able to work around. For example, you may have a requirement that every " "changeset must pass a rigorous set of tests. Defining this requirement via a " "hook in a site-wide <filename role=\"special\">~/.hgrc</filename> won't work " "for remote users on laptops, and of course local users can subvert it at will " "by overriding the hook." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:210 msgid "" "Instead, you can set up your policies for use of Mercurial so that people are " "expected to propagate changes through a well-known <quote>canonical</quote> " "server that you have locked down and configured appropriately." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:216 msgid "" "One way to do this is via a combination of social engineering and " "technology. Set up a restricted-access account; users can push changes over " "the network to repositories managed by this account, but they cannot log into " "the account and run normal shell commands. In this scenario, a user can " "commit a changeset that contains any old garbage they want." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:225 msgid "" "When someone pushes a changeset to the server that everyone pulls from, the " "server will test the changeset before it accepts it as permanent, and reject " "it if it fails to pass the test suite. If people only pull changes from this " "filtering server, it will serve to ensure that all changes that people pull " "have been automatically vetted." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:236 msgid "Care with <literal>pretxn</literal> hooks in a shared-access repository" msgstr "在共享版本库中注意 <literal>pretxn</literal> 钩子" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:239 msgid "" "If you want to use hooks to do some automated work in a repository that a " "number of people have shared access to, you need to be careful in how you do " "this." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:244 msgid "" "Mercurial only locks a repository when it is writing to the repository, and " "only the parts of Mercurial that write to the repository pay attention to " "locks. Write locks are necessary to prevent multiple simultaneous writers " "from scribbling on each other's work, corrupting the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:251 msgid "" "Because Mercurial is careful with the order in which it reads and writes " "data, it does not need to acquire a lock when it wants to read data from the " "repository. The parts of Mercurial that read from the repository never pay " "attention to locks. This lockless reading scheme greatly increases " "performance and concurrency." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:259 msgid "" "With great performance comes a trade-off, though, one which has the potential " "to cause you trouble unless you're aware of it. To describe this requires a " "little detail about how Mercurial adds changesets to a repository and reads " "those changes." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:266 msgid "" "When Mercurial <emphasis>writes</emphasis> metadata, it writes it straight " "into the destination file. It writes file data first, then manifest data " "(which contains pointers to the new file data), then changelog data (which " "contains pointers to the new manifest data). Before the first write to each " "file, it stores a record of where the end of the file was in its transaction " "log. If the transaction must be rolled back, Mercurial simply truncates each " "file back to the size it was before the transaction began." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:277 msgid "" "When Mercurial <emphasis>reads</emphasis> metadata, it reads the changelog " "first, then everything else. Since a reader will only access parts of the " "manifest or file metadata that it can see in the changelog, it can never see " "partially written data." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:283 msgid "" "Some controlling hooks (<literal role=\"hook\">pretxncommit</literal> and " "<literal role=\"hook\">pretxnchangegroup</literal>) run when a transaction is " "almost complete. All of the metadata has been written, but Mercurial can " "still roll the transaction back and cause the newly-written data to disappear." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:291 msgid "" "If one of these hooks runs for long, it opens a window of time during which a " "reader can see the metadata for changesets that are not yet permanent, and " "should not be thought of as <quote>really there</quote>. The longer the hook " "runs, the longer that window is open." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:299 msgid "The problem illustrated" msgstr "问题的演示" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:301 msgid "" "In principle, a good use for the <literal role=\"hook\">pretxnchangegroup</" "literal> hook would be to automatically build and test incoming changes " "before they are accepted into a central repository. This could let you " "guarantee that nobody can push changes to this repository that <quote>break " "the build</quote>. But if a client can pull changes while they're being " "tested, the usefulness of the test is zero; an unsuspecting someone can pull " "untested changes, potentially breaking their build." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:312 msgid "" "The safest technological answer to this challenge is to set up such a " "<quote>gatekeeper</quote> repository as <emphasis>unidirectional</emphasis>. " "Let it take changes pushed in from the outside, but do not allow anyone to " "pull changes from it (use the <literal role=\"hook\">preoutgoing</literal> " "hook to lock it down). Configure a <literal role=\"hook\">changegroup</" "literal> hook so that if a build or test succeeds, the hook will push the new " "changes out to another repository that people <emphasis>can</emphasis> pull " "from." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:324 msgid "" "In practice, putting a centralised bottleneck like this in place is not often " "a good idea, and transaction visibility has nothing to do with the problem. " "As the size of a project&emdash;and the time it takes to build and " "test&emdash;grows, you rapidly run into a wall with this <quote>try before " "you buy</quote> approach, where you have more changesets to test than time in " "which to deal with them. The inevitable result is frustration on the part of " "all involved." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:335 msgid "" "An approach that scales better is to get people to build and test before they " "push, then run automated builds and tests centrally <emphasis>after</" "emphasis> a push, to be sure all is well. The advantage of this approach is " "that it does not impose a limit on the rate at which the repository can " "accept changes." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:346 msgid "A short tutorial on using hooks" msgstr "使用钩子的简短指南" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:348 msgid "" "It is easy to write a Mercurial hook. Let's start with a hook that runs when " "you finish a <command role=\"hg-cmd\">hg commit</command>, and simply prints " "the hash of the changeset you just created. The hook is called <literal role=" "\"hook\">commit</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:355 msgid "All hooks follow the pattern in this example." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:359 msgid "" "You add an entry to the <literal role=\"rc-hooks\">hooks</literal> section of " "your <filename role=\"special\">~/.hgrc</filename>. On the left is the name " "of the event to trigger on; on the right is the action to take. As you can " "see, you can run an arbitrary shell command in a hook. Mercurial passes " "extra information to the hook using environment variables (look for " "<envar>HG_NODE</envar> in the example)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:369 msgid "Performing multiple actions per event" msgstr "每个事件执行多个操作" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:371 msgid "" "Quite often, you will want to define more than one hook for a particular kind " "of event, as shown below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:376 msgid "" "Mercurial lets you do this by adding an <emphasis>extension</emphasis> to the " "end of a hook's name. You extend a hook's name by giving the name of the " "hook, followed by a full stop (the <quote><literal>.</literal></quote> " "character), followed by some more text of your choosing. For example, " "Mercurial will run both <literal>commit.foo</literal> and <literal>commit." "bar</literal> when the <literal>commit</literal> event occurs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:387 msgid "" "To give a well-defined order of execution when there are multiple hooks " "defined for an event, Mercurial sorts hooks by extension, and executes the " "hook commands in this sorted order. In the above example, it will execute " "<literal>commit.bar</literal> before <literal>commit.foo</literal>, and " "<literal>commit</literal> before both." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:396 msgid "" "It is a good idea to use a somewhat descriptive extension when you define a " "new hook. This will help you to remember what the hook was for. If the hook " "fails, you'll get an error message that contains the hook name and extension, " "so using a descriptive extension could give you an immediate hint as to why " "the hook failed (see <xref linkend=\"sec:hook:perm\"/> for an example)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:407 msgid "Controlling whether an activity can proceed" msgstr "控制处理的活动" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:409 msgid "" "In our earlier examples, we used the <literal role=\"hook\">commit</literal> " "hook, which is run after a commit has completed. This is one of several " "Mercurial hooks that run after an activity finishes. Such hooks have no way " "of influencing the activity itself." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:416 msgid "" "Mercurial defines a number of events that occur before an activity starts; or " "after it starts, but before it finishes. Hooks that trigger on these events " "have the added ability to choose whether the activity can continue, or will " "abort." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:422 msgid "" "The <literal role=\"hook\">pretxncommit</literal> hook runs after a commit " "has all but completed. In other words, the metadata representing the " "changeset has been written out to disk, but the transaction has not yet been " "allowed to complete. The <literal role=\"hook\">pretxncommit</literal> hook " "has the ability to decide whether the transaction can complete, or must be " "rolled back." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:431 msgid "" "If the <literal role=\"hook\">pretxncommit</literal> hook exits with a status " "code of zero, the transaction is allowed to complete; the commit finishes; " "and the <literal role=\"hook\">commit</literal> hook is run. If the <literal " "role=\"hook\">pretxncommit</literal> hook exits with a non-zero status code, " "the transaction is rolled back; the metadata representing the changeset is " "erased; and the <literal role=\"hook\">commit</literal> hook is not run." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:443 msgid "" "The hook in the example above checks that a commit comment contains a bug " "ID. If it does, the commit can complete. If not, the commit is rolled back." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:451 msgid "Writing your own hooks" msgstr "编写钩子" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:453 msgid "" "When you are writing a hook, you might find it useful to run Mercurial either " "with the <option role=\"hg-opt-global\">-v</option> option, or the <envar " "role=\"rc-item-ui\">verbose</envar> config item set to <quote>true</quote>. " "When you do so, Mercurial will print a message before it calls each hook." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:462 msgid "Choosing how your hook should run" msgstr "选择钩子的执行方式" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:464 msgid "" "You can write a hook either as a normal program&emdash;typically a shell " "script&emdash;or as a Python function that is executed within the Mercurial " "process." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:469 msgid "" "Writing a hook as an external program has the advantage that it requires no " "knowledge of Mercurial's internals. You can call normal Mercurial commands " "to get any added information you need. The trade-off is that external hooks " "are slower than in-process hooks." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:476 msgid "" "An in-process Python hook has complete access to the Mercurial API, and does " "not <quote>shell out</quote> to another process, so it is inherently faster " "than an external hook. It is also easier to obtain much of the information " "that a hook requires by using the Mercurial API than by running Mercurial " "commands." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:484 msgid "" "If you are comfortable with Python, or require high performance, writing your " "hooks in Python may be a good choice. However, when you have a " "straightforward hook to write and you don't need to care about performance " "(probably the majority of hooks), a shell script is perfectly fine." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:493 msgid "Hook parameters" msgstr "钩子的参数" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:495 msgid "" "Mercurial calls each hook with a set of well-defined parameters. In Python, " "a parameter is passed as a keyword argument to your hook function. For an " "external program, a parameter is passed as an environment variable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:501 msgid "" "Whether your hook is written in Python or as a shell script, the hook-" "specific parameter names and values will be the same. A boolean parameter " "will be represented as a boolean value in Python, but as the number 1 (for " "<quote>true</quote>) or 0 (for <quote>false</quote>) as an environment " "variable for an external hook. If a hook parameter is named <literal>foo</" "literal>, the keyword argument for a Python hook will also be named " "<literal>foo</literal>, while the environment variable for an external hook " "will be named <literal>HG_FOO</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:515 msgid "Hook return values and activity control" msgstr "钩子的返回值与活动控制" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:517 msgid "" "A hook that executes successfully must exit with a status of zero if " "external, or return boolean <quote>false</quote> if in-process. Failure is " "indicated with a non-zero exit status from an external hook, or an in-process " "hook returning boolean <quote>true</quote>. If an in-process hook raises an " "exception, the hook is considered to have failed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:525 msgid "" "For a hook that controls whether an activity can proceed, zero/false means " "<quote>allow</quote>, while non-zero/true/exception means <quote>deny</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:532 msgid "Writing an external hook" msgstr "编写外部钩子" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:534 msgid "" "When you define an external hook in your <filename role=\"special\">~/.hgrc</" "filename> and the hook is run, its value is passed to your shell, which " "interprets it. This means that you can use normal shell constructs in the " "body of the hook." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:541 msgid "" "An executable hook is always run with its current directory set to a " "repository's root directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:545 msgid "" "Each hook parameter is passed in as an environment variable; the name is " "upper-cased, and prefixed with the string <quote><literal>HG_</literal></" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:550 msgid "" "With the exception of hook parameters, Mercurial does not set or modify any " "environment variables when running a hook. This is useful to remember if you " "are writing a site-wide hook that may be run by a number of different users " "with differing environment variables set. In multi-user situations, you " "should not rely on environment variables being set to the values you have in " "your environment when testing the hook." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:561 msgid "Telling Mercurial to use an in-process hook" msgstr "让 Mercurial 使用进程内钩子" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:563 msgid "" "The <filename role=\"special\">~/.hgrc</filename> syntax for defining an in-" "process hook is slightly different than for an executable hook. The value of " "the hook must start with the text <quote><literal>python:</literal></quote>, " "and continue with the fully-qualified name of a callable object to use as the " "hook's value." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:571 msgid "" "The module in which a hook lives is automatically imported when a hook is " "run. So long as you have the module name and <envar>PYTHONPATH</envar> " "right, it should <quote>just work</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:577 msgid "" "The following <filename role=\"special\">~/.hgrc</filename> example snippet " "illustrates the syntax and meaning of the notions we just described." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:583 msgid "" "When Mercurial runs the <literal>commit.example</literal> hook, it imports " "<literal>mymodule.submodule</literal>, looks for the callable object named " "<literal>myhook</literal>, and calls it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:591 msgid "Writing an in-process hook" msgstr "编写进程内钩子" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:593 msgid "" "The simplest in-process hook does nothing, but illustrates the basic shape of " "the hook API:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:598 msgid "" "The first argument to a Python hook is always a <literal role=\"py-mod-" "mercurial.ui\">ui</literal> object. The second is a repository object; at " "the moment, it is always an instance of <literal role=\"py-mod-mercurial." "localrepo\">localrepository</literal>. Following these two arguments are " "other keyword arguments. Which ones are passed in depends on the hook being " "called, but a hook can ignore arguments it doesn't care about by dropping " "them into a keyword argument dict, as with <literal>**kwargs</literal> above." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:613 msgid "Some hook examples" msgstr "钩子样例" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:616 msgid "Writing meaningful commit messages" msgstr "编写有意义的提交日志" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:618 msgid "" "It's hard to imagine a useful commit message being very short. The simple " "<literal role=\"hook\">pretxncommit</literal> hook of the example below will " "prevent you from committing a changeset with a message that is less than ten " "bytes long." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:628 msgid "Checking for trailing whitespace" msgstr "检查行尾空格" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:630 msgid "" "An interesting use of a commit-related hook is to help you to write cleaner " "code. A simple example of <quote>cleaner code</quote> is the dictum that a " "change should not add any new lines of text that contain <quote>trailing " "whitespace</quote>. Trailing whitespace is a series of space and tab " "characters at the end of a line of text. In most cases, trailing whitespace " "is unnecessary, invisible noise, but it is occasionally problematic, and " "people often prefer to get rid of it." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:641 msgid "" "You can use either the <literal role=\"hook\">precommit</literal> or <literal " "role=\"hook\">pretxncommit</literal> hook to tell whether you have a trailing " "whitespace problem. If you use the <literal role=\"hook\">precommit</" "literal> hook, the hook will not know which files you are committing, so it " "will have to check every modified file in the repository for trailing white " "space. If you want to commit a change to just the file <filename>foo</" "filename>, but the file <filename>bar</filename> contains trailing " "whitespace, doing a check in the <literal role=\"hook\">precommit</literal> " "hook will prevent you from committing <filename>foo</filename> due to the " "problem with <filename>bar</filename>. This doesn't seem right." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:657 msgid "" "Should you choose the <literal role=\"hook\">pretxncommit</literal> hook, the " "check won't occur until just before the transaction for the commit " "completes. This will allow you to check for problems only the exact files " "that are being committed. However, if you entered the commit message " "interactively and the hook fails, the transaction will roll back; you'll have " "to re-enter the commit message after you fix the trailing whitespace and run " "<command role=\"hg-cmd\">hg commit</command> again." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:670 msgid "" "In this example, we introduce a simple <literal role=\"hook\">pretxncommit</" "literal> hook that checks for trailing whitespace. This hook is short, but " "not very helpful. It exits with an error status if a change adds a line with " "trailing whitespace to any file, but does not print any information that " "might help us to identify the offending file or line. It also has the nice " "property of not paying attention to unmodified lines; only lines that " "introduce new trailing whitespace cause problems." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:681 msgid "" "The above version is much more complex, but also more useful. It parses a " "unified diff to see if any lines add trailing whitespace, and prints the name " "of the file and the line number of each such occurrence. Even better, if the " "change adds trailing whitespace, this hook saves the commit comment and " "prints the name of the save file before exiting and telling Mercurial to roll " "the transaction back, so you can use the <option role=\"hg-opt-commit\">-l " "filename</option> option to <command role=\"hg-cmd\">hg commit</command> to " "reuse the saved commit message once you've corrected the problem." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:695 msgid "" "As a final aside, note in the example above the use of <command>perl</" "command>'s in-place editing feature to get rid of trailing whitespace from a " "file. This is concise and useful enough that I will reproduce it here." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:705 msgid "Bundled hooks" msgstr "内置的钩子" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch09-hook.xml:707 msgid "" "Mercurial ships with several bundled hooks. You can find them in the " "<filename class=\"directory\">hgext</filename> directory of a Mercurial " "source tree. If you are using a Mercurial binary package, the hooks will be " "located in the <filename class=\"directory\">hgext</filename> directory of " "wherever your package installer put Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:716 msgid "" "<literal role=\"hg-ext\">acl</literal>&emdash;access control for parts of a " "repository" msgstr "<literal role=\"hg-ext\">acl</literal>—版本库的访问控制" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:719 msgid "" "The <literal role=\"hg-ext\">acl</literal> extension lets you control which " "remote users are allowed to push changesets to a networked server. You can " "protect any portion of a repository (including the entire repo), so that a " "specific remote user can push changes that do not affect the protected " "portion." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:727 msgid "" "This extension implements access control based on the identity of the user " "performing a push, <emphasis>not</emphasis> on who committed the changesets " "they're pushing. It makes sense to use this hook only if you have a locked-" "down server environment that authenticates remote users, and you want to be " "sure that only specific users are allowed to push changes to that server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:737 msgid "Configuring the <literal role=\"hook\">acl</literal> hook" msgstr "配置 <literal role=\"hook\">acl</literal> 钩子" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:740 msgid "" "In order to manage incoming changesets, the <literal role=\"hg-ext\">acl</" "literal> hook must be used as a <literal role=\"hook\">pretxnchangegroup</" "literal> hook. This lets it see which files are modified by each incoming " "changeset, and roll back a group of changesets if they modify " "<quote>forbidden</quote> files. Example:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:750 msgid "" "The <literal role=\"hg-ext\">acl</literal> extension is configured using " "three sections." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:754 msgid "" "The <literal role=\"rc-acl\">acl</literal> section has only one entry, <envar " "role=\"rc-item-acl\">sources</envar>, which lists the sources of incoming " "changesets that the hook should pay attention to. You don't normally need to " "configure this section." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:761 msgid "" "<envar role=\"rc-item-acl\">serve</envar>: Control incoming changesets that " "are arriving from a remote repository over http or ssh. This is the default " "value of <envar role=\"rc-item-acl\">sources</envar>, and usually the only " "setting you'll need for this configuration item." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:769 msgid "" "<envar role=\"rc-item-acl\">pull</envar>: Control incoming changesets that " "are arriving via a pull from a local repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:774 msgid "" "<envar role=\"rc-item-acl\">push</envar>: Control incoming changesets that " "are arriving via a push from a local repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:779 msgid "" "<envar role=\"rc-item-acl\">bundle</envar>: Control incoming changesets that " "are arriving from another repository via a bundle." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:785 msgid "" "The <literal role=\"rc-acl.allow\">acl.allow</literal> section controls the " "users that are allowed to add changesets to the repository. If this section " "is not present, all users that are not explicitly denied are allowed. If " "this section is present, all users that are not explicitly allowed are denied " "(so an empty section means that all users are denied)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:794 msgid "" "The <literal role=\"rc-acl.deny\">acl.deny</literal> section determines which " "users are denied from adding changesets to the repository. If this section " "is not present or is empty, no users are denied." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:800 msgid "" "The syntaxes for the <literal role=\"rc-acl.allow\">acl.allow</literal> and " "<literal role=\"rc-acl.deny\">acl.deny</literal> sections are identical. On " "the left of each entry is a glob pattern that matches files or directories, " "relative to the root of the repository; on the right, a user name." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:808 msgid "" "In the following example, the user <literal>docwriter</literal> can only push " "changes to the <filename class=\"directory\">docs</filename> subtree of the " "repository, while <literal>intern</literal> can push changes to any file or " "directory except <filename class=\"directory\">source/sensitive</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:822 ../en/ch09-hook.xml:1089 ../en/ch09-hook.xml:1279 msgid "Testing and troubleshooting" msgstr "测试与问题处理" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:824 msgid "" "If you want to test the <literal role=\"hg-ext\">acl</literal> hook, run it " "with Mercurial's debugging output enabled. Since you'll probably be running " "it on a server where it's not convenient (or sometimes possible) to pass in " "the <option role=\"hg-opt-global\">--debug</option> option, don't forget that " "you can enable debugging output in your <filename role=\"special\">~/.hgrc</" "filename>:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:835 msgid "" "With this enabled, the <literal role=\"hg-ext\">acl</literal> hook will print " "enough information to let you figure out why it is allowing or forbidding " "pushes from specific users." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:844 msgid "" "<literal role=\"hg-ext\">bugzilla</literal>&emdash;integration with Bugzilla" msgstr "<literal role=\"hg-ext\">bugzilla</literal>—与 Bugzilla 的集成" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:848 msgid "" "The <literal role=\"hg-ext\">bugzilla</literal> extension adds a comment to a " "Bugzilla bug whenever it finds a reference to that bug ID in a commit " "comment. You can install this hook on a shared server, so that any time a " "remote user pushes changes to this server, the hook gets run." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:855 msgid "" "It adds a comment to the bug that looks like this (you can configure the " "contents of the comment&emdash;see below):" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:864 msgid "" "The value of this hook is that it automates the process of updating a bug any " "time a changeset refers to it. If you configure the hook properly, it makes " "it easy for people to browse straight from a Bugzilla bug to a changeset that " "refers to that bug." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:871 msgid "" "You can use the code in this hook as a starting point for some more exotic " "Bugzilla integration recipes. Here are a few possibilities:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:876 msgid "" "Require that every changeset pushed to the server have a valid bug ID in its " "commit comment. In this case, you'd want to configure the hook as a <literal " "role=\"hook\">pretxncommit</literal> hook. This would allow the hook to " "reject changes that didn't contain bug IDs." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:884 msgid "" "Allow incoming changesets to automatically modify the <emphasis>state</" "emphasis> of a bug, as well as simply adding a comment. For example, the " "hook could recognise the string <quote>fixed bug 31337</quote> as indicating " "that it should update the state of bug 31337 to <quote>requires testing</" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:894 msgid "Configuring the <literal role=\"hook\">bugzilla</literal> hook" msgstr "配置 <literal role=\"hook\">bugzilla</literal> 钩子" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:897 msgid "" "You should configure this hook in your server's <filename role=\"special\">~/." "hgrc</filename> as an <literal role=\"hook\">incoming</literal> hook, for " "example as follows:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:905 msgid "" "Because of the specialised nature of this hook, and because Bugzilla was not " "written with this kind of integration in mind, configuring this hook is a " "somewhat involved process." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:911 msgid "" "Before you begin, you must install the MySQL bindings for Python on the host" "(s) where you'll be running the hook. If this is not available as a binary " "package for your system, you can download it from <citation>web:mysql-python</" "citation>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:918 msgid "" "Configuration information for this hook lives in the <literal role=\"rc-" "bugzilla\">bugzilla</literal> section of your <filename role=\"special\">~/." "hgrc</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:923 msgid "" "<envar role=\"rc-item-bugzilla\">version</envar>: The version of Bugzilla " "installed on the server. The database schema that Bugzilla uses changes " "occasionally, so this hook has to know exactly which schema to use. At the " "moment, the only version supported is <literal>2.16</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:932 msgid "" "<envar role=\"rc-item-bugzilla\">host</envar>: The hostname of the MySQL " "server that stores your Bugzilla data. The database must be configured to " "allow connections from whatever host you are running the <literal role=\"hook" "\">bugzilla</literal> hook on." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:939 msgid "" "<envar role=\"rc-item-bugzilla\">user</envar>: The username with which to " "connect to the MySQL server. The database must be configured to allow this " "user to connect from whatever host you are running the <literal role=\"hook" "\">bugzilla</literal> hook on. This user must be able to access and modify " "Bugzilla tables. The default value of this item is <literal>bugs</literal>, " "which is the standard name of the Bugzilla user in a MySQL database." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:950 msgid "" "<envar role=\"rc-item-bugzilla\">password</envar>: The MySQL password for the " "user you configured above. This is stored as plain text, so you should make " "sure that unauthorised users cannot read the <filename role=\"special\">~/." "hgrc</filename> file where you store this information." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:959 msgid "" "<envar role=\"rc-item-bugzilla\">db</envar>: The name of the Bugzilla " "database on the MySQL server. The default value of this item is " "<literal>bugs</literal>, which is the standard name of the MySQL database " "where Bugzilla stores its data." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:966 msgid "" "<envar role=\"rc-item-bugzilla\">notify</envar>: If you want Bugzilla to send " "out a notification email to subscribers after this hook has added a comment " "to a bug, you will need this hook to run a command whenever it updates the " "database. The command to run depends on where you have installed Bugzilla, " "but it will typically look something like this, if you have Bugzilla " "installed in <filename class=\"directory\">/var/www/html/bugzilla</filename>:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:979 msgid "" "The Bugzilla <literal>processmail</literal> program expects to be given a bug " "ID (the hook replaces <quote><literal>%s</literal></quote> with the bug ID) " "and an email address. It also expects to be able to write to some files in " "the directory that it runs in. If Bugzilla and this hook are not installed " "on the same machine, you will need to find a way to run <literal>processmail</" "literal> on the server where Bugzilla is installed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:994 msgid "Mapping committer names to Bugzilla user names" msgstr "提交者的名称与 Bugzilla 用户名称的映射" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:996 msgid "" "By default, the <literal role=\"hg-ext\">bugzilla</literal> hook tries to use " "the email address of a changeset's committer as the Bugzilla user name with " "which to update a bug. If this does not suit your needs, you can map " "committer email addresses to Bugzilla user names using a <literal role=\"rc-" "usermap\">usermap</literal> section." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1005 msgid "" "Each item in the <literal role=\"rc-usermap\">usermap</literal> section " "contains an email address on the left, and a Bugzilla user name on the right." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1012 msgid "" "You can either keep the <literal role=\"rc-usermap\">usermap</literal> data " "in a normal <filename role=\"special\">~/.hgrc</filename>, or tell the " "<literal role=\"hg-ext\">bugzilla</literal> hook to read the information from " "an external <filename>usermap</filename> file. In the latter case, you can " "store <filename>usermap</filename> data by itself in (for example) a user-" "modifiable repository. This makes it possible to let your users maintain " "their own <envar role=\"rc-item-bugzilla\">usermap</envar> entries. The main " "<filename role=\"special\">~/.hgrc</filename> file might look like this:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1028 msgid "" "While the <filename>usermap</filename> file that it refers to might look like " "this:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:1036 msgid "Configuring the text that gets added to a bug" msgstr "配置增加到问题中的正文" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1038 msgid "" "You can configure the text that this hook adds as a comment; you specify it " "in the form of a Mercurial template. Several <filename role=\"special\">~/." "hgrc</filename> entries (still in the <literal role=\"rc-bugzilla\">bugzilla</" "literal> section) control this behaviour." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1045 msgid "" "<literal>strip</literal>: The number of leading path elements to strip from a " "repository's path name to construct a partial path for a URL. For example, if " "the repositories on your server live under <filename class=\"directory\">/" "home/hg/repos</filename>, and you have a repository whose path is <filename " "class=\"directory\">/home/hg/repos/app/tests</filename>, then setting " "<literal>strip</literal> to <literal>4</literal> will give a partial path of " "<filename class=\"directory\">app/tests</filename>. The hook will make this " "partial path available when expanding a template, as <literal>webroot</" "literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1059 msgid "" "<literal>template</literal>: The text of the template to use. In addition to " "the usual changeset-related variables, this template can use <literal>hgweb</" "literal> (the value of the <literal>hgweb</literal> configuration item above) " "and <literal>webroot</literal> (the path constructed using <literal>strip</" "literal> above)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1069 msgid "" "In addition, you can add a <envar role=\"rc-item-web\">baseurl</envar> item " "to the <literal role=\"rc-web\">web</literal> section of your <filename role=" "\"special\">~/.hgrc</filename>. The <literal role=\"hg-ext\">bugzilla</" "literal> hook will make this available when expanding a template, as the base " "string to use when constructing a URL that will let users browse from a " "Bugzilla comment to view a changeset. Example:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1081 msgid "" "Here is an example set of <literal role=\"hg-ext\">bugzilla</literal> hook " "config information." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1091 msgid "" "The most common problems with configuring the <literal role=\"hg-ext" "\">bugzilla</literal> hook relate to running Bugzilla's " "<filename>processmail</filename> script and mapping committer names to user " "names." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1097 msgid "" "Recall from <xref linkend=\"sec:hook:bugzilla:config\"/> above that the user " "that runs the Mercurial process on the server is also the one that will run " "the <filename>processmail</filename> script. The <filename>processmail</" "filename> script sometimes causes Bugzilla to write to files in its " "configuration directory, and Bugzilla's configuration files are usually owned " "by the user that your web server runs under." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1108 msgid "" "You can cause <filename>processmail</filename> to be run with the suitable " "user's identity using the <command>sudo</command> command. Here is an " "example entry for a <filename>sudoers</filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1115 msgid "" "This allows the <literal>hg_user</literal> user to run a " "<filename>processmail-wrapper</filename> program under the identity of " "<literal>httpd_user</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1120 msgid "" "This indirection through a wrapper script is necessary, because " "<filename>processmail</filename> expects to be run with its current directory " "set to wherever you installed Bugzilla; you can't specify that kind of " "constraint in a <filename>sudoers</filename> file. The contents of the " "wrapper script are simple:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1129 msgid "" "It doesn't seem to matter what email address you pass to " "<filename>processmail</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1133 msgid "" "If your <literal role=\"rc-usermap\">usermap</literal> is not set up " "correctly, users will see an error message from the <literal role=\"hg-ext" "\">bugzilla</literal> hook when they push changes to the server. The error " "message will look like this:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1140 msgid "" "What this means is that the committer's address, <literal>john.q." "public@example.com</literal>, is not a valid Bugzilla user name, nor does it " "have an entry in your <literal role=\"rc-usermap\">usermap</literal> that " "maps it to a valid Bugzilla user name." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1150 msgid "" "<literal role=\"hg-ext\">notify</literal>&emdash;send email notifications" msgstr "<literal role=\"hg-ext\">notify</literal>—邮件通知" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1153 msgid "" "Although Mercurial's built-in web server provides RSS feeds of changes in " "every repository, many people prefer to receive change notifications via " "email. The <literal role=\"hg-ext\">notify</literal> hook lets you send out " "notifications to a set of email addresses whenever changesets arrive that " "those subscribers are interested in." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1161 msgid "" "As with the <literal role=\"hg-ext\">bugzilla</literal> hook, the <literal " "role=\"hg-ext\">notify</literal> hook is template-driven, so you can " "customise the contents of the notification messages that it sends." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1167 msgid "" "By default, the <literal role=\"hg-ext\">notify</literal> hook includes a " "diff of every changeset that it sends out; you can limit the size of the " "diff, or turn this feature off entirely. It is useful for letting " "subscribers review changes immediately, rather than clicking to follow a URL." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:1175 msgid "Configuring the <literal role=\"hg-ext\">notify</literal> hook" msgstr "配置 <literal role=\"hg-ext\">notify</literal> 钩子" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1178 msgid "" "You can set up the <literal role=\"hg-ext\">notify</literal> hook to send one " "email message per incoming changeset, or one per incoming group of changesets " "(all those that arrived in a single pull or push)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1190 msgid "" "Configuration information for this hook lives in the <literal role=\"rc-notify" "\">notify</literal> section of a <filename role=\"special\">~/.hgrc</" "filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1195 msgid "" "<envar role=\"rc-item-notify\">test</envar>: By default, this hook does not " "send out email at all; instead, it prints the message that it " "<emphasis>would</emphasis> send. Set this item to <literal>false</literal> " "to allow email to be sent. The reason that sending of email is turned off by " "default is that it takes several tries to configure this extension exactly as " "you would like, and it would be bad form to spam subscribers with a number of " "<quote>broken</quote> notifications while you debug your configuration." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1207 msgid "" "<envar role=\"rc-item-notify\">config</envar>: The path to a configuration " "file that contains subscription information. This is kept separate from the " "main <filename role=\"special\">~/.hgrc</filename> so that you can maintain " "it in a repository of its own. People can then clone that repository, update " "their subscriptions, and push the changes back to your server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1216 msgid "" "<envar role=\"rc-item-notify\">strip</envar>: The number of leading path " "separator characters to strip from a repository's path, when deciding whether " "a repository has subscribers. For example, if the repositories on your " "server live in <filename class=\"directory\">/home/hg/repos</filename>, and " "<literal role=\"hg-ext\">notify</literal> is considering a repository named " "<filename class=\"directory\">/home/hg/repos/shared/test</filename>, setting " "<envar role=\"rc-item-notify\">strip</envar> to <literal>4</literal> will " "cause <literal role=\"hg-ext\">notify</literal> to trim the path it considers " "down to <filename class=\"directory\">shared/test</filename>, and it will " "match subscribers against that." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1233 msgid "" "<envar role=\"rc-item-notify\">template</envar>: The template text to use " "when sending messages. This specifies both the contents of the message " "header and its body." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1239 msgid "" "<envar role=\"rc-item-notify\">maxdiff</envar>: The maximum number of lines " "of diff data to append to the end of a message. If a diff is longer than " "this, it is truncated. By default, this is set to 300. Set this to " "<literal>0</literal> to omit diffs from notification emails." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1248 msgid "" "<envar role=\"rc-item-notify\">sources</envar>: A list of sources of " "changesets to consider. This lets you limit <literal role=\"hg-ext\">notify</" "literal> to only sending out email about changes that remote users pushed " "into this repository via a server, for example. See <xref linkend=\"sec:hook:" "sources\"/> for the sources you can specify here." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1259 msgid "" "If you set the <envar role=\"rc-item-web\">baseurl</envar> item in the " "<literal role=\"rc-web\">web</literal> section, you can use it in a template; " "it will be available as <literal>webroot</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1265 msgid "" "Here is an example set of <literal role=\"hg-ext\">notify</literal> " "configuration information." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1271 msgid "This will produce a message that looks like the following:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1281 msgid "" "Do not forget that by default, the <literal role=\"hg-ext\">notify</literal> " "extension <emphasis>will not send any mail</emphasis> until you explicitly " "configure it to do so, by setting <envar role=\"rc-item-notify\">test</envar> " "to <literal>false</literal>. Until you do that, it simply prints the message " "it <emphasis>would</emphasis> send." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:1293 msgid "Information for writers of hooks" msgstr "编写钩子的信息" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1296 msgid "In-process hook execution" msgstr "进程内钩子的执行" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1298 msgid "An in-process hook is called with arguments of the following form:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1302 msgid "" "The <literal>ui</literal> parameter is a <literal role=\"py-mod-mercurial.ui" "\">ui</literal> object. The <literal>repo</literal> parameter is a <literal " "role=\"py-mod-mercurial.localrepo\">localrepository</literal> object. The " "names and values of the <literal>**kwargs</literal> parameters depend on the " "hook being invoked, with the following common features:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1311 msgid "" "If a parameter is named <literal>node</literal> or <literal>parentN</" "literal>, it will contain a hexadecimal changeset ID. The empty string is " "used to represent <quote>null changeset ID</quote> instead of a string of " "zeroes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1318 msgid "" "If a parameter is named <literal>url</literal>, it will contain the URL of a " "remote repository, if that can be determined." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1323 msgid "" "Boolean-valued parameters are represented as Python <literal>bool</literal> " "objects." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1328 msgid "" "An in-process hook is called without a change to the process's working " "directory (unlike external hooks, which are run in the root of the " "repository). It must not change the process's working directory, or it will " "cause any calls it makes into the Mercurial API to fail." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1335 msgid "" "If a hook returns a boolean <quote>false</quote> value, it is considered to " "have succeeded. If it returns a boolean <quote>true</quote> value or raises " "an exception, it is considered to have failed. A useful way to think of the " "calling convention is <quote>tell me if you fail</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1342 msgid "" "Note that changeset IDs are passed into Python hooks as hexadecimal strings, " "not the binary hashes that Mercurial's APIs normally use. To convert a hash " "from hex to binary, use the <literal>bin</literal> function." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1350 msgid "External hook execution" msgstr "外部钩子的执行" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1352 msgid "" "An external hook is passed to the shell of the user running Mercurial. " "Features of that shell, such as variable substitution and command " "redirection, are available. The hook is run in the root directory of the " "repository (unlike in-process hooks, which are run in the same directory that " "Mercurial was run in)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1360 msgid "" "Hook parameters are passed to the hook as environment variables. Each " "environment variable's name is converted in upper case and prefixed with the " "string <quote><literal>HG_</literal></quote>. For example, if the name of a " "parameter is <quote><literal>node</literal></quote>, the name of the " "environment variable representing that parameter will be " "<quote><literal>HG_NODE</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1369 msgid "" "A boolean parameter is represented as the string <quote><literal>1</literal></" "quote> for <quote>true</quote>, <quote><literal>0</literal></quote> for " "<quote>false</quote>. If an environment variable is named <envar>HG_NODE</" "envar>, <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it contains a " "changeset ID represented as a hexadecimal string. The empty string is used " "to represent <quote>null changeset ID</quote> instead of a string of zeroes. " "If an environment variable is named <envar>HG_URL</envar>, it will contain " "the URL of a remote repository, if that can be determined." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1381 msgid "" "If a hook exits with a status of zero, it is considered to have succeeded. " "If it exits with a non-zero status, it is considered to have failed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1388 msgid "Finding out where changesets come from" msgstr "检查修改集来自何处" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1390 msgid "" "A hook that involves the transfer of changesets between a local repository " "and another may be able to find out information about the <quote>far side</" "quote>. Mercurial knows <emphasis>how</emphasis> changes are being " "transferred, and in many cases <emphasis>where</emphasis> they are being " "transferred to or from." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:1399 msgid "Sources of changesets" msgstr "修改集的来源" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1401 msgid "" "Mercurial will tell a hook what means are, or were, used to transfer " "changesets between repositories. This is provided by Mercurial in a Python " "parameter named <literal>source</literal>, or an environment variable named " "<envar>HG_SOURCE</envar>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1409 msgid "" "<literal>serve</literal>: Changesets are transferred to or from a remote " "repository over http or ssh." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1414 msgid "" "<literal>pull</literal>: Changesets are being transferred via a pull from one " "repository into another." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1419 msgid "" "<literal>push</literal>: Changesets are being transferred via a push from one " "repository into another." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1424 msgid "" "<literal>bundle</literal>: Changesets are being transferred to or from a " "bundle." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><title> #: ../en/ch09-hook.xml:1431 msgid "Where changes are going&emdash;remote repository URLs" msgstr "修改集要到哪里—远程版本库的地址" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1434 msgid "" "When possible, Mercurial will tell a hook the location of the <quote>far " "side</quote> of an activity that transfers changeset data between " "repositories. This is provided by Mercurial in a Python parameter named " "<literal>url</literal>, or an environment variable named <envar>HG_URL</" "envar>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><para> #: ../en/ch09-hook.xml:1442 msgid "" "This information is not always known. If a hook is invoked in a repository " "that is being served via http or ssh, Mercurial cannot tell where the remote " "repository is, but it may know where the client is connecting from. In such " "cases, the URL will take one of the following forms:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1449 msgid "" "<literal>remote:ssh:1.2.3.4</literal>&emdash;remote ssh client, at the IP " "address <literal>1.2.3.4</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1454 msgid "" "<literal>remote:http:1.2.3.4</literal>&emdash;remote http client, at the IP " "address <literal>1.2.3.4</literal>. If the client is using SSL, this will be " "of the form <literal>remote:https:1.2.3.4</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><sect3><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1461 msgid "Empty&emdash;no information could be discovered about the remote client." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch09-hook.xml:1470 msgid "Hook reference" msgstr "钩子参考" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1473 msgid "" "<literal role=\"hook\">changegroup</literal>&emdash;after remote changesets " "added" msgstr "<literal role=\"hook\">changegroup</literal>—增加远程修改集之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1476 msgid "" "This hook is run after a group of pre-existing changesets has been added to " "the repository, for example via a <command role=\"hg-cmd\">hg pull</command> " "or <command role=\"hg-cmd\">hg unbundle</command>. This hook is run once per " "operation that added one or more changesets. This is in contrast to the " "<literal role=\"hook\">incoming</literal> hook, which is run once per " "changeset, regardless of whether the changesets arrive in a group." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1486 msgid "" "Some possible uses for this hook include kicking off an automated build or " "test of the added changesets, updating a bug database, or notifying " "subscribers that a repository contains new changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1492 ../en/ch09-hook.xml:1532 ../en/ch09-hook.xml:1576 #: ../en/ch09-hook.xml:1618 ../en/ch09-hook.xml:1673 ../en/ch09-hook.xml:1713 #: ../en/ch09-hook.xml:1749 ../en/ch09-hook.xml:1783 ../en/ch09-hook.xml:1846 #: ../en/ch09-hook.xml:1904 ../en/ch09-hook.xml:1940 ../en/ch09-hook.xml:1967 msgid "Parameters to this hook:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1495 ../en/ch09-hook.xml:1849 msgid "" "<literal>node</literal>: A changeset ID. The changeset ID of the first " "changeset in the group that was added. All changesets between this and " "<literal role=\"tag\">tip</literal>, inclusive, were added by a single " "<command role=\"hg-cmd\">hg pull</command>, <command role=\"hg-cmd\">hg push</" "command> or <command role=\"hg-cmd\">hg unbundle</command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1504 ../en/ch09-hook.xml:1583 ../en/ch09-hook.xml:1676 #: ../en/ch09-hook.xml:1859 msgid "" "<literal>source</literal>: A string. The source of these changes. See <xref " "linkend=\"sec:hook:sources\"/> for details." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1509 ../en/ch09-hook.xml:1588 ../en/ch09-hook.xml:1639 #: ../en/ch09-hook.xml:1681 ../en/ch09-hook.xml:1762 ../en/ch09-hook.xml:1864 msgid "" "<literal>url</literal>: A URL. The location of the remote repository, if " "known. See <xref linkend=\"sec:hook:url\"/> for more information." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1515 msgid "" "See also: <literal role=\"hook\">incoming</literal> (<xref linkend=\"sec:hook:" "incoming\"/>), <literal role=\"hook\">prechangegroup</literal> (<xref linkend=" "\"sec:hook:prechangegroup\"/>), <literal role=\"hook\">pretxnchangegroup</" "literal> (<xref linkend=\"sec:hook:pretxnchangegroup\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1526 msgid "" "<literal role=\"hook\">commit</literal>&emdash;after a new changeset is " "created" msgstr "<literal role=\"hook\">commit</literal>—创建新修改集之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1529 msgid "This hook is run after a new changeset has been created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1535 ../en/ch09-hook.xml:1907 msgid "" "<literal>node</literal>: A changeset ID. The changeset ID of the newly " "committed changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1539 ../en/ch09-hook.xml:1911 msgid "" "<literal>parent1</literal>: A changeset ID. The changeset ID of the first " "parent of the newly committed changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1544 ../en/ch09-hook.xml:1916 msgid "" "<literal>parent2</literal>: A changeset ID. The changeset ID of the second " "parent of the newly committed changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1550 msgid "" "See also: <literal role=\"hook\">precommit</literal> (<xref linkend=\"sec:" "hook:precommit\"/>), <literal role=\"hook\">pretxncommit</literal> (<xref " "linkend=\"sec:hook:pretxncommit\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1559 msgid "" "<literal role=\"hook\">incoming</literal>&emdash;after one remote changeset " "is added" msgstr "<literal role=\"hook\">incoming</literal>—增加远程修改集之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1562 msgid "" "This hook is run after a pre-existing changeset has been added to the " "repository, for example via a <command role=\"hg-cmd\">hg push</command>. If " "a group of changesets was added in a single operation, this hook is called " "once for each added changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1569 msgid "" "You can use this hook for the same purposes as the <literal role=\"hook" "\">changegroup</literal> hook (<xref linkend=\"sec:hook:changegroup\"/>); " "it's simply more convenient sometimes to run a hook once per group of " "changesets, while other times it's handier once per changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1579 msgid "" "<literal>node</literal>: A changeset ID. The ID of the newly added changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1594 msgid "" "See also: <literal role=\"hook\">changegroup</literal> (<xref linkend=\"sec:" "hook:changegroup\"/>) <literal role=\"hook\">prechangegroup</literal> (<xref " "linkend=\"sec:hook:prechangegroup\"/>), <literal role=\"hook" "\">pretxnchangegroup</literal> (<xref linkend=\"sec:hook:pretxnchangegroup\"/" ">)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1605 msgid "" "<literal role=\"hook\">outgoing</literal>&emdash;after changesets are " "propagated" msgstr "<literal role=\"hook\">outgoing</literal>—传播修改集之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1608 msgid "" "This hook is run after a group of changesets has been propagated out of this " "repository, for example by a <command role=\"hg-cmd\">hg push</command> or " "<command role=\"hg-cmd\">hg bundle</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1614 msgid "" "One possible use for this hook is to notify administrators that changes have " "been pulled." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1621 msgid "" "<literal>node</literal>: A changeset ID. The changeset ID of the first " "changeset of the group that was sent." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1626 msgid "" "<literal>source</literal>: A string. The source of the of the operation (see " "<xref linkend=\"sec:hook:sources\"/>). If a remote client pulled changes " "from this repository, <literal>source</literal> will be <literal>serve</" "literal>. If the client that obtained changes from this repository was " "local, <literal>source</literal> will be <literal>bundle</literal>, " "<literal>pull</literal>, or <literal>push</literal>, depending on the " "operation the client performed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1645 msgid "" "See also: <literal role=\"hook\">preoutgoing</literal> (<xref linkend=\"sec:" "hook:preoutgoing\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1652 msgid "" "<literal role=\"hook\">prechangegroup</literal>&emdash;before starting to add " "remote changesets" msgstr "<literal role=\"hook\">prechangegroup</literal>—增加远程修改集之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1656 msgid "" "This controlling hook is run before Mercurial begins to add a group of " "changesets from another repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1660 msgid "" "This hook does not have any information about the changesets to be added, " "because it is run before transmission of those changesets is allowed to " "begin. If this hook fails, the changesets will not be transmitted." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1666 msgid "" "One use for this hook is to prevent external changes from being added to a " "repository. For example, you could use this to <quote>freeze</quote> a " "server-hosted branch temporarily or permanently so that users cannot push to " "it, while still allowing a local administrator to modify the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1687 msgid "" "See also: <literal role=\"hook\">changegroup</literal> (<xref linkend=\"sec:" "hook:changegroup\"/>), <literal role=\"hook\">incoming</literal> (<xref " "linkend=\"sec:hook:incoming\"/>), <literal role=\"hook\">pretxnchangegroup</" "literal> (<xref linkend=\"sec:hook:pretxnchangegroup\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1698 msgid "" "<literal role=\"hook\">precommit</literal>&emdash;before starting to commit a " "changeset" msgstr "<literal role=\"hook\">precommit</literal>—提交修改集之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1701 msgid "" "This hook is run before Mercurial begins to commit a new changeset. It is run " "before Mercurial has any of the metadata for the commit, such as the files to " "be committed, the commit message, or the commit date." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1707 msgid "" "One use for this hook is to disable the ability to commit new changesets, " "while still allowing incoming changesets. Another is to run a build or test, " "and only allow the commit to begin if the build or test succeeds." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1716 msgid "" "<literal>parent1</literal>: A changeset ID. The changeset ID of the first " "parent of the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1721 msgid "" "<literal>parent2</literal>: A changeset ID. The changeset ID of the second " "parent of the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1726 msgid "" "If the commit proceeds, the parents of the working directory will become the " "parents of the new changeset." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1730 msgid "" "See also: <literal role=\"hook\">commit</literal> (<xref linkend=\"sec:hook:" "commit\"/>), <literal role=\"hook\">pretxncommit</literal> (<xref linkend=" "\"sec:hook:pretxncommit\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1738 msgid "" "<literal role=\"hook\">preoutgoing</literal>&emdash;before starting to " "propagate changesets" msgstr "<literal role=\"hook\">preoutgoing</literal>—传播修改集之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1741 msgid "" "This hook is invoked before Mercurial knows the identities of the changesets " "to be transmitted." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1745 msgid "" "One use for this hook is to prevent changes from being transmitted to another " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1752 msgid "" "<literal>source</literal>: A string. The source of the operation that is " "attempting to obtain changes from this repository (see <xref linkend=\"sec:" "hook:sources\"/>). See the documentation for the <literal>source</literal> " "parameter to the <literal role=\"hook\">outgoing</literal> hook, in <xref " "linkend=\"sec:hook:outgoing\"/>, for possible values of this parameter." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1768 msgid "" "See also: <literal role=\"hook\">outgoing</literal> (<xref linkend=\"sec:hook:" "outgoing\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1775 msgid "" "<literal role=\"hook\">pretag</literal>&emdash;before tagging a changeset" msgstr "<literal role=\"hook\">pretag</literal>—创建标签之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1778 msgid "" "This controlling hook is run before a tag is created. If the hook succeeds, " "creation of the tag proceeds. If the hook fails, the tag is not created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1786 msgid "" "<literal>local</literal>: A boolean. Whether the tag is local to this " "repository instance (i.e. stored in <filename role=\"special\">.hg/localtags</" "filename>) or managed by Mercurial (stored in <filename role=\"special\">." "hgtags</filename>)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1793 msgid "" "<literal>node</literal>: A changeset ID. The ID of the changeset to be " "tagged." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1797 msgid "<literal>tag</literal>: A string. The name of the tag to be created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1802 msgid "" "If the tag to be created is revision-controlled, the <literal role=\"hook" "\">precommit</literal> and <literal role=\"hook\">pretxncommit</literal> " "hooks (<xref linkend=\"sec:hook:commit\"/> and <xref linkend=\"sec:hook:" "pretxncommit\"/>) will also be run." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1810 msgid "" "See also: <literal role=\"hook\">tag</literal> (<xref linkend=\"sec:hook:tag" "\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1815 msgid "" "<literal role=\"hook\">pretxnchangegroup</literal>&emdash;before completing " "addition of remote changesets" msgstr "" "<literal role=\"hook\">pretxnchangegroup</literal>—完成增加远程修改集之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1819 msgid "" "This controlling hook is run before a transaction&emdash;that manages the " "addition of a group of new changesets from outside the repository&emdash;" "completes. If the hook succeeds, the transaction completes, and all of the " "changesets become permanent within this repository. If the hook fails, the " "transaction is rolled back, and the data for the changesets is erased." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1828 msgid "" "This hook can access the metadata associated with the almost-added " "changesets, but it should not do anything permanent with this data. It must " "also not modify the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1834 msgid "" "While this hook is running, if other Mercurial processes access this " "repository, they will be able to see the almost-added changesets as if they " "are permanent. This may lead to race conditions if you do not take steps to " "avoid them." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1841 msgid "" "This hook can be used to automatically vet a group of changesets. If the " "hook fails, all of the changesets are <quote>rejected</quote> when the " "transaction rolls back." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1870 msgid "" "See also: <literal role=\"hook\">changegroup</literal> (<xref linkend=\"sec:" "hook:changegroup\"/>), <literal role=\"hook\">incoming</literal> (<xref " "linkend=\"sec:hook:incoming\"/>), <literal role=\"hook\">prechangegroup</" "literal> (<xref linkend=\"sec:hook:prechangegroup\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1881 msgid "" "<literal role=\"hook\">pretxncommit</literal>&emdash;before completing commit " "of new changeset" msgstr "<literal role=\"hook\">pretxncommit</literal>—完成提交之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1884 msgid "" "This controlling hook is run before a transaction&emdash;that manages a new " "commit&emdash;completes. If the hook succeeds, the transaction completes and " "the changeset becomes permanent within this repository. If the hook fails, " "the transaction is rolled back, and the commit data is erased." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1892 msgid "" "This hook can access the metadata associated with the almost-new changeset, " "but it should not do anything permanent with this data. It must also not " "modify the working directory." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1898 msgid "" "While this hook is running, if other Mercurial processes access this " "repository, they will be able to see the almost-new changeset as if it is " "permanent. This may lead to race conditions if you do not take steps to " "avoid them." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1922 msgid "" "See also: <literal role=\"hook\">precommit</literal> (<xref linkend=\"sec:" "hook:precommit\"/>)" msgstr "" "参见: <literal role=\"hook\">precommit</literal> (<xref linkend=\"sec:hook:" "precommit\"/>)" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1929 msgid "" "<literal role=\"hook\">preupdate</literal>&emdash;before updating or merging " "working directory" msgstr "<literal role=\"hook\">preupdate</literal>—更新或合并工作目录之前" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1932 msgid "" "This controlling hook is run before an update or merge of the working " "directory begins. It is run only if Mercurial's normal pre-update checks " "determine that the update or merge can proceed. If the hook succeeds, the " "update or merge may proceed; if it fails, the update or merge does not start." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1943 msgid "" "<literal>parent1</literal>: A changeset ID. The ID of the parent that the " "working directory is to be updated to. If the working directory is being " "merged, it will not change this parent." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1949 msgid "" "<literal>parent2</literal>: A changeset ID. Only set if the working directory " "is being merged. The ID of the revision that the working directory is being " "merged with." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1956 msgid "" "See also: <literal role=\"hook\">update</literal> (<xref linkend=\"sec:hook:" "update\"/>)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1961 msgid "<literal role=\"hook\">tag</literal>&emdash;after tagging a changeset" msgstr "<literal role=\"hook\">tag</literal>—创建标签之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1964 msgid "This hook is run after a tag has been created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1970 msgid "" "<literal>local</literal>: A boolean. Whether the new tag is local to this " "repository instance (i.e. stored in <filename role=\"special\">.hg/" "localtags</filename>) or managed by Mercurial (stored in <filename role=" "\"special\">.hgtags</filename>)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1978 msgid "" "<literal>node</literal>: A changeset ID. The ID of the changeset that was " "tagged." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:1982 msgid "<literal>tag</literal>: A string. The name of the tag that was created." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1987 msgid "" "If the created tag is revision-controlled, the <literal role=\"hook\">commit</" "literal> hook (section <xref linkend=\"sec:hook:commit\"/>) is run before " "this hook." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:1992 msgid "" "See also: <literal role=\"hook\">pretag</literal> (<xref linkend=\"sec:hook:" "pretag\"/>)" msgstr "" "参见: <literal role=\"hook\">pretag</literal> (<xref linkend=\"sec:hook:pretag" "\"/>)" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch09-hook.xml:1998 msgid "" "<literal role=\"hook\">update</literal>&emdash;after updating or merging " "working directory" msgstr "<literal role=\"hook\">update</literal>—更新或合并工作目录之后" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:2001 msgid "" "This hook is run after an update or merge of the working directory " "completes. Since a merge can fail (if the external <command>hgmerge</" "command> command fails to resolve conflicts in a file), this hook " "communicates whether the update or merge completed cleanly." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:2009 msgid "" "<literal>error</literal>: A boolean. Indicates whether the update or merge " "completed successfully." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:2014 msgid "" "<literal>parent1</literal>: A changeset ID. The ID of the parent that the " "working directory was updated to. If the working directory was merged, it " "will not have changed this parent." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch09-hook.xml:2020 msgid "" "<literal>parent2</literal>: A changeset ID. Only set if the working " "directory was merged. The ID of the revision that the working directory was " "merged with." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch09-hook.xml:2026 msgid "" "See also: <literal role=\"hook\">preupdate</literal> (<xref linkend=\"sec:" "hook:preupdate\"/>)" msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch10-template.xml:5 msgid "Customising the output of Mercurial" msgstr "定制 Mercurial 的输出" #. type: Content of: <book><chapter><para> #: ../en/ch10-template.xml:7 msgid "" "Mercurial provides a powerful mechanism to let you control how it displays " "information. The mechanism is based on templates. You can use templates to " "generate specific output for a single command, or to customise the entire " "appearance of the built-in web interface." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:14 msgid "Using precanned output styles" msgstr "使用预定义的输出样式" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:16 msgid "" "Packaged with Mercurial are some output styles that you can use immediately. " "A style is simply a precanned template that someone wrote and installed " "somewhere that Mercurial can find." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:21 msgid "" "Before we take a look at Mercurial's bundled styles, let's review its normal " "output." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:26 msgid "" "This is somewhat informative, but it takes up a lot of space&emdash;five " "lines of output per changeset. The <literal>compact</literal> style reduces " "this to three lines, presented in a sparse manner." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:33 msgid "" "The <literal>changelog</literal> style hints at the expressive power of " "Mercurial's templating engine. This style attempts to follow the GNU " "Project's changelog guidelines<citation>web:changelog</citation>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:40 msgid "" "You will not be shocked to learn that Mercurial's default output style is " "named <literal>default</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:44 msgid "Setting a default style" msgstr "设置默认样式" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:46 msgid "" "You can modify the output style that Mercurial will use for every command by " "editing your <filename role=\"special\">~/.hgrc</filename> file, naming the " "style you would prefer to use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:54 msgid "" "If you write a style of your own, you can use it by either providing the path " "to your style file, or copying your style file into a location where " "Mercurial can find it (typically the <literal>templates</literal> " "subdirectory of your Mercurial install directory)." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:63 msgid "Commands that support styles and templates" msgstr "支持样式和模版的命令" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:65 msgid "" "All of Mercurial's <quote><literal>log</literal>-like</quote> commands let " "you use styles and templates: <command role=\"hg-cmd\">hg incoming</command>, " "<command role=\"hg-cmd\">hg log</command>, <command role=\"hg-cmd\">hg " "outgoing</command>, and <command role=\"hg-cmd\">hg tip</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:72 msgid "" "As I write this manual, these are so far the only commands that support " "styles and templates. Since these are the most important commands that need " "customisable output, there has been little pressure from the Mercurial user " "community to add style and template support to other commands." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:80 msgid "The basics of templating" msgstr "模版基础" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:82 msgid "" "At its simplest, a Mercurial template is a piece of text. Some of the text " "never changes, while other parts are <emphasis>expanded</emphasis>, or " "replaced with new text, when necessary." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:87 msgid "" "Before we continue, let's look again at a simple example of Mercurial's " "normal output." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:92 msgid "" "Now, let's run the same command, but using a template to change its output." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:97 msgid "" "The example above illustrates the simplest possible template; it's just a " "piece of static text, printed once for each changeset. The <option role=\"hg-" "opt-log\">--template</option> option to the <command role=\"hg-cmd\">hg log</" "command> command tells Mercurial to use the given text as the template when " "printing each changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:105 msgid "" "Notice that the template string above ends with the text <quote><literal>\\n</" "literal></quote>. This is an <emphasis>escape sequence</emphasis>, telling " "Mercurial to print a newline at the end of each template item. If you omit " "this newline, Mercurial will run each piece of output together. See <xref " "linkend=\"sec:template:escape\"/> for more details of escape sequences." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:113 msgid "" "A template that prints a fixed string of text all the time isn't very useful; " "let's try something a bit more complex." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:119 msgid "" "As you can see, the string <quote><literal>{desc}</literal></quote> in the " "template has been replaced in the output with the description of each " "changeset. Every time Mercurial finds text enclosed in curly braces " "(<quote><literal>{</literal></quote> and <quote><literal>}</literal></" "quote>), it will try to replace the braces and text with the expansion of " "whatever is inside. To print a literal curly brace, you must escape it, as " "described in <xref linkend=\"sec:template:escape\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:131 msgid "Common template keywords" msgstr "模版关键字" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:133 msgid "" "You can start writing simple templates immediately using the keywords below." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:137 msgid "" "<literal role=\"template-keyword\">author</literal>: String. The unmodified " "author of the changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:141 msgid "" "<literal role=\"template-keyword\">branches</literal>: String. The name of " "the branch on which the changeset was committed. Will be empty if the branch " "name was <literal>default</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:147 msgid "" "<literal role=\"template-keyword\">date</literal>: Date information. The " "date when the changeset was committed. This is <emphasis>not</emphasis> " "human-readable; you must pass it through a filter that will render it " "appropriately. See <xref linkend=\"sec:template:filter\"/> for more " "information on filters. The date is expressed as a pair of numbers. The " "first number is a Unix UTC timestamp (seconds since January 1, 1970); the " "second is the offset of the committer's timezone from UTC, in seconds." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:158 msgid "" "<literal role=\"template-keyword\">desc</literal>: String. The text of the " "changeset description." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:161 msgid "" "<literal role=\"template-keyword\">files</literal>: List of strings. All " "files modified, added, or removed by this changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:166 msgid "" "<literal role=\"template-keyword\">file_adds</literal>: List of strings. " "Files added by this changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:170 msgid "" "<literal role=\"template-keyword\">file_dels</literal>: List of strings. " "Files removed by this changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:174 msgid "" "<literal role=\"template-keyword\">node</literal>: String. The changeset " "identification hash, as a 40-character hexadecimal string." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:178 msgid "" "<literal role=\"template-keyword\">parents</literal>: List of strings. The " "parents of the changeset." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:182 msgid "" "<literal role=\"template-keyword\">rev</literal>: Integer. The repository-" "local changeset revision number." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:186 msgid "" "<literal role=\"template-keyword\">tags</literal>: List of strings. Any tags " "associated with the changeset." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:191 msgid "" "A few simple experiments will show us what to expect when we use these " "keywords; you can see the results below." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:196 msgid "" "As we noted above, the date keyword does not produce human-readable output, " "so we must treat it specially. This involves using a <emphasis>filter</" "emphasis>, about which more in <xref linkend=\"sec:template:filter\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:205 msgid "Escape sequences" msgstr "转义序列" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:207 msgid "" "Mercurial's templating engine recognises the most commonly used escape " "sequences in strings. When it sees a backslash (<quote><literal>\\</" "literal></quote>) character, it looks at the following character and " "substitutes the two characters with a single replacement, as described below." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:214 msgid "" "<literal>\\</literal>: Backslash, <quote><literal>\\</literal></quote>, ASCII " "134." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:218 msgid "<literal>\\n</literal>: Newline, ASCII 12." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:221 msgid "<literal>\\r</literal>: Carriage return, ASCII 15." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:224 msgid "<literal>\\t</literal>: Tab, ASCII 11." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:227 msgid "<literal>\\v</literal>: Vertical tab, ASCII 13." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:230 msgid "" "<literal>{</literal>: Open curly brace, <quote><literal>{</literal></quote>, " "ASCII 173." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:234 msgid "" "<literal>}</literal>: Close curly brace, <quote><literal>}</literal></quote>, " "ASCII 175." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:239 msgid "" "As indicated above, if you want the expansion of a template to contain a " "literal <quote><literal>\\</literal></quote>, <quote><literal>{</literal></" "quote>, or <quote><literal>{</literal></quote> character, you must escape it." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:247 msgid "Filtering keywords to change their results" msgstr "通过过滤关键字来修改输出结果" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:249 msgid "" "Some of the results of template expansion are not immediately easy to use. " "Mercurial lets you specify an optional chain of <emphasis>filters</emphasis> " "to modify the result of expanding a keyword. You have already seen a common " "filter, <literal role=\"template-kw-filt-date\">isodate</literal>, in action " "above, to make a date readable." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:256 msgid "" "Below is a list of the most commonly used filters that Mercurial supports. " "While some filters can be applied to any text, others can only be used in " "specific circumstances. The name of each filter is followed first by an " "indication of where it can be used, then a description of its effect." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:263 msgid "" "<literal role=\"template-filter\">addbreaks</literal>: Any text. Add an XHTML " "<quote><literal><br/></literal></quote> tag before the end of every " "line except the last. For example, <quote><literal>foo\\nbar</literal></" "quote> becomes <quote><literal>foo<br/>\\nbar</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:270 msgid "" "<literal role=\"template-kw-filt-date\">age</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render the age of the date, " "relative to the current time. Yields a string like <quote><literal>10 " "minutes</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:277 msgid "" "<literal role=\"template-filter\">basename</literal>: Any text, but most " "useful for the <literal role=\"template-keyword\">files</literal> keyword and " "its relatives. Treat the text as a path, and return the basename. For " "example, <quote><literal>foo/bar/baz</literal></quote> becomes " "<quote><literal>baz</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:286 msgid "" "<literal role=\"template-kw-filt-date\">date</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render a date in a similar " "format to the Unix <literal role=\"template-keyword\">date</literal> command, " "but with timezone included. Yields a string like <quote><literal>Mon Sep 04 " "15:13:13 2006 -0700</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:294 msgid "" "<literal role=\"template-kw-filt-author\">domain</literal>: Any text, but " "most useful for the <literal role=\"template-keyword\">author</literal> " "keyword. Finds the first string that looks like an email address, and " "extract just the domain component. For example, <quote><literal>Bryan " "O'Sullivan <bos@serpentine.com></literal></quote> becomes " "<quote><literal>serpentine.com</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:304 msgid "" "<literal role=\"template-kw-filt-author\">email</literal>: Any text, but most " "useful for the <literal role=\"template-keyword\">author</literal> keyword. " "Extract the first string that looks like an email address. For example, " "<quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> " "becomes <quote><literal>bos@serpentine.com</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:313 msgid "" "<literal role=\"template-filter\">escape</literal>: Any text. Replace the " "special XML/XHTML characters <quote><literal>&</literal></quote>, " "<quote><literal><</literal></quote> and <quote><literal>></literal></" "quote> with XML entities." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:321 msgid "" "<literal role=\"template-filter\">fill68</literal>: Any text. Wrap the text " "to fit in 68 columns. This is useful before you pass text through the " "<literal role=\"template-filter\">tabindent</literal> filter, and still want " "it to fit in an 80-column fixed-font window." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:329 msgid "" "<literal role=\"template-filter\">fill76</literal>: Any text. Wrap the text " "to fit in 76 columns." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:333 msgid "" "<literal role=\"template-filter\">firstline</literal>: Any text. Yield the " "first line of text, without any trailing newlines." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:338 msgid "" "<literal role=\"template-kw-filt-date\">hgdate</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render the date as a pair of " "readable numbers. Yields a string like <quote><literal>1157407993 25200</" "literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:345 msgid "" "<literal role=\"template-kw-filt-date\">isodate</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render the date as a text " "string in ISO 8601 format. Yields a string like <quote><literal>2006-09-04 " "15:13:13 -0700</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:352 msgid "" "<literal role=\"template-filter\">obfuscate</literal>: Any text, but most " "useful for the <literal role=\"template-keyword\">author</literal> keyword. " "Yield the input text rendered as a sequence of XML entities. This helps to " "defeat some particularly stupid screen-scraping email harvesting spambots." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:360 msgid "" "<literal role=\"template-kw-filt-author\">person</literal>: Any text, but " "most useful for the <literal role=\"template-keyword\">author</literal> " "keyword. Yield the text before an email address. For example, " "<quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> " "becomes <quote><literal>Bryan O'Sullivan</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:369 msgid "" "<literal role=\"template-kw-filt-date\">rfc822date</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render a date using the same " "format used in email headers. Yields a string like <quote><literal>Mon, 04 " "Sep 2006 15:13:13 -0700</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:376 msgid "" "<literal role=\"template-kw-filt-node\">short</literal>: Changeset hash. " "Yield the short form of a changeset hash, i.e. a 12-character hexadecimal " "string." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:381 msgid "" "<literal role=\"template-kw-filt-date\">shortdate</literal>: <literal role=" "\"template-keyword\">date</literal> keyword. Render the year, month, and day " "of the date. Yields a string like <quote><literal>2006-09-04</literal></" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:387 msgid "" "<literal role=\"template-filter\">strip</literal>: Any text. Strip all " "leading and trailing whitespace from the string." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:391 msgid "" "<literal role=\"template-filter\">tabindent</literal>: Any text. Yield the " "text, with every line except the first starting with a tab character." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:396 msgid "" "<literal role=\"template-filter\">urlescape</literal>: Any text. Escape all " "characters that are considered <quote>special</quote> by URL parsers. For " "example, <literal>foo bar</literal> becomes <literal>foo%20bar</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch10-template.xml:403 msgid "" "<literal role=\"template-kw-filt-author\">user</literal>: Any text, but most " "useful for the <literal role=\"template-keyword\">author</literal> keyword. " "Return the <quote>user</quote> portion of an email address. For example, " "<quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> " "becomes <quote><literal>bos</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch10-template.xml:416 msgid "" "If you try to apply a filter to a piece of data that it cannot process, " "Mercurial will fail and print a Python exception. For example, trying to run " "the output of the <literal role=\"template-keyword\">desc</literal> keyword " "into the <literal role=\"template-kw-filt-date\">isodate</literal> filter is " "not a good idea." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:425 msgid "Combining filters" msgstr "组合过滤器" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:427 msgid "" "It is easy to combine filters to yield output in the form you would like. " "The following chain of filters tidies up a description, then makes sure that " "it fits cleanly into 68 columns, then indents it by a further 8 characters " "(at least on Unix-like systems, where a tab is conventionally 8 characters " "wide)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:436 msgid "" "Note the use of <quote><literal>\\t</literal></quote> (a tab character) in " "the template to force the first line to be indented; this is necessary since " "<literal role=\"template-keyword\">tabindent</literal> indents all lines " "<emphasis>except</emphasis> the first." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:442 msgid "" "Keep in mind that the order of filters in a chain is significant. The first " "filter is applied to the result of the keyword; the second to the result of " "the first filter; and so on. For example, using <literal>fill68|tabindent</" "literal> gives very different results from <literal>tabindent|fill68</" "literal>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:453 msgid "From templates to styles" msgstr "从模版到样式" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:455 msgid "" "A command line template provides a quick and simple way to format some " "output. Templates can become verbose, though, and it's useful to be able to " "give a template a name. A style file is a template with a name, stored in a " "file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:460 msgid "" "More than that, using a style file unlocks the power of Mercurial's " "templating engine in ways that are not possible using the command line " "<option role=\"hg-opt-log\">--template</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:466 msgid "The simplest of style files" msgstr "最简单的样式文件" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:468 msgid "Our simple style file contains just one line:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:472 msgid "" "This tells Mercurial, <quote>if you're printing a changeset, use the text on " "the right as the template</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:478 msgid "Style file syntax" msgstr "样式文件语法" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:480 msgid "The syntax rules for a style file are simple." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:483 msgid "The file is processed one line at a time." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:486 msgid "Leading and trailing white space are ignored." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:489 msgid "Empty lines are skipped." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:491 msgid "" "If a line starts with either of the characters <quote><literal>#</literal></" "quote> or <quote><literal>;</literal></quote>, the entire line is treated as " "a comment, and skipped as if empty." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:496 msgid "" "A line starts with a keyword. This must start with an alphabetic character " "or underscore, and can subsequently contain any alphanumeric character or " "underscore. (In regexp notation, a keyword must match <literal>[A-Za-z_][A-" "Za-z0-9_]*</literal>.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:502 msgid "" "The next element must be an <quote><literal>=</literal></quote> character, " "which can be preceded or followed by an arbitrary amount of white space." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:507 msgid "" "If the rest of the line starts and ends with matching quote characters " "(either single or double quote), it is treated as a template body." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:511 msgid "" "If the rest of the line <emphasis>does not</emphasis> start with a quote " "character, it is treated as the name of a file; the contents of this file " "will be read and used as a template body." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch10-template.xml:520 msgid "Style files by example" msgstr "样式文件例子" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch10-template.xml:522 msgid "" "To illustrate how to write a style file, we will construct a few by example. " "Rather than provide a complete style file and walk through it, we'll mirror " "the usual process of developing a style file by starting with something very " "simple, and walking through a series of successively more complete examples." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:529 msgid "Identifying mistakes in style files" msgstr "在样式文件中定位错误" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:531 msgid "" "If Mercurial encounters a problem in a style file you are working on, it " "prints a terse error message that, once you figure out what it means, is " "actually quite useful." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:537 msgid "" "Notice that <filename>broken.style</filename> attempts to define a " "<literal>changeset</literal> keyword, but forgets to give any content for it. " "When instructed to use this style file, Mercurial promptly complains." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:544 msgid "This error message looks intimidating, but it is not too hard to follow." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:548 msgid "" "The first component is simply Mercurial's way of saying <quote>I am giving " "up</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:552 msgid "Next comes the name of the style file that contains the error." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:556 msgid "" "Following the file name is the line number where the error was encountered." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:560 msgid "Finally, a description of what went wrong." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:564 msgid "" "The description of the problem is not always clear (as in this case), but " "even when it is cryptic, it is almost always trivial to visually inspect the " "offending line in the style file and see what is wrong." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:572 msgid "Uniquely identifying a repository" msgstr "版本库的唯一标识" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:574 msgid "" "If you would like to be able to identify a Mercurial repository <quote>fairly " "uniquely</quote> using a short string as an identifier, you can use the first " "revision in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:581 msgid "" "This is not guaranteed to be unique, but it is nevertheless useful in many " "cases." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:584 msgid "" "It will not work in a completely empty repository, because such a repository " "does not have a revision zero." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:588 msgid "" "Neither will it work in the (extremely rare) case where a repository is a " "merge of two or more formerly independent repositories, and you still have " "those repositories around." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:593 msgid "Here are some uses to which you could put this identifier:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:596 msgid "" "As a key into a table for a database that manages repositories on a server." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:599 msgid "" "As half of a {<emphasis>repository ID</emphasis>, <emphasis>revision ID</" "emphasis>} tuple. Save this information away when you run an automated build " "or other activity, so that you can <quote>replay</quote> the build later if " "necessary." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch10-template.xml:608 msgid "Mimicking Subversion's output" msgstr "模仿 Subversion 的输出" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:610 msgid "" "Let's try to emulate the default output format used by another revision " "control tool, Subversion." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:615 msgid "" "Since Subversion's output style is fairly simple, it is easy to copy-and-" "paste a hunk of its output into a file, and replace the text produced above " "by Subversion with the template values we'd like to see expanded." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:622 msgid "" "There are a few small ways in which this template deviates from the output " "produced by Subversion." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:625 msgid "" "Subversion prints a <quote>readable</quote> date (the <quote><literal>Wed, 27 " "Sep 2006</literal></quote> in the example output above) in parentheses. " "Mercurial's templating engine does not provide a way to display a date in " "this format without also printing the time and time zone." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:632 msgid "" "We emulate Subversion's printing of <quote>separator</quote> lines full of " "<quote><literal>-</literal></quote> characters by ending the template with " "such a line. We use the templating engine's <literal role=\"template-keyword" "\">header</literal> keyword to print a separator line as the first line of " "output (see below), thus achieving similar output to Subversion." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch10-template.xml:641 msgid "" "Subversion's output includes a count in the header of the number of lines in " "the commit message. We cannot replicate this in Mercurial; the templating " "engine does not currently provide a filter that counts the number of lines " "the template generates." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:647 msgid "" "It took me no more than a minute or two of work to replace literal text from " "an example of Subversion's output with some keywords and filters to give the " "template above. The style file simply refers to the template." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch10-template.xml:654 msgid "" "We could have included the text of the template file directly in the style " "file by enclosing it in quotes and replacing the newlines with " "<quote><literal>\\n</literal></quote> sequences, but it would have made the " "style file too difficult to read. Readability is a good guide when you're " "trying to decide whether some text belongs in a style file, or in a template " "file that the style file points to. If the style file will look too big or " "cluttered if you insert a literal piece of text, drop it into a template " "instead." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch11-mq.xml:5 msgid "Managing change with Mercurial Queues" msgstr "使用 MQ 管理修改" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:8 msgid "The patch management problem" msgstr "补丁的管理问题" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:10 msgid "" "Here is a common scenario: you need to install a software package from " "source, but you find a bug that you must fix in the source before you can " "start using the package. You make your changes, forget about the package for " "a while, and a few months later you need to upgrade to a newer version of the " "package. If the newer version of the package still has the bug, you must " "extract your fix from the older source tree and apply it against the newer " "version. This is a tedious task, and it's easy to make mistakes." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:20 msgid "" "This is a simple case of the <quote>patch management</quote> problem. You " "have an <quote>upstream</quote> source tree that you can't change; you need " "to make some local changes on top of the upstream tree; and you'd like to be " "able to keep those changes separate, so that you can apply them to newer " "versions of the upstream source." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:27 msgid "" "The patch management problem arises in many situations. Probably the most " "visible is that a user of an open source software project will contribute a " "bug fix or new feature to the project's maintainers in the form of a patch." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:32 msgid "" "Distributors of operating systems that include open source software often " "need to make changes to the packages they distribute so that they will build " "properly in their environments." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:37 msgid "" "When you have few changes to maintain, it is easy to manage a single patch " "using the standard <command>diff</command> and <command>patch</command> " "programs (see <xref linkend=\"sec:mq:patch\"/> for a discussion of these " "tools). Once the number of changes grows, it starts to make sense to maintain " "patches as discrete <quote>chunks of work,</quote> so that for example a " "single patch will contain only one bug fix (the patch might modify several " "files, but it's doing <quote>only one thing</quote>), and you may have a " "number of such patches for different bugs you need fixed and local changes " "you require. In this situation, if you submit a bug fix patch to the " "upstream maintainers of a package and they include your fix in a subsequent " "release, you can simply drop that single patch when you're updating to the " "newer release." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:52 msgid "" "Maintaining a single patch against an upstream tree is a little tedious and " "error-prone, but not difficult. However, the complexity of the problem grows " "rapidly as the number of patches you have to maintain increases. With more " "than a tiny number of patches in hand, understanding which ones you have " "applied and maintaining them moves from messy to overwhelming." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:59 msgid "" "Fortunately, Mercurial includes a powerful extension, Mercurial Queues (or " "simply <quote>MQ</quote>), that massively simplifies the patch management " "problem." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:65 msgid "The prehistory of Mercurial Queues" msgstr "MQ 的历史" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:67 msgid "" "During the late 1990s, several Linux kernel developers started to maintain " "<quote>patch series</quote> that modified the behaviour of the Linux kernel. " "Some of these series were focused on stability, some on feature coverage, and " "others were more speculative." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:73 msgid "" "The sizes of these patch series grew rapidly. In 2002, Andrew Morton " "published some shell scripts he had been using to automate the task of " "managing his patch queues. Andrew was successfully using these scripts to " "manage hundreds (sometimes thousands) of patches on top of the Linux kernel." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:80 msgid "A patchwork quilt" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:82 msgid "" "In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the approach " "of Andrew's scripts and published a tool called <quote>patchwork quilt</" "quote> <citation>web:quilt</citation>, or simply <quote>quilt</quote> (see " "<citation>gruenbacher:2005</citation> for a paper describing it). Because " "quilt substantially automated patch management, it rapidly gained a large " "following among open source software developers." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:91 msgid "" "Quilt manages a <emphasis>stack of patches</emphasis> on top of a directory " "tree. To begin, you tell quilt to manage a directory tree, and tell it which " "files you want to manage; it stores away the names and contents of those " "files. To fix a bug, you create a new patch (using a single command), edit " "the files you need to fix, then <quote>refresh</quote> the patch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:99 msgid "" "The refresh step causes quilt to scan the directory tree; it updates the " "patch with all of the changes you have made. You can create another patch on " "top of the first, which will track the changes required to modify the tree " "from <quote>tree with one patch applied</quote> to <quote>tree with two " "patches applied</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:106 msgid "" "You can <emphasis>change</emphasis> which patches are applied to the tree. " "If you <quote>pop</quote> a patch, the changes made by that patch will vanish " "from the directory tree. Quilt remembers which patches you have popped, " "though, so you can <quote>push</quote> a popped patch again, and the " "directory tree will be restored to contain the modifications in the patch. " "Most importantly, you can run the <quote>refresh</quote> command at any time, " "and the topmost applied patch will be updated. This means that you can, at " "any time, change both which patches are applied and what modifications those " "patches make." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:118 msgid "" "Quilt knows nothing about revision control tools, so it works equally well on " "top of an unpacked tarball or a Subversion working copy." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:124 msgid "From patchwork quilt to Mercurial Queues" msgstr "从 patchwork quilt 到 MQ" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:126 msgid "" "In mid-2005, Chris Mason took the features of quilt and wrote an extension " "that he called Mercurial Queues, which added quilt-like behaviour to " "Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:130 msgid "" "The key difference between quilt and MQ is that quilt knows nothing about " "revision control systems, while MQ is <emphasis>integrated</emphasis> into " "Mercurial. Each patch that you push is represented as a Mercurial " "changeset. Pop a patch, and the changeset goes away." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:136 msgid "" "Because quilt does not care about revision control tools, it is still a " "tremendously useful piece of software to know about for situations where you " "cannot use Mercurial and MQ." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:144 msgid "The huge advantage of MQ" msgstr "MQ 的巨大优势" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:146 msgid "" "I cannot overstate the value that MQ offers through the unification of " "patches and revision control." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:149 msgid "" "A major reason that patches have persisted in the free software and open " "source world&emdash;in spite of the availability of increasingly capable " "revision control tools over the years&emdash;is the <emphasis>agility</" "emphasis> they offer." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:155 msgid "" "Traditional revision control tools make a permanent, irreversible record of " "everything that you do. While this has great value, it's also somewhat " "stifling. If you want to perform a wild-eyed experiment, you have to be " "careful in how you go about it, or you risk leaving unneeded&emdash;or worse, " "misleading or destabilising&emdash;traces of your missteps and errors in the " "permanent revision record." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:163 msgid "" "By contrast, MQ's marriage of distributed revision control with patches makes " "it much easier to isolate your work. Your patches live on top of normal " "revision history, and you can make them disappear or reappear at will. If " "you don't like a patch, you can drop it. If a patch isn't quite as you want " "it to be, simply fix it&emdash;as many times as you need to, until you have " "refined it into the form you desire." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:171 msgid "" "As an example, the integration of patches with revision control makes " "understanding patches and debugging their effects&emdash;and their interplay " "with the code they're based on&emdash;<emphasis>enormously</emphasis> easier. " "Since every applied patch has an associated changeset, you can give <command " "role=\"hg-cmd\">hg log</command> a file name to see which changesets and " "patches affected the file. You can use the <command role=\"hg-cmd\">hg " "bisect</command> command to binary-search through all changesets and applied " "patches to see where a bug got introduced or fixed. You can use the <command " "role=\"hg-cmd\">hg annotate</command> command to see which changeset or patch " "modified a particular line of a source file. And so on." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:189 msgid "" "Because MQ doesn't hide its patch-oriented nature, it is helpful to " "understand what patches are, and a little about the tools that work with them." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:193 msgid "" "The traditional Unix <command>diff</command> command compares two files, and " "prints a list of differences between them. The <command>patch</command> " "command understands these differences as <emphasis>modifications</emphasis> " "to make to a file. Take a look below for a simple example of these commands " "in action." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:202 msgid "" "The type of file that <command>diff</command> generates (and <command>patch</" "command> takes as input) is called a <quote>patch</quote> or a <quote>diff</" "quote>; there is no difference between a patch and a diff. (We'll use the " "term <quote>patch</quote>, since it's more commonly used.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:208 msgid "" "A patch file can start with arbitrary text; the <command>patch</command> " "command ignores this text, but MQ uses it as the commit message when creating " "changesets. To find the beginning of the patch content, <command>patch</" "command> searches for the first line that starts with the string " "<quote><literal>diff -</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:215 msgid "" "MQ works with <emphasis>unified</emphasis> diffs (<command>patch</command> " "can accept several other diff formats, but MQ doesn't). A unified diff " "contains two kinds of header. The <emphasis>file header</emphasis> describes " "the file being modified; it contains the name of the file to modify. When " "<command>patch</command> sees a new file header, it looks for a file with " "that name to start modifying." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:223 msgid "" "After the file header comes a series of <emphasis>hunks</emphasis>. Each " "hunk starts with a header; this identifies the range of line numbers within " "the file that the hunk should modify. Following the header, a hunk starts " "and ends with a few (usually three) lines of text from the unmodified file; " "these are called the <emphasis>context</emphasis> for the hunk. If there's " "only a small amount of context between successive hunks, <command>diff</" "command> doesn't print a new hunk header; it just runs the hunks together, " "with a few lines of context between modifications." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:235 msgid "" "Each line of context begins with a space character. Within the hunk, a line " "that begins with <quote><literal>-</literal></quote> means <quote>remove this " "line,</quote> while a line that begins with <quote><literal>+</literal></" "quote> means <quote>insert this line.</quote> For example, a line that is " "modified is represented by one deletion and one insertion." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:243 msgid "" "We will return to some of the more subtle aspects of patches later (in <xref " "linkend=\"sec:mq:adv-patch\"/>), but you should have enough information now " "to use MQ." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:250 msgid "Getting started with Mercurial Queues" msgstr "开始使用 MQ" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:252 msgid "" "Because MQ is implemented as an extension, you must explicitly enable before " "you can use it. (You don't need to download anything; MQ ships with the " "standard Mercurial distribution.) To enable MQ, edit your <filename role=" "\"home\">~/.hgrc</filename> file, and add the lines below." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:262 msgid "" "Once the extension is enabled, it will make a number of new commands " "available. To verify that the extension is working, you can use <command " "role=\"hg-cmd\">hg help</command> to see if the <command role=\"hg-ext-mq" "\">qinit</command> command is now available." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:270 msgid "" "You can use MQ with <emphasis>any</emphasis> Mercurial repository, and its " "commands only operate within that repository. To get started, simply prepare " "the repository using the <command role=\"hg-ext-mq\">qinit</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:277 msgid "" "This command creates an empty directory called <filename role=\"special\" " "class=\"directory\">.hg/patches</filename>, where MQ will keep its metadata. " "As with many Mercurial commands, the <command role=\"hg-ext-mq\">qinit</" "command> command prints nothing if it succeeds." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:284 msgid "Creating a new patch" msgstr "创建新补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:286 msgid "" "To begin work on a new patch, use the <command role=\"hg-ext-mq\">qnew</" "command> command. This command takes one argument, the name of the patch to " "create." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:290 msgid "" "MQ will use this as the name of an actual file in the <filename role=\"special" "\" class=\"directory\">.hg/patches</filename> directory, as you can see below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:297 msgid "" "Also newly present in the <filename role=\"special\" class=\"directory\">.hg/" "patches</filename> directory are two other files, <filename role=\"special" "\">series</filename> and <filename role=\"special\">status</filename>. The " "<filename role=\"special\">series</filename> file lists all of the patches " "that MQ knows about for this repository, with one patch per line. Mercurial " "uses the <filename role=\"special\">status</filename> file for internal book-" "keeping; it tracks all of the patches that MQ has <emphasis>applied</" "emphasis> in this repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch11-mq.xml:309 msgid "" "You may sometimes want to edit the <filename role=\"special\">series</" "filename> file by hand; for example, to change the sequence in which some " "patches are applied. However, manually editing the <filename role=\"special" "\">status</filename> file is almost always a bad idea, as it's easy to " "corrupt MQ's idea of what is happening." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:318 msgid "" "Once you have created your new patch, you can edit files in the working " "directory as you usually would. All of the normal Mercurial commands, such " "as <command role=\"hg-cmd\">hg diff</command> and <command role=\"hg-cmd\">hg " "annotate</command>, work exactly as they did before." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:326 msgid "Refreshing a patch" msgstr "刷新补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:328 msgid "" "When you reach a point where you want to save your work, use the <command " "role=\"hg-ext-mq\">qrefresh</command> command to update the patch you are " "working on." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:334 msgid "" "This command folds the changes you have made in the working directory into " "your patch, and updates its corresponding changeset to contain those changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:338 msgid "" "You can run <command role=\"hg-ext-mq\">qrefresh</command> as often as you " "like, so it's a good way to <quote>checkpoint</quote> your work. Refresh " "your patch at an opportune time; try an experiment; and if the experiment " "doesn't work out, <command role=\"hg-cmd\">hg revert</command> your " "modifications back to the last time you refreshed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:349 msgid "Stacking and tracking patches" msgstr "堆叠和跟踪补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:351 msgid "" "Once you have finished working on a patch, or need to work on another, you " "can use the <command role=\"hg-ext-mq\">qnew</command> command again to " "create a new patch. Mercurial will apply this patch on top of your existing " "patch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:358 msgid "" "Notice that the patch contains the changes in our prior patch as part of its " "context (you can see this more clearly in the output of <command role=\"hg-cmd" "\">hg annotate</command>)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:363 msgid "" "So far, with the exception of <command role=\"hg-ext-mq\">qnew</command> and " "<command role=\"hg-ext-mq\">qrefresh</command>, we've been careful to only " "use regular Mercurial commands. However, MQ provides many commands that are " "easier to use when you are thinking about patches, as illustrated below." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:373 msgid "" "The <command role=\"hg-ext-mq\">qseries</command> command lists every patch " "that MQ knows about in this repository, from oldest to newest (most recently " "<emphasis>created</emphasis>)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:379 msgid "" "The <command role=\"hg-ext-mq\">qapplied</command> command lists every patch " "that MQ has <emphasis>applied</emphasis> in this repository, again from " "oldest to newest (most recently applied)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:388 msgid "Manipulating the patch stack" msgstr "操作补丁堆栈" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:390 msgid "" "The previous discussion implied that there must be a difference between " "<quote>known</quote> and <quote>applied</quote> patches, and there is. MQ " "can manage a patch without it being applied in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:395 msgid "" "An <emphasis>applied</emphasis> patch has a corresponding changeset in the " "repository, and the effects of the patch and changeset are visible in the " "working directory. You can undo the application of a patch using the " "<command role=\"hg-ext-mq\">qpop</command> command. MQ still <emphasis>knows " "about</emphasis>, or manages, a popped patch, but the patch no longer has a " "corresponding changeset in the repository, and the working directory does not " "contain the changes made by the patch. <xref linkend=\"fig:mq:stack\"/> " "illustrates the difference between applied and tracked patches." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><figure><title> #: ../en/ch11-mq.xml:408 msgid "Applied and unapplied patches in the MQ patch stack" msgstr "在 MQ 补丁堆栈中应用和撤销补丁" #. type: Content of: <book><chapter><sect1><sect2><figure><mediaobject> #: ../en/ch11-mq.xml:411 msgid "<imageobject><imagedata fileref=\"figs/mq-stack.png\"/></imageobject>" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:416 msgid "" "You can reapply an unapplied, or popped, patch using the <command role=\"hg-" "ext-mq\">qpush</command> command. This creates a new changeset to correspond " "to the patch, and the patch's changes once again become present in the " "working directory. See below for examples of <command role=\"hg-ext-mq" "\">qpop</command> and <command role=\"hg-ext-mq\">qpush</command> in action." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:425 msgid "" "Notice that once we have popped a patch or two patches, the output of " "<command role=\"hg-ext-mq\">qseries</command> remains the same, while that of " "<command role=\"hg-ext-mq\">qapplied</command> has changed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:433 msgid "Pushing and popping many patches" msgstr "压入或弹出多个补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:435 msgid "" "While <command role=\"hg-ext-mq\">qpush</command> and <command role=\"hg-ext-" "mq\">qpop</command> each operate on a single patch at a time by default, you " "can push and pop many patches in one go. The <option role=\"hg-ext-mq-cmd-" "qpush-opt\">hg -a</option> option to <command role=\"hg-ext-mq\">qpush</" "command> causes it to push all unapplied patches, while the <option role=\"hg-" "ext-mq-cmd-qpop-opt\">-a</option> option to <command role=\"hg-ext-mq\">qpop</" "command> causes it to pop all applied patches. (For some more ways to push " "and pop many patches, see <xref linkend=\"sec:mq:perf\"/> below.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:451 msgid "Safety checks, and overriding them" msgstr "安全的检查,然后覆盖它们" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:453 msgid "" "Several MQ commands check the working directory before they do anything, and " "fail if they find any modifications. They do this to ensure that you won't " "lose any changes that you have made, but not yet incorporated into a patch. " "The example below illustrates this; the <command role=\"hg-ext-mq\">qnew</" "command> command will not create a new patch if there are outstanding " "changes, caused in this case by the <command role=\"hg-cmd\">hg add</command> " "of <filename>file3</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:465 msgid "" "Commands that check the working directory all take an <quote>I know what I'm " "doing</quote> option, which is always named <option>-f</option>. The exact " "meaning of <option>-f</option> depends on the command. For example, <command " "role=\"hg-cmd\">hg qnew <option role=\"hg-ext-mq-cmd-qnew-opt\">hg -f</" "option></command> will incorporate any outstanding changes into the new patch " "it creates, but <command role=\"hg-cmd\">hg qpop <option role=\"hg-ext-mq-cmd-" "qpop-opt\">hg -f</option></command> will revert modifications to any files " "affected by the patch that it is popping. Be sure to read the documentation " "for a command's <option>-f</option> option before you use it!" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:480 msgid "Working on several patches at once" msgstr "同时处理多个补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:482 msgid "" "The <command role=\"hg-ext-mq\">qrefresh</command> command always refreshes " "the <emphasis>topmost</emphasis> applied patch. This means that you can " "suspend work on one patch (by refreshing it), pop or push to make a different " "patch the top, and work on <emphasis>that</emphasis> patch for a while." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:489 msgid "" "Here's an example that illustrates how you can use this ability. Let's say " "you're developing a new feature as two patches. The first is a change to the " "core of your software, and the second&emdash;layered on top of the " "first&emdash;changes the user interface to use the code you just added to the " "core. If you notice a bug in the core while you're working on the UI patch, " "it's easy to fix the core. Simply <command role=\"hg-ext-mq\">qrefresh</" "command> the UI patch to save your in-progress changes, and <command role=" "\"hg-ext-mq\">qpop</command> down to the core patch. Fix the core bug, " "<command role=\"hg-ext-mq\">qrefresh</command> the core patch, and <command " "role=\"hg-ext-mq\">qpush</command> back to the UI patch to continue where you " "left off." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:506 msgid "More about patches" msgstr "关于补丁的更多信息" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:508 msgid "" "MQ uses the GNU <command>patch</command> command to apply patches, so it's " "helpful to know a few more detailed aspects of how <command>patch</command> " "works, and about patches themselves." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:514 msgid "The strip count" msgstr "修剪计数" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:516 msgid "" "If you look at the file headers in a patch, you will notice that the " "pathnames usually have an extra component on the front that isn't present in " "the actual path name. This is a holdover from the way that people used to " "generate patches (people still do this, but it's somewhat rare with modern " "revision control tools)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:523 msgid "" "Alice would unpack a tarball, edit her files, then decide that she wanted to " "create a patch. So she'd rename her working directory, unpack the tarball " "again (hence the need for the rename), and use the <option role=\"cmd-opt-diff" "\">-r</option> and <option role=\"cmd-opt-diff\">-N</option> options to " "<command>diff</command> to recursively generate a patch between the " "unmodified directory and the modified one. The result would be that the name " "of the unmodified directory would be at the front of the left-hand path in " "every file header, and the name of the modified directory would be at the " "front of the right-hand path." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:536 msgid "" "Since someone receiving a patch from the Alices of the net would be unlikely " "to have unmodified and modified directories with exactly the same names, the " "<command>patch</command> command has a <option role=\"cmd-opt-patch\">-p</" "option> option that indicates the number of leading path name components to " "strip when trying to apply a patch. This number is called the " "<emphasis>strip count</emphasis>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:544 msgid "" "An option of <quote><literal>-p1</literal></quote> means <quote>use a strip " "count of one</quote>. If <command>patch</command> sees a file name " "<filename>foo/bar/baz</filename> in a file header, it will strip " "<filename>foo</filename> and try to patch a file named <filename>bar/baz</" "filename>. (Strictly speaking, the strip count refers to the number of " "<emphasis>path separators</emphasis> (and the components that go with them ) " "to strip. A strip count of one will turn <filename>foo/bar</filename> into " "<filename>bar</filename>, but <filename>/foo/bar</filename> (notice the extra " "leading slash) into <filename>foo/bar</filename>.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:557 msgid "" "The <quote>standard</quote> strip count for patches is one; almost all " "patches contain one leading path name component that needs to be stripped. " "Mercurial's <command role=\"hg-cmd\">hg diff</command> command generates path " "names in this form, and the <command role=\"hg-cmd\">hg import</command> " "command and MQ expect patches to have a strip count of one." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:565 msgid "" "If you receive a patch from someone that you want to add to your patch queue, " "and the patch needs a strip count other than one, you cannot just <command " "role=\"hg-ext-mq\">qimport</command> the patch, because <command role=\"hg-" "ext-mq\">qimport</command> does not yet have a <literal>-p</literal> option " "(see <ulink role=\"hg-bug\" url=\"http://www.selenic.com/mercurial/bts/" "issue311\">issue 311</ulink>). Your best bet is to <command role=\"hg-ext-mq" "\">qnew</command> a patch of your own, then use <command>patch -pN</command> " "to apply their patch, followed by <command role=\"hg-cmd\">hg addremove</" "command> to pick up any files added or removed by the patch, followed by " "<command role=\"hg-ext-mq\">hg qrefresh</command>. This complexity may become " "unnecessary; see <ulink role=\"hg-bug\" url=\"http://www.selenic.com/" "mercurial/bts/issue311\">issue 311</ulink> for details." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:584 msgid "Strategies for applying a patch" msgstr "应用补丁的策略" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:586 msgid "" "When <command>patch</command> applies a hunk, it tries a handful of " "successively less accurate strategies to try to make the hunk apply. This " "falling-back technique often makes it possible to take a patch that was " "generated against an old version of a file, and apply it against a newer " "version of that file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:593 msgid "" "First, <command>patch</command> tries an exact match, where the line numbers, " "the context, and the text to be modified must apply exactly. If it cannot " "make an exact match, it tries to find an exact match for the context, without " "honouring the line numbering information. If this succeeds, it prints a line " "of output saying that the hunk was applied, but at some <emphasis>offset</" "emphasis> from the original line number." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:602 msgid "" "If a context-only match fails, <command>patch</command> removes the first and " "last lines of the context, and tries a <emphasis>reduced</emphasis> context-" "only match. If the hunk with reduced context succeeds, it prints a message " "saying that it applied the hunk with a <emphasis>fuzz factor</emphasis> (the " "number after the fuzz factor indicates how many lines of context " "<command>patch</command> had to trim before the patch applied)." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:611 msgid "" "When neither of these techniques works, <command>patch</command> prints a " "message saying that the hunk in question was rejected. It saves rejected " "hunks (also simply called <quote>rejects</quote>) to a file with the same " "name, and an added <filename role=\"special\">.rej</filename> extension. It " "also saves an unmodified copy of the file with a <filename role=\"special\">." "orig</filename> extension; the copy of the file without any extensions will " "contain any changes made by hunks that <emphasis>did</emphasis> apply " "cleanly. If you have a patch that modifies <filename>foo</filename> with six " "hunks, and one of them fails to apply, you will have: an unmodified " "<filename>foo.orig</filename>, a <filename>foo.rej</filename> containing one " "hunk, and <filename>foo</filename>, containing the changes made by the five " "successful hunks." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:629 msgid "Some quirks of patch representation" msgstr "补丁的一些特性" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:631 msgid "" "There are a few useful things to know about how <command>patch</command> " "works with files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:634 msgid "" "This should already be obvious, but <command>patch</command> cannot handle " "binary files." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:638 msgid "" "Neither does it care about the executable bit; it creates new files as " "readable, but not executable." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:642 msgid "" "<command>patch</command> treats the removal of a file as a diff between the " "file to be removed and the empty file. So your idea of <quote>I deleted this " "file</quote> looks like <quote>every line of this file was deleted</quote> in " "a patch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:648 msgid "" "It treats the addition of a file as a diff between the empty file and the " "file to be added. So in a patch, your idea of <quote>I added this file</" "quote> looks like <quote>every line of this file was added</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:654 msgid "" "It treats a renamed file as the removal of the old name, and the addition of " "the new name. This means that renamed files have a big footprint in " "patches. (Note also that Mercurial does not currently try to infer when " "files have been renamed or copied in a patch.)" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:660 msgid "" "<command>patch</command> cannot represent empty files, so you cannot use a " "patch to represent the notion <quote>I added this empty file to the tree</" "quote>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:667 msgid "Beware the fuzz" msgstr "当心毛刺" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:669 msgid "" "While applying a hunk at an offset, or with a fuzz factor, will often be " "completely successful, these inexact techniques naturally leave open the " "possibility of corrupting the patched file. The most common cases typically " "involve applying a patch twice, or at an incorrect location in the file. If " "<command>patch</command> or <command role=\"hg-ext-mq\">qpush</command> ever " "mentions an offset or fuzz factor, you should make sure that the modified " "files are correct afterwards." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:679 msgid "" "It's often a good idea to refresh a patch that has applied with an offset or " "fuzz factor; refreshing the patch generates new context information that will " "make it apply cleanly. I say <quote>often,</quote> not <quote>always,</" "quote> because sometimes refreshing a patch will make it fail to apply " "against a different revision of the underlying files. In some cases, such as " "when you're maintaining a patch that must sit on top of multiple versions of " "a source tree, it's acceptable to have a patch apply with some fuzz, provided " "you've verified the results of the patching process in such cases." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:692 msgid "Handling rejection" msgstr "处理拒绝" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:694 msgid "" "If <command role=\"hg-ext-mq\">qpush</command> fails to apply a patch, it " "will print an error message and exit. If it has left <filename role=\"special" "\">.rej</filename> files behind, it is usually best to fix up the rejected " "hunks before you push more patches or do any further work." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:700 msgid "" "If your patch <emphasis>used to</emphasis> apply cleanly, and no longer does " "because you've changed the underlying code that your patches are based on, " "Mercurial Queues can help; see <xref linkend=\"sec:mq:merge\"/> for details." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:705 msgid "" "Unfortunately, there aren't any great techniques for dealing with rejected " "hunks. Most often, you'll need to view the <filename role=\"special\">.rej</" "filename> file and edit the target file, applying the rejected hunks by hand." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:710 msgid "" "If you're feeling adventurous, Neil Brown, a Linux kernel hacker, wrote a " "tool called <command>wiggle</command> <citation>web:wiggle</citation>, which " "is more vigorous than <command>patch</command> in its attempts to make a " "patch apply." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:716 msgid "" "Another Linux kernel hacker, Chris Mason (the author of Mercurial Queues), " "wrote a similar tool called <command>mpatch</command> <citation>web:mpatch</" "citation>, which takes a simple approach to automating the application of " "hunks rejected by <command>patch</command>. The <command>mpatch</command> " "command can help with four common reasons that a hunk may be rejected:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:725 msgid "The context in the middle of a hunk has changed." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:728 msgid "A hunk is missing some context at the beginning or end." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:731 msgid "" "A large hunk might apply better&emdash;either entirely or in part&emdash;if " "it was broken up into smaller hunks." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:735 msgid "" "A hunk removes lines with slightly different content than those currently " "present in the file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:739 msgid "" "If you use <command>wiggle</command> or <command>mpatch</command>, you should " "be doubly careful to check your results when you're done. In fact, " "<command>mpatch</command> enforces this method of double-checking the tool's " "output, by automatically dropping you into a merge program when it has done " "its job, so that you can verify its work and finish off any remaining merges." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:751 msgid "Getting the best performance out of MQ" msgstr "MQ 的性能" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:753 msgid "" "MQ is very efficient at handling a large number of patches. I ran some " "performance experiments in mid-2006 for a talk that I gave at the 2006 " "EuroPython conference <citation>web:europython</citation>. I used as my data " "set the Linux 2.6.17-mm1 patch series, which consists of 1,738 patches. I " "applied these on top of a Linux kernel repository containing all 27,472 " "revisions between Linux 2.6.12-rc2 and Linux 2.6.17." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:762 msgid "" "On my old, slow laptop, I was able to <command role=\"hg-cmd\">hg qpush " "<option role=\"hg-ext-mq-cmd-qpush-opt\">hg -a</option></command> all 1,738 " "patches in 3.5 minutes, and <command role=\"hg-cmd\">hg qpop <option role=" "\"hg-ext-mq-cmd-qpop-opt\">hg -a</option></command> them all in 30 seconds. " "(On a newer laptop, the time to push all patches dropped to two minutes.) I " "could <command role=\"hg-ext-mq\">qrefresh</command> one of the biggest " "patches (which made 22,779 lines of changes to 287 files) in 6.6 seconds." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:773 msgid "" "Clearly, MQ is well suited to working in large trees, but there are a few " "tricks you can use to get the best performance of it." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:777 msgid "" "First of all, try to <quote>batch</quote> operations together. Every time " "you run <command role=\"hg-ext-mq\">qpush</command> or <command role=\"hg-ext-" "mq\">qpop</command>, these commands scan the working directory once to make " "sure you haven't made some changes and then forgotten to run <command role=" "\"hg-ext-mq\">qrefresh</command>. On a small tree, the time that this scan " "takes is unnoticeable. However, on a medium-sized tree (containing tens of " "thousands of files), it can take a second or more." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:788 msgid "" "The <command role=\"hg-ext-mq\">qpush</command> and <command role=\"hg-ext-mq" "\">qpop</command> commands allow you to push and pop multiple patches at a " "time. You can identify the <quote>destination patch</quote> that you want to " "end up at. When you <command role=\"hg-ext-mq\">qpush</command> with a " "destination specified, it will push patches until that patch is at the top of " "the applied stack. When you <command role=\"hg-ext-mq\">qpop</command> to a " "destination, MQ will pop patches until the destination patch is at the top." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:798 msgid "" "You can identify a destination patch using either the name of the patch, or " "by number. If you use numeric addressing, patches are counted from zero; " "this means that the first patch is zero, the second is one, and so on." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:805 msgid "Updating your patches when the underlying code changes" msgstr "当基础代码改变时,更新补丁的方法" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:808 msgid "" "It's common to have a stack of patches on top of an underlying repository " "that you don't modify directly. If you're working on changes to third-party " "code, or on a feature that is taking longer to develop than the rate of " "change of the code beneath, you will often need to sync up with the " "underlying code, and fix up any hunks in your patches that no longer apply. " "This is called <emphasis>rebasing</emphasis> your patch series." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:817 msgid "" "The simplest way to do this is to <command role=\"hg-cmd\">hg qpop <option " "role=\"hg-ext-mq-cmd-qpop-opt\">hg -a</option></command> your patches, then " "<command role=\"hg-cmd\">hg pull</command> changes into the underlying " "repository, and finally <command role=\"hg-cmd\">hg qpush <option role=\"hg-" "ext-mq-cmd-qpop-opt\">hg -a</option></command> your patches again. MQ will " "stop pushing any time it runs across a patch that fails to apply during " "conflicts, allowing you to fix your conflicts, <command role=\"hg-ext-mq" "\">qrefresh</command> the affected patch, and continue pushing until you have " "fixed your entire stack." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:829 msgid "" "This approach is easy to use and works well if you don't expect changes to " "the underlying code to affect how well your patches apply. If your patch " "stack touches code that is modified frequently or invasively in the " "underlying repository, however, fixing up rejected hunks by hand quickly " "becomes tiresome." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:836 msgid "" "It's possible to partially automate the rebasing process. If your patches " "apply cleanly against some revision of the underlying repo, MQ can use this " "information to help you to resolve conflicts between your patches and a " "different revision." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:842 msgid "The process is a little involved." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch11-mq.xml:844 msgid "" "To begin, <command role=\"hg-cmd\">hg qpush -a</command> all of your patches " "on top of the revision where you know that they apply cleanly." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch11-mq.xml:848 msgid "" "Save a backup copy of your patch directory using <command role=\"hg-cmd\">hg " "qsave <option role=\"hg-ext-mq-cmd-qsave-opt\">hg -e</option> <option role=" "\"hg-ext-mq-cmd-qsave-opt\">hg -c</option></command>. This prints the name " "of the directory that it has saved the patches in. It will save the patches " "to a directory called <filename role=\"special\" class=\"directory\">.hg/" "patches.N</filename>, where <literal>N</literal> is a small integer. It also " "commits a <quote>save changeset</quote> on top of your applied patches; this " "is for internal book-keeping, and records the states of the <filename role=" "\"special\">series</filename> and <filename role=\"special\">status</" "filename> files." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch11-mq.xml:862 msgid "" "Use <command role=\"hg-cmd\">hg pull</command> to bring new changes into the " "underlying repository. (Don't run <command role=\"hg-cmd\">hg pull -u</" "command>; see below for why.)" msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch11-mq.xml:867 msgid "" "Update to the new tip revision, using <command role=\"hg-cmd\">hg update " "<option role=\"hg-opt-update\">-C</option></command> to override the patches " "you have pushed." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch11-mq.xml:872 msgid "" "Merge all patches using <command>hg qpush -m -a</command>. The <option role=" "\"hg-ext-mq-cmd-qpush-opt\">-m</option> option to <command role=\"hg-ext-mq" "\">qpush</command> tells MQ to perform a three-way merge if the patch fails " "to apply." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:880 msgid "" "During the <command role=\"hg-cmd\">hg qpush <option role=\"hg-ext-mq-cmd-" "qpush-opt\">hg -m</option></command>, each patch in the <filename role=" "\"special\">series</filename> file is applied normally. If a patch applies " "with fuzz or rejects, MQ looks at the queue you <command role=\"hg-ext-mq" "\">qsave</command>d, and performs a three-way merge with the corresponding " "changeset. This merge uses Mercurial's normal merge machinery, so it may pop " "up a GUI merge tool to help you to resolve problems." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:890 msgid "" "When you finish resolving the effects of a patch, MQ refreshes your patch " "based on the result of the merge." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:893 msgid "" "At the end of this process, your repository will have one extra head from the " "old patch queue, and a copy of the old patch queue will be in <filename role=" "\"special\" class=\"directory\">.hg/patches.N</filename>. You can remove the " "extra head using <command role=\"hg-cmd\">hg qpop -a -n patches.N</command> " "or <command role=\"hg-cmd\">hg strip</command>. You can delete <filename " "role=\"special\" class=\"directory\">.hg/patches.N</filename> once you are " "sure that you no longer need it as a backup." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:905 msgid "Identifying patches" msgstr "标识补丁" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:907 msgid "" "MQ commands that work with patches let you refer to a patch either by using " "its name or by a number. By name is obvious enough; pass the name " "<filename>foo.patch</filename> to <command role=\"hg-ext-mq\">qpush</" "command>, for example, and it will push patches until <filename>foo.patch</" "filename> is applied." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:914 msgid "" "As a shortcut, you can refer to a patch using both a name and a numeric " "offset; <literal>foo.patch-2</literal> means <quote>two patches before " "<literal>foo.patch</literal></quote>, while <literal>bar.patch+4</literal> " "means <quote>four patches after <literal>bar.patch</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:920 msgid "" "Referring to a patch by index isn't much different. The first patch printed " "in the output of <command role=\"hg-ext-mq\">qseries</command> is patch zero " "(yes, it's one of those start-at-zero counting systems); the second is patch " "one; and so on." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:926 msgid "" "MQ also makes it easy to work with patches when you are using normal " "Mercurial commands. Every command that accepts a changeset ID will also " "accept the name of an applied patch. MQ augments the tags normally in the " "repository with an eponymous one for each applied patch. In addition, the " "special tags <literal role=\"tag\">qbase</literal> and <literal role=\"tag" "\">qtip</literal> identify the <quote>bottom-most</quote> and topmost applied " "patches, respectively." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:936 msgid "" "These additions to Mercurial's normal tagging capabilities make dealing with " "patches even more of a breeze." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:939 msgid "Want to patchbomb a mailing list with your latest series of changes?" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:942 msgid "" "(Don't know what <quote>patchbombing</quote> is? See <xref linkend=\"sec:" "hgext:patchbomb\"/>.)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:945 msgid "" "Need to see all of the patches since <literal>foo.patch</literal> that have " "touched files in a subdirectory of your tree?" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:952 msgid "" "Because MQ makes the names of patches available to the rest of Mercurial " "through its normal internal tag machinery, you don't need to type in the " "entire name of a patch when you want to identify it by name." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:957 msgid "" "Another nice consequence of representing patch names as tags is that when you " "run the <command role=\"hg-cmd\">hg log</command> command, it will display a " "patch's name as a tag, simply as part of its normal output. This makes it " "easy to visually distinguish applied patches from underlying <quote>normal</" "quote> revisions. The following example shows a few normal Mercurial " "commands in use with applied patches." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:970 msgid "Useful things to know about" msgstr "其它需要了解的东西" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:972 msgid "" "There are a number of aspects of MQ usage that don't fit tidily into sections " "of their own, but that are good to know. Here they are, in one place." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:977 msgid "" "Normally, when you <command role=\"hg-ext-mq\">qpop</command> a patch and " "<command role=\"hg-ext-mq\">qpush</command> it again, the changeset that " "represents the patch after the pop/push will have a <emphasis>different " "identity</emphasis> than the changeset that represented the hash beforehand. " "See <xref linkend=\"sec:mqref:cmd:qpush\"/> for information as to why this is." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:986 msgid "" "It's not a good idea to <command role=\"hg-cmd\">hg merge</command> changes " "from another branch with a patch changeset, at least if you want to maintain " "the <quote>patchiness</quote> of that changeset and changesets below it on " "the patch stack. If you try to do this, it will appear to succeed, but MQ " "will become confused." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:997 msgid "Managing patches in a repository" msgstr "在版本库管理补丁" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:999 msgid "" "Because MQ's <filename role=\"special\" class=\"directory\">.hg/patches</" "filename> directory resides outside a Mercurial repository's working " "directory, the <quote>underlying</quote> Mercurial repository knows nothing " "about the management or presence of patches." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1005 msgid "" "This presents the interesting possibility of managing the contents of the " "patch directory as a Mercurial repository in its own right. This can be a " "useful way to work. For example, you can work on a patch for a while, " "<command role=\"hg-ext-mq\">qrefresh</command> it, then <command role=\"hg-cmd" "\">hg commit</command> the current state of the patch. This lets you " "<quote>roll back</quote> to that version of the patch later on." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1014 msgid "" "You can then share different versions of the same patch stack among multiple " "underlying repositories. I use this when I am developing a Linux kernel " "feature. I have a pristine copy of my kernel sources for each of several CPU " "architectures, and a cloned repository under each that contains the patches I " "am working on. When I want to test a change on a different architecture, I " "push my current patches to the patch repository associated with that kernel " "tree, pop and push all of my patches, and build and test that kernel." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1024 msgid "" "Managing patches in a repository makes it possible for multiple developers to " "work on the same patch series without colliding with each other, all on top " "of an underlying source base that they may or may not control." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:1030 msgid "MQ support for patch repositories" msgstr "MQ 支持补丁版本库" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1032 msgid "" "MQ helps you to work with the <filename role=\"special\" class=\"directory\">." "hg/patches</filename> directory as a repository; when you prepare a " "repository for working with patches using <command role=\"hg-ext-mq\">qinit</" "command>, you can pass the <option role=\"hg-ext-mq-cmd-qinit-opt\">hg -c</" "option> option to create the <filename role=\"special\" class=\"directory\">." "hg/patches</filename> directory as a Mercurial repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch11-mq.xml:1042 msgid "" "If you forget to use the <option role=\"hg-ext-mq-cmd-qinit-opt\">hg -c</" "option> option, you can simply go into the <filename role=\"special\" class=" "\"directory\">.hg/patches</filename> directory at any time and run <command " "role=\"hg-cmd\">hg init</command>. Don't forget to add an entry for the " "<filename role=\"special\">status</filename> file to the <filename role=" "\"special\">.hgignore</filename> file, though" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch11-mq.xml:1051 msgid "" "(<command role=\"hg-cmd\">hg qinit <option role=\"hg-ext-mq-cmd-qinit-opt" "\">hg -c</option></command> does this for you automatically); you " "<emphasis>really</emphasis> don't want to manage the <filename role=\"special" "\">status</filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1058 msgid "" "As a convenience, if MQ notices that the <filename class=\"directory\">.hg/" "patches</filename> directory is a repository, it will automatically <command " "role=\"hg-cmd\">hg add</command> every patch that you create and import." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1063 msgid "" "MQ provides a shortcut command, <command role=\"hg-ext-mq\">qcommit</" "command>, that runs <command role=\"hg-cmd\">hg commit</command> in the " "<filename role=\"special\" class=\"directory\">.hg/patches</filename> " "directory. This saves some bothersome typing." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1069 msgid "" "Finally, as a convenience to manage the patch directory, you can define the " "alias <command>mq</command> on Unix systems. For example, on Linux systems " "using the <command>bash</command> shell, you can include the following " "snippet in your <filename role=\"home\">~/.bashrc</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1078 msgid "" "You can then issue commands of the form <command>mq pull</command> from the " "main repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:1083 msgid "A few things to watch out for" msgstr "需要注意的事情" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1085 msgid "" "MQ's support for working with a repository full of patches is limited in a " "few small respects." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1088 msgid "" "MQ cannot automatically detect changes that you make to the patch directory. " "If you <command role=\"hg-cmd\">hg pull</command>, manually edit, or <command " "role=\"hg-cmd\">hg update</command> changes to patches or the <filename role=" "\"special\">series</filename> file, you will have to <command role=\"hg-cmd" "\">hg qpop <option role=\"hg-ext-mq-cmd-qpop-opt\">hg -a</option></command> " "and then <command role=\"hg-cmd\">hg qpush <option role=\"hg-ext-mq-cmd-qpush-" "opt\">hg -a</option></command> in the underlying repository to see those " "changes show up there. If you forget to do this, you can confuse MQ's idea " "of which patches are applied." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:1104 msgid "Third party tools for working with patches" msgstr "操作补丁的第三方工具" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1106 msgid "" "Once you've been working with patches for a while, you'll find yourself " "hungry for tools that will help you to understand and manipulate the patches " "you're dealing with." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1110 msgid "" "The <command>diffstat</command> command <citation>web:diffstat</citation> " "generates a histogram of the modifications made to each file in a patch. It " "provides a good way to <quote>get a sense of</quote> a patch&emdash;which " "files it affects, and how much change it introduces to each file and as a " "whole. (I find that it's a good idea to use <command>diffstat</command>'s " "<option role=\"cmd-opt-diffstat\">-p</option> option as a matter of course, " "as otherwise it will try to do clever things with prefixes of file names that " "inevitably confuse at least me.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1124 msgid "" "The <literal role=\"package\">patchutils</literal> package <citation>web:" "patchutils</citation> is invaluable. It provides a set of small utilities " "that follow the <quote>Unix philosophy;</quote> each does one useful thing " "with a patch. The <literal role=\"package\">patchutils</literal> command I " "use most is <command>filterdiff</command>, which extracts subsets from a " "patch file. For example, given a patch that modifies hundreds of files " "across dozens of directories, a single invocation of <command>filterdiff</" "command> can generate a smaller patch that only touches files whose names " "match a particular glob pattern. See <xref linkend=\"mq-collab:tips:interdiff" "\"/> for another example." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:1140 msgid "Good ways to work with patches" msgstr "操作补丁的好习惯" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1142 msgid "" "Whether you are working on a patch series to submit to a free software or " "open source project, or a series that you intend to treat as a sequence of " "regular changesets when you're done, you can use some simple techniques to " "keep your work well organised." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1148 msgid "" "Give your patches descriptive names. A good name for a patch might be " "<filename>rework-device-alloc.patch</filename>, because it will immediately " "give you a hint what the purpose of the patch is. Long names shouldn't be a " "problem; you won't be typing the names often, but you <emphasis>will</" "emphasis> be running commands like <command role=\"hg-ext-mq\">qapplied</" "command> and <command role=\"hg-ext-mq\">qtop</command> over and over. Good " "naming becomes especially important when you have a number of patches to work " "with, or if you are juggling a number of different tasks and your patches " "only get a fraction of your attention." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1160 msgid "" "Be aware of what patch you're working on. Use the <command role=\"hg-ext-mq" "\">qtop</command> command and skim over the text of your patches " "frequently&emdash;for example, using <command role=\"hg-cmd\">hg tip <option " "role=\"hg-opt-tip\">-p</option></command>)&emdash;to be sure of where you " "stand. I have several times worked on and <command role=\"hg-ext-mq" "\">qrefresh</command>ed a patch other than the one I intended, and it's often " "tricky to migrate changes into the right patch after making them in the wrong " "one." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1170 msgid "" "For this reason, it is very much worth investing a little time to learn how " "to use some of the third-party tools I described in <xref linkend=\"sec:mq:" "tools\"/>, particularly <command>diffstat</command> and <command>filterdiff</" "command>. The former will give you a quick idea of what changes your patch " "is making, while the latter makes it easy to splice hunks selectively out of " "one patch and into another." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:1181 msgid "MQ cookbook" msgstr "MQ 手册" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:1184 msgid "Manage <quote>trivial</quote> patches" msgstr "管理<quote>琐碎的</quote>补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1186 msgid "" "Because the overhead of dropping files into a new Mercurial repository is so " "low, it makes a lot of sense to manage patches this way even if you simply " "want to make a few changes to a source tarball that you downloaded." msgstr "" # #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1191 msgid "" "Begin by downloading and unpacking the source tarball, and turning it into a " "Mercurial repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1196 msgid "Continue by creating a patch stack and making your changes." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1201 msgid "" "Let's say a few weeks or months pass, and your package author releases a new " "version. First, bring their changes into the repository." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1207 msgid "" "The pipeline starting with <command role=\"hg-cmd\">hg locate</command> above " "deletes all files in the working directory, so that <command role=\"hg-cmd" "\">hg commit</command>'s <option role=\"hg-opt-commit\">--addremove</option> " "option can actually tell which files have really been removed in the newer " "version of the source." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1215 msgid "Finally, you can apply your patches on top of the new tree." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:1222 msgid "Combining entire patches" msgstr "组合全部的补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1224 msgid "" "MQ provides a command, <command role=\"hg-ext-mq\">qfold</command> that lets " "you combine entire patches. This <quote>folds</quote> the patches you name, " "in the order you name them, into the topmost applied patch, and concatenates " "their descriptions onto the end of its description. The patches that you " "fold must be unapplied before you fold them." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1232 msgid "" "The order in which you fold patches matters. If your topmost applied patch " "is <literal>foo</literal>, and you <command role=\"hg-ext-mq\">qfold</" "command> <literal>bar</literal> and <literal>quux</literal> into it, you will " "end up with a patch that has the same effect as if you applied first " "<literal>foo</literal>, then <literal>bar</literal>, followed by " "<literal>quux</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch11-mq.xml:1243 msgid "Merging part of one patch into another" msgstr "合并补丁的部分内容到其它补丁" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1245 msgid "" "Merging <emphasis>part</emphasis> of one patch into another is more difficult " "than combining entire patches." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1249 msgid "" "If you want to move changes to entire files, you can use <command>filterdiff</" "command>'s <option role=\"cmd-opt-filterdiff\">-i</option> and <option role=" "\"cmd-opt-filterdiff\">-x</option> options to choose the modifications to " "snip out of one patch, concatenating its output onto the end of the patch you " "want to merge into. You usually won't need to modify the patch you've merged " "the changes from. Instead, MQ will report some rejected hunks when you " "<command role=\"hg-ext-mq\">qpush</command> it (from the hunks you moved into " "the other patch), and you can simply <command role=\"hg-ext-mq\">qrefresh</" "command> the patch to drop the duplicate hunks." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1262 msgid "" "If you have a patch that has multiple hunks modifying a file, and you only " "want to move a few of those hunks, the job becomes more messy, but you can " "still partly automate it. Use <command>lsdiff -nvv</command> to print some " "metadata about the patch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1270 msgid "This command prints three different kinds of number:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:1273 msgid "" "(in the first column) a <emphasis>file number</emphasis> to identify each " "file modified in the patch;" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:1277 msgid "" "(on the next line, indented) the line number within a modified file where a " "hunk starts; and" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch11-mq.xml:1280 msgid "" "(on the same line) a <emphasis>hunk number</emphasis> to identify that hunk." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1284 msgid "" "You'll have to use some visual inspection, and reading of the patch, to " "identify the file and hunk numbers you'll want, but you can then pass them to " "to <command>filterdiff</command>'s <option role=\"cmd-opt-filterdiff\">--" "files</option> and <option role=\"cmd-opt-filterdiff\">--hunks</option> " "options, to select exactly the file and hunk you want to extract." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch11-mq.xml:1292 msgid "" "Once you have this hunk, you can concatenate it onto the end of your " "destination patch and continue with the remainder of <xref linkend=\"sec:mq:" "combine\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch11-mq.xml:1299 msgid "Differences between quilt and MQ" msgstr "MQ 与 quilt 的区别" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1301 msgid "" "If you are already familiar with quilt, MQ provides a similar command set. " "There are a few differences in the way that it works." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch11-mq.xml:1305 msgid "" "You will already have noticed that most quilt commands have MQ counterparts " "that simply begin with a <quote><literal>q</literal></quote>. The exceptions " "are quilt's <literal>add</literal> and <literal>remove</literal> commands, " "the counterparts for which are the normal Mercurial <command role=\"hg-cmd" "\">hg add</command> and <command role=\"hg-cmd\">hg remove</command> " "commands. There is no MQ equivalent of the quilt <literal>edit</literal> " "command." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch12-mq-collab.xml:5 msgid "Advanced uses of Mercurial Queues" msgstr "MQ 的高级用法" #. type: Content of: <book><chapter><para> #: ../en/ch12-mq-collab.xml:7 msgid "" "While it's easy to pick up straightforward uses of Mercurial Queues, use of a " "little discipline and some of MQ's less frequently used capabilities makes it " "possible to work in complicated development environments." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch12-mq-collab.xml:12 msgid "" "In this chapter, I will use as an example a technique I have used to manage " "the development of an Infiniband device driver for the Linux kernel. The " "driver in question is large (at least as drivers go), with 25,000 lines of " "code spread across 35 source files. It is maintained by a small team of " "developers." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch12-mq-collab.xml:18 msgid "" "While much of the material in this chapter is specific to Linux, the same " "principles apply to any code base for which you're not the primary owner, and " "upon which you need to do a lot of development." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:24 msgid "The problem of many targets" msgstr "多个目标的问题" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:26 msgid "" "The Linux kernel changes rapidly, and has never been internally stable; " "developers frequently make drastic changes between releases. This means that " "a version of the driver that works well with a particular released version of " "the kernel will not even <emphasis>compile</emphasis> correctly against, " "typically, any other version." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:33 msgid "" "To maintain a driver, we have to keep a number of distinct versions of Linux " "in mind." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:36 msgid "" "One target is the main Linux kernel development tree. Maintenance of the code " "is in this case partly shared by other developers in the kernel community, " "who make <quote>drive-by</quote> modifications to the driver as they develop " "and refine kernel subsystems." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:42 msgid "" "We also maintain a number of <quote>backports</quote> to older versions of " "the Linux kernel, to support the needs of customers who are running older " "Linux distributions that do not incorporate our drivers. (To " "<emphasis>backport</emphasis> a piece of code is to modify it to work in an " "older version of its target environment than the version it was developed " "for.)" msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:50 msgid "" "Finally, we make software releases on a schedule that is necessarily not " "aligned with those used by Linux distributors and kernel developers, so that " "we can deliver new features to customers without forcing them to upgrade " "their entire kernels or distributions." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch12-mq-collab.xml:58 msgid "Tempting approaches that don't work well" msgstr "工作不好的诱人方法" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:60 msgid "" "There are two <quote>standard</quote> ways to maintain a piece of software " "that has to target many different environments." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:64 msgid "" "The first is to maintain a number of branches, each intended for a single " "target. The trouble with this approach is that you must maintain iron " "discipline in the flow of changes between repositories. A new feature or bug " "fix must start life in a <quote>pristine</quote> repository, then percolate " "out to every backport repository. Backport changes are more limited in the " "branches they should propagate to; a backport change that is applied to a " "branch where it doesn't belong will probably stop the driver from compiling." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:74 msgid "" "The second is to maintain a single source tree filled with conditional " "statements that turn chunks of code on or off depending on the intended " "target. Because these <quote>ifdefs</quote> are not allowed in the Linux " "kernel tree, a manual or automatic process must be followed to strip them out " "and yield a clean tree. A code base maintained in this fashion rapidly " "becomes a rat's nest of conditional blocks that are difficult to understand " "and maintain." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:83 msgid "" "Neither of these approaches is well suited to a situation where you don't " "<quote>own</quote> the canonical copy of a source tree. In the case of a " "Linux driver that is distributed with the standard kernel, Linus's tree " "contains the copy of the code that will be treated by the world as " "canonical. The upstream version of <quote>my</quote> driver can be modified " "by people I don't know, without me even finding out about it until after the " "changes show up in Linus's tree." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:93 msgid "" "These approaches have the added weakness of making it difficult to generate " "well-formed patches to submit upstream." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:97 msgid "" "In principle, Mercurial Queues seems like a good candidate to manage a " "development scenario such as the above. While this is indeed the case, MQ " "contains a few added features that make the job more pleasant." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:105 msgid "Conditionally applying patches with guards" msgstr "有条件的应用补丁" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:107 msgid "" "Perhaps the best way to maintain sanity with so many targets is to be able to " "choose specific patches to apply for a given situation. MQ provides a " "feature called <quote>guards</quote> (which originates with quilt's " "<literal>guards</literal> command) that does just this. To start off, let's " "create a simple repository for experimenting in." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:116 msgid "" "This gives us a tiny repository that contains two patches that don't have any " "dependencies on each other, because they touch different files." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:120 msgid "" "The idea behind conditional application is that you can <quote>tag</quote> a " "patch with a <emphasis>guard</emphasis>, which is simply a text string of " "your choosing, then tell MQ to select specific guards to use when applying " "patches. MQ will then either apply, or skip over, a guarded patch, depending " "on the guards that you have selected." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:127 msgid "" "A patch can have an arbitrary number of guards; each one is " "<emphasis>positive</emphasis> (<quote>apply this patch if this guard is " "selected</quote>) or <emphasis>negative</emphasis> (<quote>skip this patch if " "this guard is selected</quote>). A patch with no guards is always applied." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:135 msgid "Controlling the guards on a patch" msgstr "控制补丁的应用条件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:137 msgid "" "The <command role=\"hg-ext-mq\">qguard</command> command lets you determine " "which guards should apply to a patch, or display the guards that are already " "in effect. Without any arguments, it displays the guards on the current " "topmost patch." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:144 msgid "" "To set a positive guard on a patch, prefix the name of the guard with a " "<quote><literal>+</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:149 msgid "" "To set a negative guard on a patch, prefix the name of the guard with a " "<quote><literal>-</literal></quote>." msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch12-mq-collab.xml:156 msgid "" "The <command role=\"hg-ext-mq\">qguard</command> command <emphasis>sets</" "emphasis> the guards on a patch; it doesn't <emphasis>modify</emphasis> " "them. What this means is that if you run <command role=\"hg-cmd\">hg qguard " "+a +b</command> on a patch, then <command role=\"hg-cmd\">hg qguard +c</" "command> on the same patch, the <emphasis>only</emphasis> guard that will be " "set on it afterwards is <literal>+c</literal>." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:165 msgid "" "Mercurial stores guards in the <filename role=\"special\">series</filename> " "file; the form in which they are stored is easy both to understand and to " "edit by hand. (In other words, you don't have to use the <command role=\"hg-" "ext-mq\">qguard</command> command if you don't want to; it's okay to simply " "edit the <filename role=\"special\">series</filename> file.)" msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:177 msgid "Selecting the guards to use" msgstr "选择使用的条件" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:179 msgid "" "The <command role=\"hg-ext-mq\">qselect</command> command determines which " "guards are active at a given time. The effect of this is to determine which " "patches MQ will apply the next time you run <command role=\"hg-ext-mq" "\">qpush</command>. It has no other effect; in particular, it doesn't do " "anything to patches that are already applied." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:186 msgid "" "With no arguments, the <command role=\"hg-ext-mq\">qselect</command> command " "lists the guards currently in effect, one per line of output. Each argument " "is treated as the name of a guard to apply." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:193 msgid "" "In case you're interested, the currently selected guards are stored in the " "<filename role=\"special\">guards</filename> file." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:198 msgid "" "We can see the effect the selected guards have when we run <command role=\"hg-" "ext-mq\">qpush</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:203 msgid "" "A guard cannot start with a <quote><literal>+</literal></quote> or " "<quote><literal>-</literal></quote> character. The name of a guard must not " "contain white space, but most other characters are acceptable. If you try to " "use a guard with an invalid name, MQ will complain:" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:212 msgid "Changing the selected guards changes the patches that are applied." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:217 msgid "" "You can see in the example below that negative guards take precedence over " "positive guards." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:224 msgid "MQ's rules for applying patches" msgstr "MQ 应用补丁的规则" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:226 msgid "" "The rules that MQ uses when deciding whether to apply a patch are as follows." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:229 msgid "A patch that has no guards is always applied." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:232 msgid "" "If the patch has any negative guard that matches any currently selected " "guard, the patch is skipped." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:235 msgid "" "If the patch has any positive guard that matches any currently selected " "guard, the patch is applied." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:238 msgid "" "If the patch has positive or negative guards, but none matches any currently " "selected guard, the patch is skipped." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:245 msgid "Trimming the work environment" msgstr "修剪工作环境" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:247 msgid "" "In working on the device driver I mentioned earlier, I don't apply the " "patches to a normal Linux kernel tree. Instead, I use a repository that " "contains only a snapshot of the source files and headers that are relevant to " "Infiniband development. This repository is 1% the size of a kernel " "repository, so it's easier to work with." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:254 msgid "" "I then choose a <quote>base</quote> version on top of which the patches are " "applied. This is a snapshot of the Linux kernel tree as of a revision of my " "choosing. When I take the snapshot, I record the changeset ID from the " "kernel repository in the commit message. Since the snapshot preserves the " "<quote>shape</quote> and content of the relevant parts of the kernel tree, I " "can apply my patches on top of either my tiny repository or a normal kernel " "tree." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:263 msgid "" "Normally, the base tree atop which the patches apply should be a snapshot of " "a very recent upstream tree. This best facilitates the development of " "patches that can easily be submitted upstream with few or no modifications." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:270 msgid "Dividing up the <filename role=\"special\">series</filename> file" msgstr "分类补丁<filename role=\"special\">系列</filename>" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:273 msgid "" "I categorise the patches in the <filename role=\"special\">series</filename> " "file into a number of logical groups. Each section of like patches begins " "with a block of comments that describes the purpose of the patches that " "follow." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:279 msgid "" "The sequence of patch groups that I maintain follows. The ordering of these " "groups is important; I'll describe why after I introduce the groups." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:283 msgid "" "The <quote>accepted</quote> group. Patches that the development team has " "submitted to the maintainer of the Infiniband subsystem, and which he has " "accepted, but which are not present in the snapshot that the tiny repository " "is based on. These are <quote>read only</quote> patches, present only to " "transform the tree into a similar state as it is in the upstream maintainer's " "repository." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:291 msgid "" "The <quote>rework</quote> group. Patches that I have submitted, but that the " "upstream maintainer has requested modifications to before he will accept them." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:296 msgid "" "The <quote>pending</quote> group. Patches that I have not yet submitted to " "the upstream maintainer, but which we have finished working on. These will be " "<quote>read only</quote> for a while. If the upstream maintainer accepts " "them upon submission, I'll move them to the end of the <quote>accepted</" "quote> group. If he requests that I modify any, I'll move them to the " "beginning of the <quote>rework</quote> group." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:305 msgid "" "The <quote>in progress</quote> group. Patches that are actively being " "developed, and should not be submitted anywhere yet." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:309 msgid "" "The <quote>backport</quote> group. Patches that adapt the source tree to " "older versions of the kernel tree." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:313 msgid "" "The <quote>do not ship</quote> group. Patches that for some reason should " "never be submitted upstream. For example, one such patch might change " "embedded driver identification strings to make it easier to distinguish, in " "the field, between an out-of-tree version of the driver and a version shipped " "by a distribution vendor." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:321 msgid "" "Now to return to the reasons for ordering groups of patches in this way. We " "would like the lowest patches in the stack to be as stable as possible, so " "that we will not need to rework higher patches due to changes in context. " "Putting patches that will never be changed first in the <filename role=" "\"special\">series</filename> file serves this purpose." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:329 msgid "" "We would also like the patches that we know we'll need to modify to be " "applied on top of a source tree that resembles the upstream tree as closely " "as possible. This is why we keep accepted patches around for a while." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:334 msgid "" "The <quote>backport</quote> and <quote>do not ship</quote> patches float at " "the end of the <filename role=\"special\">series</filename> file. The " "backport patches must be applied on top of all other patches, and the " "<quote>do not ship</quote> patches might as well stay out of harm's way." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:343 msgid "Maintaining the patch series" msgstr "维护补丁系列" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:345 msgid "" "In my work, I use a number of guards to control which patches are to be " "applied." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:349 msgid "" "<quote>Accepted</quote> patches are guarded with <literal>accepted</" "literal>. I enable this guard most of the time. When I'm applying the " "patches on top of a tree where the patches are already present, I can turn " "this patch off, and the patches that follow it will apply cleanly." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:356 msgid "" "Patches that are <quote>finished</quote>, but not yet submitted, have no " "guards. If I'm applying the patch stack to a copy of the upstream tree, I " "don't need to enable any guards in order to get a reasonably safe source tree." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:362 msgid "" "Those patches that need reworking before being resubmitted are guarded with " "<literal>rework</literal>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:366 msgid "" "For those patches that are still under development, I use <literal>devel</" "literal>." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch12-mq-collab.xml:369 msgid "" "A backport patch may have several guards, one for each version of the kernel " "to which it applies. For example, a patch that backports a piece of code to " "2.6.9 will have a <literal>2.6.9</literal> guard." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch12-mq-collab.xml:374 msgid "" "This variety of guards gives me considerable flexibility in determining what " "kind of source tree I want to end up with. For most situations, the " "selection of appropriate guards is automated during the build process, but I " "can manually tune the guards to use for less common circumstances." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch12-mq-collab.xml:381 msgid "The art of writing backport patches" msgstr "编写向后移植补丁的艺术" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:383 msgid "" "Using MQ, writing a backport patch is a simple process. All such a patch has " "to do is modify a piece of code that uses a kernel feature not present in the " "older version of the kernel, so that the driver continues to work correctly " "under that older version." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:389 msgid "" "A useful goal when writing a good backport patch is to make your code look as " "if it was written for the older version of the kernel you're targeting. The " "less obtrusive the patch, the easier it will be to understand and maintain. " "If you're writing a collection of backport patches to avoid the <quote>rat's " "nest</quote> effect of lots of <literal>#ifdef</literal>s (hunks of source " "code that are only used conditionally) in your code, don't introduce version-" "dependent <literal>#ifdef</literal>s into the patches. Instead, write " "several patches, each of which makes unconditional changes, and control their " "application using guards." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:402 msgid "" "There are two reasons to divide backport patches into a distinct group, away " "from the <quote>regular</quote> patches whose effects they modify. The first " "is that intermingling the two makes it more difficult to use a tool like the " "<literal role=\"hg-ext\">patchbomb</literal> extension to automate the " "process of submitting the patches to an upstream maintainer. The second is " "that a backport patch could perturb the context in which a subsequent regular " "patch is applied, making it impossible to apply the regular patch cleanly " "<emphasis>without</emphasis> the earlier backport patch already being applied." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch12-mq-collab.xml:417 msgid "Useful tips for developing with MQ" msgstr "使用 MQ 开发的技巧" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch12-mq-collab.xml:420 msgid "Organising patches in directories" msgstr "将补丁放到几个目录中" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:422 msgid "" "If you're working on a substantial project with MQ, it's not difficult to " "accumulate a large number of patches. For example, I have one patch " "repository that contains over 250 patches." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:427 msgid "" "If you can group these patches into separate logical categories, you can if " "you like store them in different directories; MQ has no problems with patch " "names that contain path separators." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch12-mq-collab.xml:434 msgid "Viewing the history of a patch" msgstr "察看补丁的历史" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:436 msgid "" "If you're developing a set of patches over a long time, it's a good idea to " "maintain them in a repository, as discussed in <xref linkend=\"sec:mq:repo\"/" ">. If you do so, you'll quickly discover that using the <command role=\"hg-" "cmd\">hg diff</command> command to look at the history of changes to a patch " "is unworkable. This is in part because you're looking at the second " "derivative of the real code (a diff of a diff), but also because MQ adds " "noise to the process by modifying time stamps and directory names when it " "updates a patch." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:448 msgid "" "However, you can use the <literal role=\"hg-ext\">extdiff</literal> " "extension, which is bundled with Mercurial, to turn a diff of two versions of " "a patch into something readable. To do this, you will need a third-party " "package called <literal role=\"package\">patchutils</literal> <citation>web:" "patchutils</citation>. This provides a command named <command>interdiff</" "command>, which shows the differences between two diffs as a diff. Used on " "two versions of the same diff, it generates a diff that represents the diff " "from the first to the second version." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:459 msgid "" "You can enable the <literal role=\"hg-ext\">extdiff</literal> extension in " "the usual way, by adding a line to the <literal role=\"rc-extensions" "\">extensions</literal> section of your <filename role=\"special\">~/.hgrc</" "filename>." msgstr "" # #. &example.hg-interdiff; #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:466 msgid "" "The <command>interdiff</command> command expects to be passed the names of " "two files, but the <literal role=\"hg-ext\">extdiff</literal> extension " "passes the program it runs a pair of directories, each of which can contain " "an arbitrary number of files. We thus need a small program that will run " "<command>interdiff</command> on each pair of files in these two directories. " "This program is available as <filename role=\"special\">hg-interdiff</" "filename> in the <filename class=\"directory\">examples</filename> directory " "of the source code repository that accompanies this book." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:478 msgid "" "With the <filename role=\"special\">hg-interdiff</filename> program in your " "shell's search path, you can run it as follows, from inside an MQ patch " "directory:" msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:482 msgid "" "Since you'll probably want to use this long-winded command a lot, you can get " "<literal role=\"hg-ext\">hgext</literal> to make it available as a normal " "Mercurial command, again by editing your <filename role=\"special\">~/.hgrc</" "filename>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:489 msgid "" "This directs <literal role=\"hg-ext\">hgext</literal> to make an " "<literal>interdiff</literal> command available, so you can now shorten the " "previous invocation of <command role=\"hg-ext-extdiff\">extdiff</command> to " "something a little more wieldy." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><note><para> #: ../en/ch12-mq-collab.xml:497 msgid "" "The <command>interdiff</command> command works well only if the underlying " "files against which versions of a patch are generated remain the same. If " "you create a patch, modify the underlying files, and then regenerate the " "patch, <command>interdiff</command> may not produce useful output." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch12-mq-collab.xml:505 msgid "" "The <literal role=\"hg-ext\">extdiff</literal> extension is useful for more " "than merely improving the presentation of MQ patches. To read more about it, " "go to <xref linkend=\"sec:hgext:extdiff\"/>." msgstr "" #. type: Content of: <book><chapter><title> #: ../en/ch13-hgext.xml:5 msgid "Adding functionality with extensions" msgstr "使用扩展增加功能" #. type: Content of: <book><chapter><para> #: ../en/ch13-hgext.xml:7 msgid "" "While the core of Mercurial is quite complete from a functionality " "standpoint, it's deliberately shorn of fancy features. This approach of " "preserving simplicity keeps the software easy to deal with for both " "maintainers and users." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch13-hgext.xml:12 msgid "" "However, Mercurial doesn't box you in with an inflexible command set: you can " "add features to it as <emphasis>extensions</emphasis> (sometimes known as " "<emphasis>plugins</emphasis>). We've already discussed a few of these " "extensions in earlier chapters." msgstr "" #. type: Content of: <book><chapter><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:18 msgid "" "<xref linkend=\"sec:tour-merge:fetch\"/> covers the <literal role=\"hg-ext" "\">fetch</literal> extension; this combines pulling new changes and merging " "them with local changes into a single command, <command role=\"hg-ext-fetch" "\">fetch</command>." msgstr "" #. type: Content of: <book><chapter><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:24 msgid "" "In <xref linkend=\"chap:hook\"/>, we covered several extensions that are " "useful for hook-related functionality: <literal role=\"hg-ext\">acl</literal> " "adds access control lists; <literal role=\"hg-ext\">bugzilla</literal> adds " "integration with the Bugzilla bug tracking system; and <literal role=\"hg-ext" "\">notify</literal> sends notification emails on new changes." msgstr "" #. type: Content of: <book><chapter><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:33 msgid "" "The Mercurial Queues patch management extension is so invaluable that it " "merits two chapters and an appendix all to itself. <xref linkend=\"chap:mq\"/" "> covers the basics; <xref linkend=\"chap:mq-collab\"/> discusses advanced " "topics; and <xref linkend=\"chap:mqref\"/> goes into detail on each command." msgstr "" #. type: Content of: <book><chapter><para> #: ../en/ch13-hgext.xml:43 msgid "" "In this chapter, we'll cover some of the other extensions that are available " "for Mercurial, and briefly touch on some of the machinery you'll need to know " "about if you want to write an extension of your own." msgstr "" #. type: Content of: <book><chapter><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:48 msgid "" "In <xref linkend=\"sec:hgext:inotify\"/>, we'll discuss the possibility of " "<emphasis>huge</emphasis> performance improvements using the <literal role=" "\"hg-ext\">inotify</literal> extension." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch13-hgext.xml:55 msgid "" "Improve performance with the <literal role=\"hg-ext\">inotify</literal> " "extension" msgstr "使用扩展 <literal role=\"hg-ext\">inotify</literal> 以提高性能" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:58 msgid "" "Are you interested in having some of the most common Mercurial operations run " "as much as a hundred times faster? Read on!" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:62 msgid "" "Mercurial has great performance under normal circumstances. For example, " "when you run the <command role=\"hg-cmd\">hg status</command> command, " "Mercurial has to scan almost every directory and file in your repository so " "that it can display file status. Many other Mercurial commands need to do " "the same work behind the scenes; for example, the <command role=\"hg-cmd\">hg " "diff</command> command uses the status machinery to avoid doing an expensive " "comparison operation on files that obviously haven't changed." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:72 msgid "" "Because obtaining file status is crucial to good performance, the authors of " "Mercurial have optimised this code to within an inch of its life. However, " "there's no avoiding the fact that when you run <command role=\"hg-cmd\">hg " "status</command>, Mercurial is going to have to perform at least one " "expensive system call for each managed file to determine whether it's changed " "since the last time Mercurial checked. For a sufficiently large repository, " "this can take a long time." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:82 msgid "" "To put a number on the magnitude of this effect, I created a repository " "containing 150,000 managed files. I timed <command role=\"hg-cmd\">hg " "status</command> as taking ten seconds to run, even when <emphasis>none</" "emphasis> of those files had been modified." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:88 msgid "" "Many modern operating systems contain a file notification facility. If a " "program signs up to an appropriate service, the operating system will notify " "it every time a file of interest is created, modified, or deleted. On Linux " "systems, the kernel component that does this is called <literal>inotify</" "literal>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:95 msgid "" "Mercurial's <literal role=\"hg-ext\">inotify</literal> extension talks to the " "kernel's <literal>inotify</literal> component to optimise <command role=\"hg-" "cmd\">hg status</command> commands. The extension has two components. A " "daemon sits in the background and receives notifications from the " "<literal>inotify</literal> subsystem. It also listens for connections from a " "regular Mercurial command. The extension modifies Mercurial's behaviour so " "that instead of scanning the filesystem, it queries the daemon. Since the " "daemon has perfect information about the state of the repository, it can " "respond with a result instantaneously, avoiding the need to scan every " "directory and file in the repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:108 msgid "" "Recall the ten seconds that I measured plain Mercurial as taking to run " "<command role=\"hg-cmd\">hg status</command> on a 150,000 file repository. " "With the <literal role=\"hg-ext\">inotify</literal> extension enabled, the " "time dropped to 0.1 seconds, a factor of <emphasis>one hundred</emphasis> " "faster." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:115 msgid "Before we continue, please pay attention to some caveats." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:118 msgid "" "The <literal role=\"hg-ext\">inotify</literal> extension is Linux-specific. " "Because it interfaces directly to the Linux kernel's <literal>inotify</" "literal> subsystem, it does not work on other operating systems." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:123 msgid "" "It should work on any Linux distribution that was released after early 2005. " "Older distributions are likely to have a kernel that lacks <literal>inotify</" "literal>, or a version of <literal>glibc</literal> that does not have the " "necessary interfacing support." msgstr "" #. type: Content of: <book><chapter><sect1><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:130 msgid "" "Not all filesystems are suitable for use with the <literal role=\"hg-ext" "\">inotify</literal> extension. Network filesystems such as NFS are a non-" "starter, for example, particularly if you're running Mercurial on several " "systems, all mounting the same network filesystem. The kernel's " "<literal>inotify</literal> system has no way of knowing about changes made on " "another system. Most local filesystems (e.g. ext3, XFS, ReiserFS) should " "work fine." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:141 msgid "" "The <literal role=\"hg-ext\">inotify</literal> extension is not yet shipped " "with Mercurial as of May 2007, so it's a little more involved to set up than " "other extensions. But the performance improvement is worth it!" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:146 msgid "" "The extension currently comes in two parts: a set of patches to the Mercurial " "source code, and a library of Python bindings to the <literal>inotify</" "literal> subsystem." msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch13-hgext.xml:150 msgid "" "There are <emphasis>two</emphasis> Python <literal>inotify</literal> binding " "libraries. One of them is called <literal>pyinotify</literal>, and is " "packaged by some Linux distributions as <literal>python-inotify</literal>. " "This is <emphasis>not</emphasis> the one you'll need, as it is too buggy and " "inefficient to be practical." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:157 msgid "" "To get going, it's best to already have a functioning copy of Mercurial " "installed." msgstr "" #. type: Content of: <book><chapter><sect1><note><para> #: ../en/ch13-hgext.xml:160 msgid "" "If you follow the instructions below, you'll be <emphasis>replacing</" "emphasis> and overwriting any existing installation of Mercurial that you " "might already have, using the latest <quote>bleeding edge</quote> Mercurial " "code. Don't say you weren't warned!" msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:167 msgid "" "Clone the Python <literal>inotify</literal> binding repository. Build and " "install it." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:174 msgid "" "Clone the <filename class=\"directory\">crew</filename> Mercurial " "repository. Clone the <literal role=\"hg-ext\">inotify</literal> patch " "repository so that Mercurial Queues will be able to apply patches to your " "cope of the <filename class=\"directory\">crew</filename> repository." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:184 msgid "" "Make sure that you have the Mercurial Queues extension, <literal role=\"hg-ext" "\">mq</literal>, enabled. If you've never used MQ, read <xref linkend=\"sec:" "mq:start\"/> to get started quickly." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:190 msgid "" "Go into the <filename class=\"directory\">inotify</filename> repo, and apply " "all of the <literal role=\"hg-ext\">inotify</literal> patches using the " "<option role=\"hg-ext-mq-cmd-qpush-opt\">hg -a</option> option to the " "<command role=\"hg-ext-mq\">qpush</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:199 msgid "" "If you get an error message from <command role=\"hg-ext-mq\">qpush</command>, " "you should not continue. Instead, ask for help." msgstr "" #. type: Content of: <book><chapter><sect1><orderedlist><listitem><para> #: ../en/ch13-hgext.xml:203 msgid "Build and install the patched version of Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:209 msgid "" "Once you've build a suitably patched version of Mercurial, all you need to do " "to enable the <literal role=\"hg-ext\">inotify</literal> extension is add an " "entry to your <filename role=\"special\">~/.hgrc</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:214 msgid "" "When the <literal role=\"hg-ext\">inotify</literal> extension is enabled, " "Mercurial will automatically and transparently start the status daemon the " "first time you run a command that needs status in a repository. It runs one " "status daemon per repository." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:220 msgid "" "The status daemon is started silently, and runs in the background. If you " "look at a list of running processes after you've enabled the <literal role=" "\"hg-ext\">inotify</literal> extension and run a few commands in different " "repositories, you'll thus see a few <literal>hg</literal> processes sitting " "around, waiting for updates from the kernel and queries from Mercurial." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:228 msgid "" "The first time you run a Mercurial command in a repository when you have the " "<literal role=\"hg-ext\">inotify</literal> extension enabled, it will run " "with about the same performance as a normal Mercurial command. This is " "because the status daemon needs to perform a normal status scan so that it " "has a baseline against which to apply later updates from the kernel. " "However, <emphasis>every</emphasis> subsequent command that does any kind of " "status check should be noticeably faster on repositories of even fairly " "modest size. Better yet, the bigger your repository is, the greater a " "performance advantage you'll see. The <literal role=\"hg-ext\">inotify</" "literal> daemon makes status operations almost instantaneous on repositories " "of all sizes!" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:242 msgid "" "If you like, you can manually start a status daemon using the <command role=" "\"hg-ext-inotify\">inserve</command> command. This gives you slightly finer " "control over how the daemon ought to run. This command will of course only " "be available when the <literal role=\"hg-ext\">inotify</literal> extension is " "enabled." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:249 msgid "" "When you're using the <literal role=\"hg-ext\">inotify</literal> extension, " "you should notice <emphasis>no difference at all</emphasis> in Mercurial's " "behaviour, with the sole exception of status-related commands running a whole " "lot faster than they used to. You should specifically expect that commands " "will not print different output; neither should they give different results. " "If either of these situations occurs, please report a bug." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch13-hgext.xml:260 msgid "" "Flexible diff support with the <literal role=\"hg-ext\">extdiff</literal> " "extension" msgstr "使用扩展 <literal role=\"hg-ext\">extdiff</literal> 以扩展差异支持" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:263 msgid "" "Mercurial's built-in <command role=\"hg-cmd\">hg diff</command> command " "outputs plaintext unified diffs." msgstr "" "Mercurial 内置命令 <command role=\"hg-cmd\">hg diff</command> 的输出与统一差异" "不同。" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:268 msgid "" "If you would like to use an external tool to display modifications, you'll " "want to use the <literal role=\"hg-ext\">extdiff</literal> extension. This " "will let you use, for example, a graphical diff tool." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:273 msgid "" "The <literal role=\"hg-ext\">extdiff</literal> extension is bundled with " "Mercurial, so it's easy to set up. In the <literal role=\"rc-extensions" "\">extensions</literal> section of your <filename role=\"special\">~/.hgrc</" "filename>, simply add a one-line entry to enable the extension." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:280 msgid "" "This introduces a command named <command role=\"hg-ext-extdiff\">extdiff</" "command>, which by default uses your system's <command>diff</command> command " "to generate a unified diff in the same form as the built-in <command role=" "\"hg-cmd\">hg diff</command> command." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:288 msgid "" "The result won't be exactly the same as with the built-in <command role=\"hg-" "cmd\">hg diff</command> variations, because the output of <command>diff</" "command> varies from one system to another, even when passed the same options." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:293 msgid "" "As the <quote><literal>making snapshot</literal></quote> lines of output " "above imply, the <command role=\"hg-ext-extdiff\">extdiff</command> command " "works by creating two snapshots of your source tree. The first snapshot is " "of the source revision; the second, of the target revision or working " "directory. The <command role=\"hg-ext-extdiff\">extdiff</command> command " "generates these snapshots in a temporary directory, passes the name of each " "directory to an external diff viewer, then deletes the temporary directory. " "For efficiency, it only snapshots the directories and files that have changed " "between the two revisions." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:306 msgid "" "Snapshot directory names have the same base name as your repository. If your " "repository path is <filename class=\"directory\">/quux/bar/foo</filename>, " "then <filename class=\"directory\">foo</filename> will be the name of each " "snapshot directory. Each snapshot directory name has its changeset ID " "appended, if appropriate. If a snapshot is of revision " "<literal>a631aca1083f</literal>, the directory will be named <filename class=" "\"directory\">foo.a631aca1083f</filename>. A snapshot of the working " "directory won't have a changeset ID appended, so it would just be <filename " "class=\"directory\">foo</filename> in this example. To see what this looks " "like in practice, look again at the <command role=\"hg-ext-extdiff\">extdiff</" "command> example above. Notice that the diff has the snapshot directory " "names embedded in its header." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:322 msgid "" "The <command role=\"hg-ext-extdiff\">extdiff</command> command accepts two " "important options. The <option role=\"hg-ext-extdiff-cmd-extdiff-opt\">hg -p</" "option> option lets you choose a program to view differences with, instead of " "<command>diff</command>. With the <option role=\"hg-ext-extdiff-cmd-extdiff-" "opt\">hg -o</option> option, you can change the options that <command role=" "\"hg-ext-extdiff\">extdiff</command> passes to the program (by default, these " "options are <quote><literal>-Npru</literal></quote>, which only make sense if " "you're running <command>diff</command>). In other respects, the <command " "role=\"hg-ext-extdiff\">extdiff</command> command acts similarly to the built-" "in <command role=\"hg-cmd\">hg diff</command> command: you use the same " "option names, syntax, and arguments to specify the revisions you want, the " "files you want, and so on." msgstr "" # #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:339 msgid "" "As an example, here's how to run the normal system <command>diff</command> " "command, getting it to generate context diffs (using the <option role=\"cmd-" "opt-diff\">-c</option> option) instead of unified diffs, and five lines of " "context instead of the default three (passing <literal>5</literal> as the " "argument to the <option role=\"cmd-opt-diff\">-C</option> option)." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:348 msgid "" "Launching a visual diff tool is just as easy. Here's how to launch the " "<command>kdiff3</command> viewer." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:352 msgid "" "If your diff viewing command can't deal with directories, you can easily work " "around this with a little scripting. For an example of such scripting in " "action with the <literal role=\"hg-ext\">mq</literal> extension and the " "<command>interdiff</command> command, see <xref linkend=\"mq-collab:tips:" "interdiff\"/>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch13-hgext.xml:360 msgid "Defining command aliases" msgstr "定义命令的别名" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch13-hgext.xml:362 msgid "" "It can be cumbersome to remember the options to both the <command role=\"hg-" "ext-extdiff\">extdiff</command> command and the diff viewer you want to use, " "so the <literal role=\"hg-ext\">extdiff</literal> extension lets you define " "<emphasis>new</emphasis> commands that will invoke your diff viewer with " "exactly the right options." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch13-hgext.xml:369 msgid "" "All you need to do is edit your <filename role=\"special\">~/.hgrc</" "filename>, and add a section named <literal role=\"rc-extdiff\">extdiff</" "literal>. Inside this section, you can define multiple commands. Here's how " "to add a <literal>kdiff3</literal> command. Once you've defined this, you " "can type <quote><literal>hg kdiff3</literal></quote> and the <literal role=" "\"hg-ext\">extdiff</literal> extension will run <command>kdiff3</command> for " "you." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch13-hgext.xml:379 msgid "" "If you leave the right hand side of the definition empty, as above, the " "<literal role=\"hg-ext\">extdiff</literal> extension uses the name of the " "command you defined as the name of the external program to run. But these " "names don't have to be the same. Here, we define a command named " "<quote><literal>hg wibble</literal></quote>, which runs <command>kdiff3</" "command>." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch13-hgext.xml:389 msgid "" "You can also specify the default options that you want to invoke your diff " "viewing program with. The prefix to use is <quote><literal>opts.</literal></" "quote>, followed by the name of the command to which the options apply. This " "example defines a <quote><literal>hg vimdiff</literal></quote> command that " "runs the <command>vim</command> editor's <literal>DirDiff</literal> extension." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch13-hgext.xml:403 msgid "" "Cherrypicking changes with the <literal role=\"hg-ext\">transplant</literal> " "extension" msgstr "使用扩展 <literal role=\"hg-ext\">transplant</literal> 以挑选修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:406 msgid "Need to have a long chat with Brendan about this." msgstr "" #. type: Content of: <book><chapter><sect1><title> #: ../en/ch13-hgext.xml:410 msgid "" "Send changes via email with the <literal role=\"hg-ext\">patchbomb</literal> " "extension" msgstr "" "使用扩展 <literal role=\"hg-ext\">patchbomb</literal> 通过 email 发送修改" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:413 msgid "" "Many projects have a culture of <quote>change review</quote>, in which people " "send their modifications to a mailing list for others to read and comment on " "before they commit the final version to a shared repository. Some projects " "have people who act as gatekeepers; they apply changes from other people to a " "repository to which those others don't have access." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:421 msgid "" "Mercurial makes it easy to send changes over email for review or application, " "via its <literal role=\"hg-ext\">patchbomb</literal> extension. The " "extension is so named because changes are formatted as patches, and it's " "usual to send one changeset per email message. Sending a long series of " "changes by email is thus much like <quote>bombing</quote> the recipient's " "inbox, hence <quote>patchbomb</quote>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:429 msgid "" "As usual, the basic configuration of the <literal role=\"hg-ext\">patchbomb</" "literal> extension takes just one or two lines in your <filename role=" "\"special\"> /.hgrc</filename>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:435 msgid "" "Once you've enabled the extension, you will have a new command available, " "named <command role=\"hg-ext-patchbomb\">email</command>." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:439 msgid "" "The safest and best way to invoke the <command role=\"hg-ext-patchbomb" "\">email</command> command is to <emphasis>always</emphasis> run it first " "with the <option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -n</option> " "option. This will show you what the command <emphasis>would</emphasis> send, " "without actually sending anything. Once you've had a quick glance over the " "changes and verified that you are sending the right ones, you can rerun the " "same command, with the <option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -n</" "option> option removed." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:450 msgid "" "The <command role=\"hg-ext-patchbomb\">email</command> command accepts the " "same kind of revision syntax as every other Mercurial command. For example, " "this command will send every revision between 7 and <literal>tip</literal>, " "inclusive." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:455 msgid "" "You can also specify a <emphasis>repository</emphasis> to compare with. If " "you provide a repository but no revisions, the <command role=\"hg-ext-" "patchbomb\">email</command> command will send all revisions in the local " "repository that are not present in the remote repository. If you " "additionally specify revisions or a branch name (the latter using the <option " "role=\"hg-ext-patchbomb-cmd-email-opt\">hg -b</option> option), this will " "constrain the revisions sent." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:464 msgid "" "It's perfectly safe to run the <command role=\"hg-ext-patchbomb\">email</" "command> command without the names of the people you want to send to: if you " "do this, it will just prompt you for those values interactively. (If you're " "using a Linux or Unix-like system, you should have enhanced " "<literal>readline</literal>-style editing capabilities when entering those " "headers, too, which is useful.)" msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:472 msgid "" "When you are sending just one revision, the <command role=\"hg-ext-patchbomb" "\">email</command> command will by default use the first line of the " "changeset description as the subject of the single email message it sends." msgstr "" #. type: Content of: <book><chapter><sect1><para> #: ../en/ch13-hgext.xml:477 msgid "" "If you send multiple revisions, the <command role=\"hg-ext-patchbomb\">email</" "command> command will usually send one message per changeset. It will " "preface the series with an introductory message, in which you should describe " "the purpose of the series of changes you're sending." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><title> #: ../en/ch13-hgext.xml:484 msgid "Changing the behaviour of patchbombs" msgstr "修改 patchbomb 的行为" #. type: Content of: <book><chapter><sect1><sect2><para> #: ../en/ch13-hgext.xml:486 msgid "" "Not every project has exactly the same conventions for sending changes in " "email; the <literal role=\"hg-ext\">patchbomb</literal> extension tries to " "accommodate a number of variations through command line options." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:492 msgid "" "You can write a subject for the introductory message on the command line " "using the <option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -s</option> " "option. This takes one argument, the text of the subject to use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:498 msgid "" "To change the email address from which the messages originate, use the " "<option role=\"hg-ext-patchbomb-cmd-email-opt\">hg -f</option> option. This " "takes one argument, the email address to use." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:504 msgid "" "The default behaviour is to send unified diffs (see <xref linkend=\"sec:mq:" "patch\"/> for a description of the format), one per message. You can send a " "binary bundle instead with the <option role=\"hg-ext-patchbomb-cmd-email-opt" "\">hg -b</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:512 msgid "" "Unified diffs are normally prefaced with a metadata header. You can omit " "this, and send unadorned diffs, with the <option role=\"hg-ext-patchbomb-cmd-" "email-opt\">hg --plain</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:518 msgid "" "Diffs are normally sent <quote>inline</quote>, in the same body part as the " "description of a patch. This makes it easiest for the largest number of " "readers to quote and respond to parts of a diff, as some mail clients will " "only quote the first MIME body part in a message. If you'd prefer to send the " "description and the diff in separate body parts, use the <option role=\"hg-" "ext-patchbomb-cmd-email-opt\">hg -a</option> option." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:528 msgid "" "Instead of sending mail messages, you can write them to an <literal>mbox</" "literal>-format mail folder using the <option role=\"hg-ext-patchbomb-cmd-" "email-opt\">hg -m</option> option. That option takes one argument, the name " "of the file to write to." msgstr "" #. type: Content of: <book><chapter><sect1><sect2><itemizedlist><listitem><para> #: ../en/ch13-hgext.xml:535 msgid "" "If you would like to add a <command>diffstat</command>-format summary to each " "patch, and one to the introductory message, use the <option role=\"hg-ext-" "patchbomb-cmd-email-opt\">hg -d</option> option. The <command>diffstat</" "command> command displays a table containing the name of each file patched, " "the number of lines affected, and a histogram showing how much each file is " "modified. This gives readers a qualitative glance at how complex a patch is." msgstr ""