hgbook

annotate fr/complete.xml @ 1029:9e12ed413ef9

Fixing build, depending on installation fop config file may be missing
author Romain PELISSE <belaran@gmail.com>
date Thu Apr 22 12:39:20 2010 +0200 (2010-04-22)
parents
children
rev   line source
belaran@999 1 <?xml version="1.0"?>
belaran@999 2
belaran@999 3 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
belaran@999 4 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
belaran@999 5 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 6 <book id="hg">
belaran@999 7 <title>Mercurial: The Definitive Guide</title>
belaran@999 8
belaran@999 9 <!-- hg parents &#x2d;&#x2d;template '{node|short} ({date|shortdate})'
belaran@999 10 <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle>
belaran@999 11 -->
belaran@999 12 <subtitle>Compiled from $rev_id$</subtitle>
belaran@999 13 <bookinfo>
belaran@999 14 <edition>1</edition>
belaran@999 15 <isbn>9780596800673</isbn>
belaran@999 16 <authorgroup>
belaran@999 17 <author>
belaran@999 18 <firstname>Bryan</firstname>
belaran@999 19 <surname>O'Sullivan</surname>
belaran@999 20 </author>
belaran@999 21 </authorgroup>
belaran@999 22
belaran@999 23 <editor>
belaran@999 24 <firstname>Mike</firstname>
belaran@999 25 <surname>Loukides</surname>
belaran@999 26 </editor>
belaran@999 27
belaran@999 28 <copyright>
belaran@999 29 <year>2006</year>
belaran@999 30 <year>2007</year>
belaran@999 31 <year>2008</year>
belaran@999 32 <year>2009</year>
belaran@999 33 <holder>Bryan O'Sullivan</holder>
belaran@999 34 </copyright>
belaran@999 35 </bookinfo>
belaran@999 36
belaran@999 37 <!-- BEGIN ch00 -->
belaran@999 38 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 39
belaran@999 40 <preface id="chap:preface">
belaran@999 41 <?dbhtml filename="preface.html"?>
belaran@999 42 <title>Preface</title>
belaran@999 43
belaran@999 44 <sect1>
belaran@999 45 <title>Un conte technique</title>
belaran@999 46
belaran@999 47 <para id="x_72e">Il y a quelques années, quand j'ai voulu expliqué
belaran@999 48 pourquoi je pensais que le gestion de révision distribuée est importante,
belaran@999 49 le domaine était encore si nouveau qu'il n'y avait presque aucune
belaran@999 50 littérature publiée pour servir de référence aux personnes intéressées.</para>
belaran@999 51
belaran@999 52 <para id="x_72f">Bien qu'à cette époque je passais beaucoup de temps
belaran@999 53 à travailler sur les entrailles de Mercurial, je me suis mis à la
belaran@999 54 rédaction de ce livre parce qu'il me semblait la manière la plus efficace
belaran@999 55 d'aider notre logiciel à atteindre un vaste auditoire, toujours avec
belaran@999 56 l'idée que la gestion de révision devrait être distribuée par nature. J'ai
belaran@999 57 publié ce libre en ligne sous une licence libre pour la même raison : pour
belaran@999 58 diffuser la parole auprès du monde.</para>
belaran@999 59
belaran@999 60 <para id="x_730">Il y a un rythme familier à un bon livre sur un logiciel
belaran@999 61 qui ressemble de près au fait de conter une histoire : Pourquoi ceci est ?
belaran@999 62 Pourquoi ceci est important ? Comment peut il m'aider ? Comment m'en
belaran@999 63 servir ? Dans ce livre, j'essaye de répondre à toutes ces questions pour
belaran@999 64 la gestion de révision distribuée en général, et pour Mercurial en
belaran@999 65 particulier.</para>
belaran@999 66 </sect1>
belaran@999 67
belaran@999 68 <sect1>
belaran@999 69 <title>Merci de votre soutien à Mercurial</title>
belaran@999 70
belaran@999 71 <para id="x_731">En achetant une copie de ce livre, vous soutenez le
belaran@999 72 développement et la liberté de Mercurial en particulier, et dans
belaran@999 73 l'Open Source, au logiciel libre en général. O'Reilly Media et
belaran@999 74 moi-même donnons les revenus issus des ventes de ce livre à la
belaran@999 75 Software Freedom Conservancy (<ulink url="http://www.softwarefreedom.org/">http://www.softwarefreedom.org/</ulink>)
belaran@999 76 qui fournit un support juridique à Mercurial et à de
belaran@999 77 nombreux autres projets Open Source proéminents et de qualité.</para>
belaran@999 78 </sect1>
belaran@999 79
belaran@999 80 <sect1>
belaran@999 81 <title>Remerciements</title>
belaran@999 82
belaran@999 83 <para id="x_732">Ce livre n'aurait pas vu le jour sans les
belaran@999 84 efforts de Matt Mackal, l'auteur et le chef du projet Mercurial.
belaran@999 85 Il est assisté très efficacement par des centaines de contributeurs
belaran@999 86 volontaires à travers le monde.</para>
belaran@999 87
belaran@999 88 <para id="x_733">Les enfants, Cian et Ruairi, ont toujours été prêt
belaran@999 89 à m'aider à me reposer avec de merveilleux et impulsif jeux d'enfants.
belaran@999 90 Je tiens aussi à remercier mon ex-femme, Shannon, pour son soutien.
belaran@999 91 </para>
belaran@999 92
belaran@999 93 <para id="x_734">Mes collègues et amis m'ont aidé et assisté de
belaran@999 94 de nombreuses manières. Cette liste de personne est nécessaire mais très
belaran@999 95 incomplète : Stephen Hahn, Karyn Ritter, Bonnie Corwin, James Vasile,
belaran@999 96 Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh, Jeremy
belaran@999 97 Fitzhardinge, Rachel Chalmers.</para>
belaran@999 98
belaran@999 99 <para id="x_735">J'ai conçu ce livre de manière ouverte, en publiant
belaran@999 100 des brouillons des chapitres du livre sur des site web, au fur et à
belaran@999 101 mesure que je les réalisais. Leurs lecteurs m'ont fait des retours
belaran@999 102 utilisant l'application web que j'avais développée. A la fin de sa
belaran@999 103 conception, plus de 100 personnes m'avaient fait des commentaires,
belaran@999 104 un chiffre incroyable quand l'on considère que ce système de
belaran@999 105 commentaire n'a tourné que dans les deux derniers mois de la
belaran@999 106 rédaction du livre.</para>
belaran@999 107
belaran@999 108 <para id="x_736">J'aimerais particulièrement remercier les
belaran@999 109 personnes suivantes, dont les commentaires représentent plus
belaran@999 110 d'un tiers de l'ensemble de ces derniers. Je voudrais les
belaran@999 111 remercier pour leur attention et effort à me faire des retours
belaran@999 112 très détaillés.</para>
belaran@999 113
belaran@999 114 <para id="x_737">Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe,
belaran@999 115 Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der
belaran@999 116 Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon
belaran@999 117 Parise.</para>
belaran@999 118
belaran@999 119 <para id="x_738">Je souhaite aussi remercier l'aide des personnes
belaran@999 120 qui ont découvert des erreurs et fournit des suggestions avisées
belaran@999 121 à travers tout le livre.</para>
belaran@999 122
belaran@999 123 <para id="x_739">Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan
belaran@999 124 Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric
belaran@999 125 Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan
belaran@999 126 Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted
belaran@999 127 Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned
belaran@999 128 Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph
belaran@999 129 Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris,
belaran@999 130 Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen,
belaran@999 131 David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry
belaran@999 132 Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger,
belaran@999 133 Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav
belaran@999 134 Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli,
belaran@999 135 Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser,
belaran@999 136 Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry,
belaran@999 137 Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák,
belaran@999 138 Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord
belaran@999 139 Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan
belaran@999 140 Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers,
belaran@999 141 Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan
belaran@999 142 Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz
belaran@999 143 Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam,
belaran@999 144 Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot,
belaran@999 145 Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez,
belaran@999 146 Ahmed Chaudhary.</para>
belaran@999 147 </sect1>
belaran@999 148
belaran@999 149 <sect1>
belaran@999 150 <title>Conventions utilisées dans ce livre</title>
belaran@999 151
belaran@999 152 <para id="x_73a">Les conventions typographiques suivantes sont utilisées dans ce livre :</para>
belaran@999 153
belaran@999 154 <variablelist>
belaran@999 155 <varlistentry>
belaran@999 156 <term>Italique</term>
belaran@999 157
belaran@999 158 <listitem>
belaran@999 159 <para id="x_73b">Indique les termes nouveaux, les URLs, les
belaran@999 160 adresses mail, les noms de fichiers et les extensions de
belaran@999 161 fichier.</para>
belaran@999 162 </listitem>
belaran@999 163 </varlistentry>
belaran@999 164
belaran@999 165 <varlistentry>
belaran@999 166 <term><literal moreinfo="none">Taille constante</literal></term>
belaran@999 167
belaran@999 168 <listitem>
belaran@999 169 <para id="x_73c">Utilisé pour les extraits de code, comme
belaran@999 170 dans les paragraphes pour référer aux éléments du programme,
belaran@999 171 tels que les variables ou les noms de fonctions, de bases
belaran@999 172 de données, de types de données, de variables d'environnement,
belaran@999 173 d'instructions, et de mots clés.</para>
belaran@999 174 </listitem>
belaran@999 175 </varlistentry>
belaran@999 176
belaran@999 177 <varlistentry>
belaran@999 178 <term><userinput moreinfo="none">Taille constante avec gras</userinput></term>
belaran@999 179
belaran@999 180 <listitem>
belaran@999 181 <para id="x_73d">Afficher les commandes ou autres textes qui
belaran@999 182 devraient être saisis par l'utilisateur.</para>
belaran@999 183 </listitem>
belaran@999 184 </varlistentry>
belaran@999 185
belaran@999 186 <varlistentry>
belaran@999 187 <term><replaceable>Constante avec italique</replaceable></term>
belaran@999 188
belaran@999 189 <listitem>
belaran@999 190 <para id="x_73e">Affiche les textes qui devraient être remplacés
belaran@999 191 par une valeur définie par l'utilisateur ou des valeurs définies
belaran@999 192 selon le contexte.</para>
belaran@999 193 </listitem>
belaran@999 194 </varlistentry>
belaran@999 195 </variablelist>
belaran@999 196
belaran@999 197 <tip>
belaran@999 198 <para id="x_73f">Cette icône indique une astuce, une suggestion ou
belaran@999 199 une note d'ordre général.</para>
belaran@999 200 </tip>
belaran@999 201
belaran@999 202 <caution>
belaran@999 203 <para id="x_740">Cette icône est un message d'alerte ou de prudence.</para>
belaran@999 204 </caution>
belaran@999 205 </sect1>
belaran@999 206
belaran@999 207 <sect1>
belaran@999 208 <title>Utiliser les exemples de code</title>
belaran@999 209
belaran@999 210 <para id="x_741">Ce livre est ici pour vous aider dans votre
belaran@999 211 travail. De manière générale, vous pouvez donc utiliser le code
belaran@999 212 de ce livre dans vos programmes et votre documentation. Vous
belaran@999 213 n'avez pas à nous contacter pour nous demander la permission
belaran@999 214 de le faire, à moins que vous ne reproduisiez une partie significative
belaran@999 215 du code. Par exemple, écrire un programme qui utilise plusieurs
belaran@999 216 extraits de code du livre ne demande aucune autorisation particulière.
belaran@999 217 Vendre ou distribuer un CD-ROM provenant des livres O'Reilly demande
belaran@999 218 à l'inverse une autorisation. Répondre à une question en citant ce
belaran@999 219 livre ou ses exemples de code ne demande aucune autorisation préalable.
belaran@999 220 Intégrer une grande quantité des codes d'exemples de ce livre dans
belaran@999 221 votre propre ouvrage demande une autorisation de notre part.</para>
belaran@999 222
belaran@999 223 <para id="x_742">Nous apprécions, sans l'exiger, que vous citiez
belaran@999 224 l'ouvrage dans vos écrits l'utilisant, en indiquant le titre,
belaran@999 225 l'auteur, l'éditeur et son ISBN. Par exemple: “<emphasis>Titre du
belaran@999 226 livre</emphasis> par Son Auteur. Copyright 2008 O’Reilly Media, Inc.,
belaran@999 227 978-0-596-xxxx-x.”</para>
belaran@999 228
belaran@999 229 <para id="x_743">Si vous estimez que votre usage des exemples de code
belaran@999 230 dépasse le cadre défini ci dessus, n'hésitez pas à nous contacter :
belaran@999 231 <email>permissions@oreilly.com</email>.</para>
belaran@999 232 </sect1>
belaran@999 233
belaran@999 234 <sect1>
belaran@999 235 <title>Safari® Books Online</title>
belaran@999 236
belaran@999 237 <note role="safarienabled">
belaran@999 238 <para id="x_744">Quand vous voyez l'icône de Safari® Books Online
belaran@999 239 sur la couverture d'un de vos livres techniques préférés, cela signifie
belaran@999 240 que le livre est disponible, en ligne, à travers le O’Reilly Network Safari
belaran@999 241 Bookshelf.</para>
belaran@999 242 </note>
belaran@999 243
belaran@999 244 <para id="x_745">Safari offre une solution qui est meilleure que
belaran@999 245 les e-books. C'est une bibliothèque virtuelle qui vous laisse
belaran@999 246 aisément rechercher dans des milliers de livres, mais aussi
belaran@999 247 copier-coller leurs exemples, télécharger des chapitres, et
belaran@999 248 trouver des réponses rapides quand vous avez besoin d'une
belaran@999 249 information précise et à jour. Essayez le gratuitement :
belaran@999 250 <ulink role="orm:hideurl:ital" url="http://my.safaribooksonline.com/?portal=oreilly">http://my.safaribooksonline.com</ulink>.</para>
belaran@999 251 </sect1>
belaran@999 252
belaran@999 253 <sect1>
belaran@999 254 <title>Comment nous contacter</title>
belaran@999 255
belaran@999 256 <para id="x_746">Merci d'adresser vos commentaires et vos questions
belaran@999 257 sur ce livre à son éditeur:</para>
belaran@999 258
belaran@999 259 <simplelist type="vert">
belaran@999 260 <member>O’Reilly Media, Inc.</member>
belaran@999 261
belaran@999 262 <member>1005 Gravenstein Highway North</member>
belaran@999 263
belaran@999 264 <member>Sebastopol, CA 95472</member>
belaran@999 265
belaran@999 266 <member>800-998-9938 (in the United States or Canada)</member>
belaran@999 267
belaran@999 268 <member>707-829-0515 (international or local)</member>
belaran@999 269
belaran@999 270 <member>707 829-0104 (fax)</member>
belaran@999 271 </simplelist>
belaran@999 272
belaran@999 273 <para id="x_747">Nous avons une page web pour cet ouvrage, où nous
belaran@999 274 publions des errata, des exemples, et encore d'autres informations
belaran@999 275 additionnelles. Vous pouvez accéder à cette page par l'URL suivante:
belaran@999 276 </para>
belaran@999 277
belaran@999 278 <simplelist type="vert">
belaran@999 279 <member><ulink url="http://www.oreilly.com/catalog/&lt;catalog page&gt;"/></member>
belaran@999 280 </simplelist>
belaran@999 281
belaran@999 282 <remark>N'oubliez pas de mettre à jour l'attribut &lt;url&gt; aussi.</remark>
belaran@999 283
belaran@999 284 <para id="x_748">Pour commenter ou poser des questions techniques
belaran@999 285 sur cet ouvrage, envoyez un email à :</para>
belaran@999 286
belaran@999 287 <simplelist type="vert">
belaran@999 288 <member><email>bookquestions@oreilly.com</email></member>
belaran@999 289 </simplelist>
belaran@999 290
belaran@999 291 <para id="x_749">Pour plus d'informations sur nos livres, nos
belaran@999 292 conférences, nos centres d'informations, et le réseau O’Reilly,
belaran@999 293 voyez notre site web :</para>
belaran@999 294
belaran@999 295 <simplelist type="vert">
belaran@999 296 <member><ulink url="http://www.oreilly.com"/></member>
belaran@999 297 </simplelist>
belaran@999 298 </sect1>
belaran@999 299 </preface>
belaran@999 300
belaran@999 301 <!--
belaran@999 302 local variables:
belaran@999 303 sgml-parent-document: ("00book.xml" "book" "preface")
belaran@999 304 end:
belaran@999 305 -->
belaran@999 306
belaran@999 307 <!-- BEGIN ch01 -->
belaran@999 308 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 309
belaran@999 310 <chapter id="chap:intro">
belaran@999 311 <?dbhtml filename="how-did-we-get-here.html"?>
belaran@999 312 <title>Comment en est on arrivé là ?</title>
belaran@999 313
belaran@999 314 <sect1>
belaran@999 315 <title>À propos de la gestion source</title>
belaran@999 316
belaran@999 317 <para id="x_6d">La gestion de sources est un processus permettant de gérer différentes
belaran@999 318 versions de la même information. Dans sa forme la plus simple, c'est
belaran@999 319 ce que tout le monde fait manuellement : quand vous modifiez
belaran@999 320 un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro,
belaran@999 321 à chaque fois plus grand que celui de la version précédente.</para>
belaran@999 322
belaran@999 323 <para id="x_6e">Ce genre de gestion de version manuelle est cependant facilement sujette
belaran@999 324 aux erreurs, ainsi, depuis longtemps, des logiciels existent pour
belaran@999 325 résoudre cette problématique. Les premiers outils de gestion de sources
belaran@999 326 étaient destinés à aider un seul utilisateur, à automatiser la gestion
belaran@999 327 des versions d'un seul fichier. Dans les dernières décades, cette cible
belaran@999 328 s'est largement agrandie, ils gèrent désormais de multiples fichiers, et
belaran@999 329 aident un grand nombre de personnes à travailler ensemble. Les outils les
belaran@999 330 plus modernes n'ont aucune difficulté à gérer plusieurs milliers de
belaran@999 331 personnes travaillant ensemble sur des projets regroupant plusieurs
belaran@999 332 centaines de milliers de fichiers.</para>
belaran@999 333
belaran@999 334 <para id="x_6f">L'arrivée de la gestion de révision distribuée est
belaran@999 335 relativement récente, et, pour le moment, ce nouveau domaine a grandi
belaran@999 336 grâce à la volonté des gens d'explorer ces territoires encore inconnus.
belaran@999 337 </para>
belaran@999 338
belaran@999 339 <para id="x_70">J'écris un livre sur la gestion de révision distribuée
belaran@999 340 parce que je pense qu'il s'agit d'un sujet important qui mérite un guide
belaran@999 341 du terrain. J'ai choisi d'écrire un livre sur Mercurial car il est
belaran@999 342 l'outil le plus facile pour découvrir ce nouveau domaine, tout en étant
belaran@999 343 un outil efficace qui répond aux demandes d'environnements réels et
belaran@999 344 difficiles, là où d'autres outils de gestions de versions s'effondrent.</para>
belaran@999 345
belaran@999 346 <sect2>
belaran@999 347 <title>Pourquoi utiliser un gestionnaire de source ?</title>
belaran@999 348
belaran@999 349 <para id="x_71">Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez
belaran@999 350 utiliser un outil automatisant la gestion de version pour votre projet.</para>
belaran@999 351
belaran@999 352 <itemizedlist>
belaran@999 353 <listitem><para id="x_72">L'outil se chargera de suivre l'évolution de votre projet, sans
belaran@999 354 que vous ayez à le faire. Pour chaque modification, vous aurez à votre
belaran@999 355 disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis>
belaran@999 356 il l'a fait, <emphasis>quand</emphasis> il l'a fait, et
belaran@999 357 <emphasis>ce</emphasis> qu'il a modifié.</para>
belaran@999 358 </listitem>
belaran@999 359 <listitem><para id="x_73">Quand vous travaillez avec d'autres personnes, les logiciels de
belaran@999 360 gestion de source facilitent le travail collaboratif. Par exemple, quand
belaran@999 361 plusieurs personnes font, plus ou moins simultanément, des modifications
belaran@999 362 incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para>
belaran@999 363 </listitem>
belaran@999 364 <listitem><para id="x_74">L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement
belaran@999 365 qui se révèle être une erreur, vous pourrez revenir à une version
belaran@999 366 antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de
belaran@999 367 gestion de source <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel
belaran@999 368 moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus
belaran@999 369 de détails).</para>
belaran@999 370 </listitem>
belaran@999 371 <listitem><para id="x_75">L'outil vous permettra aussi de travailler sur plusieurs versions différentes
belaran@999 372 de votre projet et de gérer l'écart entre chacune.</para>
belaran@999 373 </listitem></itemizedlist>
belaran@999 374 <para id="x_76">La plupart de ces raisons ont autant d'importances —du
belaran@999 375 moins en théorie— que vous travailliez sur un projet pour vous, ou
belaran@999 376 avec une centaine d'autres personnes.
belaran@999 377 </para>
belaran@999 378
belaran@999 379 <para id="x_77">Une question fondamentale à propos des outils de gestion de
belaran@999 380 source, qu'il s'agisse du projet d'une personne ou d'une grande équipe, est
belaran@999 381 quels sont ses <emphasis>avantages</emphasis> par rapport à ses
belaran@999 382 <emphasis>coûts</emphasis>. Un outil qui est difficile à utiliser ou à
belaran@999 383 comprendre exigera un lourd effort d'adaptation.
belaran@999 384 </para>
belaran@999 385
belaran@999 386 <para id="x_78">)Un projet de cinq milles personnes s'effondrera très
belaran@999 387 certainement de lui même sans aucun processus et outil de gestion de
belaran@999 388 source. Dans ce cas, le coût d'utilisation d'un logiciel de gestion de
belaran@999 389 source est dérisoire puisque <emphasis>sans</emphasis>, l'échec est presque
belaran@999 390 garanti.
belaran@999 391 </para>
belaran@999 392
belaran@999 393 <para id="x_79">D'un autre coté, un <quote>rapide hack</quote> d'une personne
belaran@999 394 peut sembler un contexte bien pauvre pour utiliser un outil de gestion de
belaran@999 395 source, car, bien évidement le coût d'utilisation dépasse le coût total du
belaran@999 396 projet. N'est ce pas ?
belaran@999 397 </para>
belaran@999 398
belaran@999 399 <para id="x_7a">Mercurial supporte ces <emphasis>deux</emphasis>
belaran@999 400 échelles de travail. Vous pouvez apprendre les bases en quelques
belaran@999 401 minutes seulement, et, grâce à sa performance, vous pouvez l'utiliser
belaran@999 402 avec facilité sur le plus petit des projets. Cette simplicité
belaran@999 403 signifie que vous n'avez pas de concept obscurs ou de séquence de
belaran@999 404 commandes défiant l'imagination, sans aucune corrélation avec
belaran@999 405 <emphasis>ce que vous êtes entrain de faire</emphasis>. En même
belaran@999 406 temps, ces mêmes performances et sa nature
belaran@999 407 <quote>peer-to-peer</quote> vous permettent d'adapter, sans
belaran@999 408 difficulté, son utilisation à de très grands projets.
belaran@999 409 </para>
belaran@999 410
belaran@999 411 <para id="x_7b">Aucun outil de gestion de source ne peut sauver un
belaran@999 412 projet mal mené, mais un bon outil peut rendre beaucoup plus fluide
belaran@999 413 votre travail.
belaran@999 414 </para>
belaran@999 415
belaran@999 416 </sect2>
belaran@999 417
belaran@999 418 <sect2>
belaran@999 419 <title>Les multiples noms de la gestion de source</title>
belaran@999 420
belaran@999 421 <para id="x_7c">La gestion de source
belaran@999 422 <!-- TODO:<footnote><J'ai utilisé systématiquement le terme
belaran@999 423 <quote>gestion de source</quote> à travers tout l'ouvrage. Ce
belaran@999 424 n'est pas forcement la meilleure traduction, et ceci peut rendre
belaran@999 425 la lecture un peu lourde, mais je pense que le document y gagne
belaran@999 426 en clarté et en précision. -->
belaran@999 427 est un domaine tellement large qu'il n'existe pas qu'un seul nom ou
belaran@999 428 acronyme pour le désigner. Voici quelques noms ou acronymes que vous
belaran@999 429 rencontrerez le plus souvent.
belaran@999 430 <!-- TODO:<footnote> J'ai conservé la liste des noms en anglais pour
belaran@999 431 des raisons de commodité (ils sont plus <quote>googelable</quote>).
belaran@999 432 En outre, j'ai opté pour conserver l'ensemble des opérations de
belaran@999 433 Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en
belaran@999 434 anglais, là aussi pour faciliter la lecture d'autres documents en
belaran@999 435 anglais, ainsi que l'utilisation de Mercurial. -->
belaran@999 436 </para>
belaran@999 437
belaran@999 438 <para>:
belaran@999 439 </para>
belaran@999 440
belaran@999 441 <itemizedlist>
belaran@999 442 <listitem><para id="x_7d">Revision control (RCS)</para></listitem>
belaran@999 443 <listitem><para id="x_7e">Software configuration management (SCM), ou
belaran@999 444 configuration management</para></listitem>
belaran@999 445 <listitem><para id="x_7f">Source code management</para></listitem>
belaran@999 446 <listitem><para id="x_80">Source code control, ou source control</para></listitem>
belaran@999 447 <listitem><para id="x_81">Version control (VCS)</para></listitem></itemizedlist>
belaran@999 448
belaran@999 449 <para id="x_82">Certaines personnes prétendent que ces termes ont en fait
belaran@999 450 des sens différents mais en pratique ils se recouvrent tellement qu'il n'y
belaran@999 451 a pas réellement de manière pertinente de les distinguer. </para>
belaran@999 452
belaran@999 453 </sect2>
belaran@999 454 </sect1>
belaran@999 455
belaran@999 456 <sect1>
belaran@999 457
belaran@999 458 <title>A propos des exemples dans ce livre</title>
belaran@999 459
belaran@999 460 <para id="x_84">Ce livre prend une approche non usuel pour les exemples
belaran@999 461 de code. Tous les exemples sont en <quote>live</quote> — Chacun
belaran@999 462 est actuellement le résultat d'un script shell qui exécute les
belaran@999 463 commandes Mercurial que vous voyez. A chaque fois qu'une image du livre
belaran@999 464 est construite à partir des sources, tous les scripts d'exemple sont
belaran@999 465 lancés automatiquement, et leurs résultats effectifs sont comparés aux
belaran@999 466 résultats attendus.</para>
belaran@999 467
belaran@999 468 <para id="x_85">L'avantage de dette approche est que les exemples sont
belaran@999 469 toujours précis ; ils décrivent <emphasis>exactement</emphasis> la
belaran@999 470 conduite de la version de Mercurial qui est mentionnée en entête du
belaran@999 471 livre. Si je met à jour la version de Mercurial que je suis en train de
belaran@999 472 documenter, et que la sortie de certaines commandes change, la
belaran@999 473 construction du livre échoue.</para>
belaran@999 474
belaran@999 475 <para id="x_86">
belaran@999 476 Il existe un petit désavantage à cette approche qui est que les dates et
belaran@999 477 heures que vous verrez dans les exemples tendent à être
belaran@999 478 <quote>écrasés</quote> ensemble, dans le sens où elles ne sont pas
belaran@999 479 celles qu'elles auraient été si un humain avait tapé les commandes. En
belaran@999 480 effet, humain ne peut pas taper plus d'une commande toutes les quelques
belaran@999 481 secondes, avec le temps qui s'écoule, mes scripts d'exemples exécutent
belaran@999 482 plusieurs commandes en une seconde.
belaran@999 483 </para>
belaran@999 484
belaran@999 485 <para id="x_87">Une circonstance de ceci est que plusieurs commits
belaran@999 486 consécutifs dans un exemple peuvent apparaître comme ayant eu lieu
belaran@999 487 durant la même seconde.
belaran@999 488 Vous pouvez observer le phénomène dans l'exemple <literal role="hg-ext" moreinfo="none">bisect</literal> dans <xref linkend="sec:undo:bisect"/>
belaran@999 489 </para>
belaran@999 490
belaran@999 491 <para id="x_88">Donc, lorsque vous lisez ces exemples, ne prêtez pas trop
belaran@999 492 d'importance aux dates et heures que vous voyez dans la sortie des
belaran@999 493 commandes. Cependant, <emphasis>soyez</emphasis> confiants que le
belaran@999 494 comportement que vous voyez est consistent et reproductible
belaran@999 495 </para>
belaran@999 496
belaran@999 497 </sect1>
belaran@999 498
belaran@999 499 <!-- The next section has disapper from this part of the book. it may be splaced somewhere else... t-->
belaran@999 500
belaran@999 501 <sect1>
belaran@999 502 <title>Tendances de la gestion de source</title>
belaran@999 503
belaran@999 504 <para id="x_89">Il y a eu une tendance évidente dans le développement et
belaran@999 505 l'utilisation d'outils de gestion de source depuis les quatre dernières
belaran@999 506 décades, au fur et à mesure que les utilisateurs se sont habitués à
belaran@999 507 leur outils et se sont sentis contraints par leurs limitations.
belaran@999 508 </para>
belaran@999 509
belaran@999 510 <para id="x_8a">La première génération commença simplement par gérer un
belaran@999 511 fichier unique sur un ordinateur individuel. Cependant, même si ces
belaran@999 512 outils présentaient une grande avancée par rapport à la gestion
belaran@999 513 manuelle des versions, leur modèle de verrouillage et leur utilisation
belaran@999 514 limitée à un seul ordinateur rendaient leur utilisation possible
belaran@999 515 uniquement dans une très petite équipe.
belaran@999 516 </para>
belaran@999 517
belaran@999 518 <para id="x_8b">La seconde génération a assoupli ces contraintes en
belaran@999 519 adoptant une architecture réseau et centralisée, permettant de gérer
belaran@999 520 plusieurs projets entiers en même temps. Alors que les projets
belaran@999 521 grandirent en taille, ils rencontrèrent de nouveaux problèmes. Avec les
belaran@999 522 clients discutant régulièrement avec le serveurs, la montée en charge
belaran@999 523 devint un réel problème sur les gros projets. Une connexion réseau peu
belaran@999 524 fiable pouvait complètement empêcher les utilisateurs distants de
belaran@999 525 dialoguer avec le serveur. Alors que les projets <emphasis remap="it">Open Source</emphasis> commencèrent à mettre en place des
belaran@999 526 accès en lecture seule disponible anonymement, les utilisateurs sans
belaran@999 527 les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient
belaran@999 528 pas utiliser les outils pour collaborer naturellement avec le projet,
belaran@999 529 comme ils ne pouvaient pas non plus enregistrer leurs modifications.
belaran@999 530 </para>
belaran@999 531
belaran@999 532 <para id="x_8c">La génération actuelle des outils de gestion de source
belaran@999 533 est <quote>peer-to-peer</quote> par nature. Tous ces systèmes ont
belaran@999 534 abandonné la dépendance à un serveur central, et ont permis à leur
belaran@999 535 utilisateur de distribuer les données de leur gestion de source à qui
belaran@999 536 en a besoin. La collaboration à travers Internet a transformé la
belaran@999 537 contrainte technologique en une simple question de choix et de
belaran@999 538 consensus. Les outils modernes peuvent maintenant fonctionner en mode
belaran@999 539 déconnecté sans limite et de manière autonome, la connexion au réseau
belaran@999 540 n'étant nécessaire que pour synchroniser les modifications avec les
belaran@999 541 autres dépôts.
belaran@999 542 </para>
belaran@999 543 </sect1>
belaran@999 544
belaran@999 545 <sect1>
belaran@999 546 <title>Quelques avantages des gestionnaires de source distribués</title>
belaran@999 547
belaran@999 548 <para id="x_8d">Même si les gestionnaire de source distribués sont depuis
belaran@999 549 plusieurs années assez robustes et aussi utilisables que leurs
belaran@999 550 prédécesseurs, les utilisateurs d'autres outils n'y ont pas encore été
belaran@999 551 sensibilisés. Les gestionnaires de source distribués se distinguent
belaran@999 552 particulièrement de leurs équivalents centralisés de nombreuses
belaran@999 553 manières.
belaran@999 554 </para>
belaran@999 555
belaran@999 556 <para id="x_8e">Pour un développeur individuel, ils restent beaucoup plus
belaran@999 557 rapides que les outils centralisés. Cela pour une raison simple : un
belaran@999 558 outil centralisé doit toujours dialoguer à travers le réseau pour la
belaran@999 559 plupart des opérations, car presque toutes les métadonnées sont
belaran@999 560 stockées sur la seule copie du serveur central. Un outil distribué
belaran@999 561 stocke toute ses métadonnées localement. À tâche égale, effectuer un
belaran@999 562 échange avec le réseau ajoute un délai aux outils centralisés. Ne
belaran@999 563 sous-estimez pas la valeur d'un outil rapide : vous allez passer
belaran@999 564 beaucoup de temps à interagir avec un logiciel de gestion de source.
belaran@999 565 </para>
belaran@999 566
belaran@999 567 <para id="x_8f">Les outils distribués sont complètement indépendants des
belaran@999 568 aléas de votre serveur, d'autant plus qu'ils répliquent les métadonnées
belaran@999 569 à beaucoup d'endroits. Si votre serveur central prend feu, vous avez
belaran@999 570 intérêt à ce que les médias de sauvegardes soient fiables, et que votre
belaran@999 571 dernier <quote>backup</quote> soit récent et fonctionne sans problème.
belaran@999 572 Avec un outil distribué, vous avez autant de <quote>backup</quote> que
belaran@999 573 de contributeurs.
belaran@999 574 </para>
belaran@999 575
belaran@999 576 <para id="x_90">En outre, la fiabilité de votre réseau affectera beaucoup
belaran@999 577 moins les outils distribués. Vous ne pouvez même pas utiliser un outil
belaran@999 578 centralisé sans connexion réseau, à l'exception de quelques commandes,
belaran@999 579 très limitées. Avec un outil distribué, si votre connexion réseau tombe
belaran@999 580 pendant que vous travaillez, vous pouvez ne même pas vous en rendre
belaran@999 581 compte. La seule chose que vous ne serez pas capable de faire sera de
belaran@999 582 communiquer avec des dépôts distants, opération somme toute assez rare
belaran@999 583 en comparaison aux opérations locales. Si vous avez une équipe de
belaran@999 584 collaborateurs très dispersée ceci peut être significatif.
belaran@999 585 </para>
belaran@999 586
belaran@999 587 <sect2>
belaran@999 588 <title>Avantages pour les projets Open Source</title>
belaran@999 589
belaran@999 590 <para id="x_91">Si vous prenez goût à un projet <emphasis remap="it">Open Source</emphasis> et que vous décidez de commencer
belaran@999 591 à toucher à son code, et que le projet utilise un gestionnaire de
belaran@999 592 source distribué, vous êtes immédiatement un "pair" avec les
belaran@999 593 personnes formant le <quote>cœur</quote> du projet. S'ils publient
belaran@999 594 leurs dépôts, vous pouvez immédiatement copier leurs historiques de
belaran@999 595 projet, faire des modifications, enregistrer votre travail en
belaran@999 596 utilisant les mêmes outils qu'eux. Par comparaison avec un outil
belaran@999 597 centralisé, vous devez utiliser un logiciel en mode <quote>lecture
belaran@999 598 seule</quote> à moins que quelqu'un ne vous donne les privilèges de
belaran@999 599 <quote>commit</quote> sur le serveur central. Avant ça, vous ne serez
belaran@999 600 pas capable d'enregistrer vos modifications, et vos propres
belaran@999 601 modifications risqueront de se corrompre chaque fois que vous
belaran@999 602 essayerez de mettre à jour à votre espace de travail avec le serveur
belaran@999 603 central.
belaran@999 604 </para>
belaran@999 605
belaran@999 606 <sect3>
belaran@999 607 <title>Le non-problème du "fork"</title>
belaran@999 608
belaran@999 609 <para id="x_92">Il a été souvent suggéré que les gestionnaires de
belaran@999 610 source distribués posent un risque pour les projets <emphasis remap="it">Open Source</emphasis> car ils facilitent grandement la
belaran@999 611 création de <quote>fork</quote>.
belaran@999 612 <!--footnote{NdT:Création d'une <ulink url="version alternative du
belaran@999 613 logiciel">version alternative du
belaran@999 614 logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique}
belaran@999 615 -->
belaran@999 616 Un <quote>fork</quote> apparait quand il y des divergences d'opinion
belaran@999 617 ou d'attitude au sein d'un groupe de développeurs qui aboutissent à
belaran@999 618 la décision de ne plus travailler ensemble. Chaque parti s'empare
belaran@999 619 d'une copie plus ou moins complète du code source du projet et
belaran@999 620 continue dans sa propre direction.
belaran@999 621 </para>
belaran@999 622
belaran@999 623
belaran@999 624 <para id="x_93">Parfois ces différents partis décident de se
belaran@999 625 réconcilier. Avec un serveur central, l'aspect
belaran@999 626 <emphasis>technique</emphasis> de cette réconciliation est un
belaran@999 627 processus douloureux, et essentiellement manuel. Vous devez décider
belaran@999 628 quelle modification est <quote>la gagnante</quote>, et replacer, par
belaran@999 629 un moyen ou un autre, les modifications de l'autre équipe dans
belaran@999 630 l'arborescence du projet. Ceci implique généralement la perte d'une
belaran@999 631 partie de l'historique d'un des partis, ou même des deux.
belaran@999 632 </para>
belaran@999 633
belaran@999 634 <para id="x_94">Ce que les outils distribués permettent à ce sujet est
belaran@999 635 probablement la <emphasis>meilleure</emphasis> façon de développer un
belaran@999 636 projet. Chaque modification que vous effectuez est potentiellement un
belaran@999 637 <quote>fork</quote>. La grande force de cette approche est que les
belaran@999 638 gestionnaires de source distribués doivent être vraiment très
belaran@999 639 efficaces pour <emphasis>fusionner (merge)</emphasis>
belaran@999 640 <!-- TODO footnote{NdT:j'ai choisi de traduire ici <emphasis
belaran@999 641 remap="it">merging</emphasis> par <quote>fusionner</quote> pour des
belaran@999 642 raisons de clarté} -->
belaran@999 643 des <quote>forks</quote>, car les <quote>forks</quote>, dans ce
belaran@999 644 contexte, arrivent tout le temps.
belaran@999 645 </para>
belaran@999 646
belaran@999 647 <para id="x_95">Si chaque altération que n'importe qui effectue, à tout
belaran@999 648 moment, est vue comme un <quote>fork</quote> à fusionner, alors ce
belaran@999 649 que le monde de l'<emphasis remap="it">Open Source</emphasis> voit
belaran@999 650 comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis>
belaran@999 651 une problématique sociale. En fait, les outils de gestions de source
belaran@999 652 distribués <emphasis>réduisent</emphasis> les chances de
belaran@999 653 <quote>fork</quote> :
belaran@999 654 </para>
belaran@999 655
belaran@999 656 <itemizedlist>
belaran@999 657 <listitem>
belaran@999 658 <para>Ils éliminent la distinction sociale qu'imposent les outils
belaran@999 659 centralisés entre les membres du projets (ceux qui ont accès au
belaran@999 660 <quote>commit</quote>) et ceux de l'extérieur (ce qui ne l'ont
belaran@999 661 pas).
belaran@999 662 </para>
belaran@999 663 <para>Ils rendent plus facile la réconciliation après un
belaran@999 664 <quote>fork</quote> social, car tout ce qu'elle implique est une
belaran@999 665 simple fusion.
belaran@999 666 </para>
belaran@999 667 </listitem>
belaran@999 668 </itemizedlist>
belaran@999 669
belaran@999 670 <para id="x_98">Certaines personnes font de la résistance envers les
belaran@999 671 gestionnaires de source distribués parce qu'ils veulent garder un
belaran@999 672 contrôle ferme sur leur projet, et ils pensent que les outils
belaran@999 673 centralisés leur fournissent ce contrôle. Néanmoins, si c'est votre
belaran@999 674 cas, sachez que si vous publiez votre dépôt CVS ou Subversion de
belaran@999 675 manière publique, il existe une quantité d'outils disponibles pour
belaran@999 676 récupérer entièrement votre projet et son historique (quoique
belaran@999 677 lentement) et le récréer ailleurs, sans votre contrôle. En fait,
belaran@999 678 votre contrôle sur votre projet est illusoire, vous ne faites
belaran@999 679 qu'interdire à vos collaborateurs de travailler de manière fluide, en
belaran@999 680 disposant d'un miroir ou d'un <quote>fork</quote> de votre
belaran@999 681 historique.
belaran@999 682 </para>
belaran@999 683
belaran@999 684 </sect3>
belaran@999 685 </sect2>
belaran@999 686 <sect2>
belaran@999 687 <title>Avantages pour les projets commerciaux</title>
belaran@999 688
belaran@999 689 <para id="x_99">Beaucoup de projets commerciaux sont réalisés par des
belaran@999 690 équipes éparpillées à travers le globe. Les contributeurs qui sont
belaran@999 691 loin du serveur central devront subir des commandes lentes et même
belaran@999 692 parfois peu fiables. Les solutions propriétaires de gestion de source
belaran@999 693 tentent de palier ce problème avec des réplications de sites distants
belaran@999 694 qui sont à la fois coûteuses à mettre en place et lourdes à
belaran@999 695 administrer. Un système distribué ne souffre pas de ce genre de
belaran@999 696 problèmes. En outre, il est très aisé de mettre en place plusieurs
belaran@999 697 serveurs de références, disons un par site, de manière à ce qu'il n'y
belaran@999 698 ait pas de communication redondante entre les dépôts, sur une
belaran@999 699 connexion longue distance souvent onéreuse.
belaran@999 700 </para>
belaran@999 701
belaran@999 702 <para id="x_9a">Les systèmes de gestion de source supportent
belaran@999 703 généralement assez mal la monté en charge. Il n'est pas rare pour un
belaran@999 704 gestionnaire de source centralisé pourtant onéreux de s'effondrer
belaran@999 705 sous la charge combinée d'une douzaine d'utilisateurs concurrents
belaran@999 706 seulement. Une fois encore, la réponse à cette problématique est
belaran@999 707 généralement encore la mise en place d'un ensemble complexe de
belaran@999 708 serveurs synchronisés par un mécanisme de réplication. Dans le cas
belaran@999 709 d'un gestionnaire de source distribué, la charge du serveur central
belaran@999 710 — si vous avez un— est plusieurs fois inférieure (car
belaran@999 711 toutes les données sont déjà répliquées ailleurs), un simple serveur,
belaran@999 712 pas très cher, peut gérer les besoins d'une plus grande équipe, et la
belaran@999 713 réplication pour balancer la charge devient le travail d'un simple
belaran@999 714 script.
belaran@999 715 </para>
belaran@999 716
belaran@999 717 <para id="x_9b">Si vous avez des employés sur le terrain, en train de
belaran@999 718 chercher à résoudre un souci sur le site d'un client, ils
belaran@999 719 bénéficieront aussi d'un gestionnaire de source distribué. Cet outil
belaran@999 720 leur permettra de générer des versions personnalisées, d'essayer
belaran@999 721 différentes solutions, en les isolant aisément les unes des autres,
belaran@999 722 et de rechercher efficacement à travers l'historique des sources, la
belaran@999 723 cause des bugs ou des régressions, tout ceci sans avoir besoin de la
belaran@999 724 moindre connexion au réseau de votre compagnie.
belaran@999 725 </para>
belaran@999 726
belaran@999 727 </sect2>
belaran@999 728 </sect1>
belaran@999 729 <sect1>
belaran@999 730 <title>Pourquoi choisir Mercurial?</title>
belaran@999 731
belaran@999 732 <para id="x_9c">Mercurial a plusieurs caractéristiques qui en font un
belaran@999 733 choix particulièrement pertinent pour la gestion de source :
belaran@999 734 </para>
belaran@999 735 <itemizedlist>
belaran@999 736 <listitem><para id="x_9d">Il est simple à apprendre et à utiliser.</para></listitem>
belaran@999 737 <listitem><para id="x_9e">Il est léger.</para></listitem>
belaran@999 738 <listitem><para id="x_9f">Il s'adapte très bien à la charge.</para></listitem>
belaran@999 739 <listitem><para id="x_a0">Il se personnalise facilement.</para></listitem>
belaran@999 740 </itemizedlist>
belaran@999 741
belaran@999 742 <para id="x_a1">Si vous êtes déjà familier d'un outil de gestion de
belaran@999 743 source, vous serez capable de l'utiliser en moins de 5 minutes. Sinon,
belaran@999 744 ça ne sera pas beaucoup plus long. Les commandes utilisées par
belaran@999 745 Mercurial, comme ses fonctionnalités, sont généralement uniformes et
belaran@999 746 cohérentes, et vous pouvez ainsi garder en tête simplement quelques
belaran@999 747 règles générales, plutôt qu'un lot complexe d'exceptions.
belaran@999 748 </para>
belaran@999 749
belaran@999 750 <para id="x_a2">Sur un petit projet, vous pouvez commencer à travailler
belaran@999 751 avec Mercurial en quelques instants. Ajouter des modifications ou des
belaran@999 752 branches, transférer ces modifications (localement ou via le réseau),
belaran@999 753 et les opérations d'historique ou de statut sont aussi très rapides.
belaran@999 754 Mercurial reste hors de votre chemin grâce à sa simplicité
belaran@999 755 d'utilisation et sa rapidité d'exécution.
belaran@999 756 </para>
belaran@999 757
belaran@999 758 <para id="x_a3">L'utilité de Mercurial ne se limite pas à de petits
belaran@999 759 projets: il est aussi utilisé par des projets ayant des centaines ou
belaran@999 760 même des milliers de contributeurs, avec plusieurs dizaines de milliers
belaran@999 761 de fichiers, et des centaines de méga octets de code source.
belaran@999 762 </para>
belaran@999 763
belaran@999 764 <para id="x_a4">Si les fonctionnalités au cœur de Mercurial ne sont pas
belaran@999 765 suffisantes pour vous, il est très aisé d'en construire d'autres.
belaran@999 766 Mercurial est adapté à l'utilisation de scripts, et son implémentation
belaran@999 767 interne en Python, propre et claire, rend encore plus facile l'ajout de
belaran@999 768 fonctionnalités sous forme d'extensions. Il en existe déjà un certain
belaran@999 769 nombre de très populaires et très utiles, dont le périmètre va de la
belaran@999 770 recherche de bugs à l'amélioration des performances.
belaran@999 771 </para>
belaran@999 772
belaran@999 773 </sect1>
belaran@999 774 <sect1>
belaran@999 775 <title>Mercurial comparé aux autres outils</title>
belaran@999 776
belaran@999 777 <para id="x_a5">Avant que vous n'alliez plus loin, comprenez bien que
belaran@999 778 cette section reflète mes propres expériences, et elle est donc (j'ose
belaran@999 779 le dire) peu objective. Néanmoins, j'ai utilisé les outils de gestion
belaran@999 780 de source listés ci dessous, dans la plupart des cas, pendant plusieurs
belaran@999 781 années.
belaran@999 782 </para>
belaran@999 783
belaran@999 784 <sect2>
belaran@999 785 <title>Subversion</title>
belaran@999 786
belaran@999 787 <para id="x_a6">Subversion est un des outils de gestion de source les
belaran@999 788 plus populaire, il fût développé pour remplacer CVS. Il a une
belaran@999 789 architecture client/server centralisée.
belaran@999 790 </para>
belaran@999 791
belaran@999 792 <para id="x_a7">Subversion et Mercurial ont des noms de commandes très
belaran@999 793 similaires pour les mêmes opérations, ainsi si vous êtes familier
belaran@999 794 avec l'un, c'est facile d'apprendre l'autre. Ces deux outils sont
belaran@999 795 portables sur les systèmes d'exploitation les plus populaires.
belaran@999 796 </para>
belaran@999 797
belaran@999 798 <para id="x_a8">Avant la version 1.5, Subversion n'offrait aucune forme
belaran@999 799 de support pour les fusions. Lors de l'écriture de ce livre, ses
belaran@999 800 capacités de fusion étaient nouvelles, et réputées pour être <ulink url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">
belaran@999 801 complexes et buguées</ulink>.
belaran@999 802 </para>
belaran@999 803
belaran@999 804 <para id="x_a9">Mercurial dispose d'un avantage substantiel en terme de
belaran@999 805 performance par rapport à Subversion sur la plupart des opérations
belaran@999 806 que j'ai pu tester. J'ai mesuré une différence de performance allant
belaran@999 807 de deux à six fois plus rapide avec le système de stockage de fichier
belaran@999 808 local de Subversion 1.4.3 (<emphasis>ra_local</emphasis>), qui est la
belaran@999 809 méthode d'accès la plus rapide disponible. Dans un déploiement plus
belaran@999 810 réaliste, impliquant un stockage réseau, Subversion serait encore
belaran@999 811 plus désavantagé. Parce que la plupart des commandes Subversion
belaran@999 812 doivent communiquer avec le serveur et que Subversion n'a pas de
belaran@999 813 mécanisme de réplication, la capacité du serveur et la bande passante
belaran@999 814 sont devenues des goulots d'étranglement pour les projets de taille
belaran@999 815 moyenne ou grande.
belaran@999 816 </para>
belaran@999 817
belaran@999 818 <para id="x_aa">En outre, Subversion implique une surcharge
belaran@999 819 substantielle dans le stockage local de certaines données, pour
belaran@999 820 éviter des transactions avec le serveur, pour certaines opérations
belaran@999 821 communes, telles que la recherche des fichiers modifiés
belaran@999 822 (<literal moreinfo="none">status</literal>) et l'affichage des modifications par
belaran@999 823 rapport à la révision courante (<literal moreinfo="none">diff</literal>). En
belaran@999 824 conséquence, un répertoire de travail Subversion a souvent la même
belaran@999 825 taille, ou est plus grand, qu'un dépôt Mercurial et son espace de
belaran@999 826 travail, et ceci bien que le dépôt Mercurial contienne l'intégralité
belaran@999 827 de l'historique.
belaran@999 828 </para>
belaran@999 829
belaran@999 830 <para id="x_ab">Subversion est largement supporté par les outils
belaran@999 831 tierces. Mercurial est actuellement encore en retrait de ce point de
belaran@999 832 vue. L'écart se réduit néanmoins, en effet, certains des outils
belaran@999 833 graphiques sont maintenant supérieurs à leurs équivalents Subversion.
belaran@999 834 Comme Mercurial, Subversion dispose d'un excellent manuel
belaran@999 835 utilisateur.
belaran@999 836 </para>
belaran@999 837
belaran@999 838 <para id="x_ac">Parce que Subversion ne stocke pas l'historique chez
belaran@999 839 ses clients, il est parfaitement adapté à la gestion de projets qui
belaran@999 840 doivent suivre un ensemble de larges fichiers binaires et opaques. Si
belaran@999 841 vous suivez une cinquantaine de versions d'un fichier incompressible
belaran@999 842 de 10MB, l'occupation disque coté client d'un projet sous Subversion
belaran@999 843 restera à peu près constante. A l'inverse, l'occupation disque du
belaran@999 844 même projet sous n'importe lequel des gestionnaires de source
belaran@999 845 distribués grandira rapidement, proportionnellement aux nombres de
belaran@999 846 versions, car les différences entre chaque révisions seront très
belaran@999 847 grandes.
belaran@999 848 </para>
belaran@999 849
belaran@999 850 <para id="x_ad">En outre, c'est souvent difficile ou, généralement,
belaran@999 851 impossible de fusionner des différences dans un fichier binaire. La
belaran@999 852 capacité de Subversion de verrouiller des fichiers, pour permettre à
belaran@999 853 l'utilisateur d'être le seul à le mettre à jour
belaran@999 854 (<quote>commit</quote>) temporairement, est un avantage significatif
belaran@999 855 dans un projet doté de beaucoup de fichiers binaires.
belaran@999 856 </para>
belaran@999 857
belaran@999 858 <para id="x_ae">Mercurial peut importer l'historique depuis un dépôt
belaran@999 859 Subversion. Il peut aussi exporter l'ensemble des révisions d'un
belaran@999 860 projet vers un dépôt Subversion. Ceci rend très facile de
belaran@999 861 <quote>prendre la température</quote> et d'utiliser Mercurial et
belaran@999 862 Subversion en parallèle, avant de décider de migrer vers Mercurial.
belaran@999 863 La conversion de l'historique est incrémentale, donc vous pouvez
belaran@999 864 effectuer une conversion initiale, puis de petites additions par la
belaran@999 865 suite pour ajouter les nouvelle modifications.
belaran@999 866 </para>
belaran@999 867
belaran@999 868
belaran@999 869 </sect2>
belaran@999 870 <sect2>
belaran@999 871 <title>Git</title>
belaran@999 872
belaran@999 873 <para id="x_af">Git est un outil de gestion de source distribué qui fût
belaran@999 874 développé pour gérer le code source de noyau de Linux. Comme
belaran@999 875 Mercurial, sa conception initiale a été inspirée par Monotone.
belaran@999 876 </para>
belaran@999 877
belaran@999 878 <para id="x_b0">Git dispose d'un ensemble conséquent de commandes, avec
belaran@999 879 plus de 139 commandes individuelles pour la version 1.5.0. Il a aussi
belaran@999 880 la réputation d'être difficile à apprendre. Comparé à Git, le point
belaran@999 881 fort de Mercurial est clairement sa simplicité.
belaran@999 882 </para>
belaran@999 883
belaran@999 884 <para id="x_b1">En terme de performance, Git est extrêmement rapide.
belaran@999 885 Dans la plupart des cas, il est plus rapide que Mercurial, tout du
belaran@999 886 moins sur Linux, alors que Mercurial peut être plus performant sur
belaran@999 887 d'autres opérations. Néanmoins, sur Windows, les performances et le
belaran@999 888 niveau de support général fourni par Git, au moment de l'écriture de
belaran@999 889 cet ouvrage, est bien derrière celui de Mercurial.
belaran@999 890 </para>
belaran@999 891
belaran@999 892 <para id="x_b2">Alors que le dépôt Mercurial ne demande aucune
belaran@999 893 maintenance, un dépôt Git exige d'exécuter manuellement et
belaran@999 894 régulièrement la commande <quote>repacks</quote> sur ses métadonnées.
belaran@999 895 Sans ceci, les performances de git se dégradent et la consommation de
belaran@999 896 l'espace disque augmente rapidement. Un serveur qui contient
belaran@999 897 plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment
belaran@999 898 <quote>repacked</quote> deviendra un vrai problème lors des
belaran@999 899 <quote>backups</quote> du disque, et il y eu des cas, où un
belaran@999 900 <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un
belaran@999 901 dépôt fraichement <quote>repacked</quote> sera légèrement plus petit
belaran@999 902 qu'un dépôt Mercurial, mais un dépôt non <quote>repacked</quote> est
belaran@999 903 beaucoup plus grand.
belaran@999 904 </para>
belaran@999 905
belaran@999 906 <para id="x_b3">Le cœur de Git est écrit en C. La plupart des commandes
belaran@999 907 Git sont implémentées sous forme de scripts Shell ou Perl, et la
belaran@999 908 qualité de ces scripts varie grandement. J'ai plusieurs fois constaté
belaran@999 909 que certains de ces scripts étaient chargés en mémoire aveuglément et
belaran@999 910 que la présence d'erreurs pouvait s'avérer fatal.
belaran@999 911 </para>
belaran@999 912
belaran@999 913 <para id="x_b4">Mercurial peut importer l'historique d'un dépôt Git.</para>
belaran@999 914
belaran@999 915 </sect2>
belaran@999 916 <sect2>
belaran@999 917 <title>CVS</title>
belaran@999 918
belaran@999 919 <para id="x_b5">CVS est probablement l'outil de gestion de source le
belaran@999 920 plus utilisé aujourd'hui dans le monde. À cause de son manque de
belaran@999 921 clarté interne, il n'est plus maintenu depuis plusieurs années.
belaran@999 922 </para>
belaran@999 923
belaran@999 924 <para id="x_b6">Il a une architecture client/serveur centralisée. Il ne
belaran@999 925 regroupe pas les modifications de fichiers dans une opération de
belaran@999 926 <quote>commit</quote> atomique, ce qui permet à ses utilisateurs de
belaran@999 927 <quote>casser le <emphasis>build</emphasis></quote> assez facilement
belaran@999 928 : une personne peut effectuer une opération de <quote>commit</quote>
belaran@999 929 sans problème puis être bloquée par besoin de fusion, avec comme
belaran@999 930 conséquence néfaste, que les autres utilisateurs ne récupèreront
belaran@999 931 qu'une partie de ses modifications. Ce problème affecte aussi la
belaran@999 932 manière de travailler avec l'historique du projet. Si vous voulez
belaran@999 933 voir toutes les modifications d'une personne du projet, vous devrez
belaran@999 934 injecter manuellement les descriptions et les <emphasis remap="it">timestamps</emphasis> des modifications de chacun des
belaran@999 935 fichiers impliqués (si vous savez au moins quels sont ces fichiers).
belaran@999 936 </para>
belaran@999 937
belaran@999 938 <para id="x_b7">CVS a une notion étrange des <emphasis remap="it">tags</emphasis> et des branches que je n'essayerai même
belaran@999 939 pas de décrire ici. Il ne supporte pas bien les opérations de
belaran@999 940 renommage d'un fichier ou d'un répertoire, ce qui facilite la
belaran@999 941 corruption de son dépôt. Il n'a presque pas pour ainsi dire de
belaran@999 942 contrôle de cohérence interne, il est donc pratiquement impossible de
belaran@999 943 dire si un dépôt est corrompu ni à quel point. Je ne recommanderai
belaran@999 944 pas CVS pour un projet existant ou nouveau.
belaran@999 945 </para>
belaran@999 946
belaran@999 947 <para id="x_b8">Mercurial peut importer l'historique d'un projet CVS.
belaran@999 948 Néanmoins, il y a quelques principes à respecter; ce qui est vrai
belaran@999 949 aussi pour les autres outils d'import de projet CVS. À cause de
belaran@999 950 l'absence de <quote>commit</quote> atomique et gestion de version de
belaran@999 951 l'arborescence, il n'est pas possible de reconstruire de manière
belaran@999 952 précise l'ensemble de l'historique. Un travail de
belaran@999 953 <quote>devinette</quote> est donc nécessaire, et les fichiers
belaran@999 954 renommés ne sont pas détectés. Parce qu'une bonne part de
belaran@999 955 l'administration d'un dépôt CVS est effectuée manuellement, et est
belaran@999 956 donc, sujette à erreur, il est courant que les imports CVS
belaran@999 957 rencontrent de nombreux problèmes avec les dépôt corrompus (des
belaran@999 958 <emphasis remap="it">timestamps</emphasis> de révision complètement
belaran@999 959 buggés et des fichiers verrouillés depuis des années sont deux des
belaran@999 960 problèmes les moins intéressants dont je me souvienne).
belaran@999 961 </para>
belaran@999 962
belaran@999 963 <para id="x_b9">Mercurial peut importer l'historique depuis un dépôt CVS.
belaran@999 964 </para>
belaran@999 965
belaran@999 966
belaran@999 967 </sect2>
belaran@999 968 <sect2>
belaran@999 969 <title>Outils propriétaires</title>
belaran@999 970
belaran@999 971 <para id="x_ba">Perforce a une architecture client/serveur centralisée,
belaran@999 972 sans aucun mécanisme de mise en cache de données coté client.
belaran@999 973 Contrairement à la plupart des outils modernes de gestion de source,
belaran@999 974 Perforce exige de ses utilisateurs d'exécuter une commande pour
belaran@999 975 informer le serveur central de tout fichier qu'ils souhaitent
belaran@999 976 modifier.
belaran@999 977 </para>
belaran@999 978
belaran@999 979 <para id="x_bb">Les performances de Perforce sont plutôt bonnes pour
belaran@999 980 des petites équipes, mais elles s'effondrent rapidement lorsque le
belaran@999 981 nombre d'utilisateurs augmente au delà de la douzaine. Des
belaran@999 982 installations de Perforce assez larges nécessitent le déploiement de
belaran@999 983 proxies pour supporter la montée en charge associée.
belaran@999 984 </para>
belaran@999 985
belaran@999 986 </sect2>
belaran@999 987 <sect2>
belaran@999 988 <title>Choisir un outil de gestion de source</title>
belaran@999 989
belaran@999 990 <para id="x_bc">A l'exception de CVS, tous les outils listés ci-dessus
belaran@999 991 ont des forces qui leur sont propres et qui correspondent à certaines
belaran@999 992 formes de projet. Il n'y a pas un seul meilleur outil de gestion de
belaran@999 993 source qui correspondrait le mieux à toutes les situations.
belaran@999 994 </para>
belaran@999 995
belaran@999 996 <para id="x_bd">En guise exemple, Subversion est un très bon choix
belaran@999 997 lorsqu'on travaille avec beaucoup de fichiers binaires, qui évoluent
belaran@999 998 régulièrement, grâce à sa nature centralisée et sa capacité à
belaran@999 999 verrouiller des fichiers.
belaran@999 1000 </para>
belaran@999 1001
belaran@999 1002 <para id="x_be">Personnellement, je préfère Mercurial pour sa
belaran@999 1003 simplicité, ses performances et sa bonne capacité de fusion, et il
belaran@999 1004 m'a très bien rendu service de plusieurs années maintenant.
belaran@999 1005 </para>
belaran@999 1006
belaran@999 1007 </sect2>
belaran@999 1008 </sect1>
belaran@999 1009 <sect1>
belaran@999 1010 <title>Migrer depuis un outil à Mercurial</title>
belaran@999 1011
belaran@999 1012 <para id="x_bf">Mercurial est livré avec une extension nommée <literal role="hg-ext" moreinfo="none">convert</literal>, qui peut, de manière incrémentale
belaran@999 1013 importer des révisions depuis différents autres outils de gestion de
belaran@999 1014 source. Par <quote>incrémental</quote>, j'entends que vous pouvez
belaran@999 1015 convertir l'historique entier du projet en une seule fois, puis
belaran@999 1016 relancer l'outil d'import plus tard pour obtenir les modifications
belaran@999 1017 effectuées depuis votre import initial.
belaran@999 1018 </para>
belaran@999 1019
belaran@999 1020 <para id="x_c0">Les outils de gestion de source supportés par <literal role="hg-ext" moreinfo="none">convert</literal> sont :
belaran@999 1021 </para>
belaran@999 1022 <itemizedlist>
belaran@999 1023 <listitem><para id="x_c1">Subversion</para></listitem>
belaran@999 1024 <listitem><para id="x_c2">CVS</para></listitem>
belaran@999 1025 <listitem><para id="x_c3">Git</para></listitem>
belaran@999 1026 <listitem><para id="x_c4">Darcs</para></listitem>
belaran@999 1027 </itemizedlist>
belaran@999 1028
belaran@999 1029 <para id="x_c5">En outre, <literal role="hg-ext" moreinfo="none">convert</literal> peut
belaran@999 1030 exporter les modifications depuis Mercurial vers Subversion. Ceci rend
belaran@999 1031 possible d'essayer Subversion en parallèle avant de choisir une
belaran@999 1032 solution définitive, sans aucun risque de perte de données.
belaran@999 1033 </para>
belaran@999 1034
belaran@999 1035 <para id="x_c6">La commande <command role="hg-ext-conver" moreinfo="none">convert</command> est très simple à utiliser.
belaran@999 1036 Simplement, indiquez le chemin ou l'URL du dépôt de source, en lui
belaran@999 1037 indiquant éventuellement le nom du chemin de destination, et la
belaran@999 1038 conversion se met en route. Après cet import initial, il suffit de
belaran@999 1039 relancer la commande encore une fois pour importer les modifications
belaran@999 1040 effectuées depuis.
belaran@999 1041 </para>
belaran@999 1042 </sect1>
belaran@999 1043
belaran@999 1044 <sect1>
belaran@999 1045 <title>Une courte histoire de la gestion de source</title>
belaran@999 1046
belaran@999 1047 <para id="x_c7">Le plus célèbre des anciens outils de gestion de source
belaran@999 1048 est <emphasis remap="it">SCCS</emphasis> (Source Code Control System)},
belaran@999 1049 que Marc Rochkind conçu dans les laboratoires de recherche de Bell
belaran@999 1050 (<emphasis remap="it">Bell Labs</emphasis>), dans le début des années
belaran@999 1051 70. <emphasis remap="it">SCCS</emphasis> ne fonctionnait que sur des
belaran@999 1052 fichiers individuels, et obligeait chaque personne travaillant sur le
belaran@999 1053 projet d'avoir un accès à un répertoire de travail commun, sur le même
belaran@999 1054 système. Seulement une seule personne pouvait modifier un fichier au
belaran@999 1055 même moment, ce fonctionnement était assuré par l'utilisation de verrou
belaran@999 1056 (<quote>lock</quote>). Il était courant que des personnes verrouillent
belaran@999 1057 des fichiers, et plus tard, oublient de le déverrouiller ; empêchant
belaran@999 1058 n'importe qui d'autre de travailler sur ces fichiers sans l'aide de
belaran@999 1059 l'administrateur...
belaran@999 1060 </para>
belaran@999 1061
belaran@999 1062 <para id="x_c8">Walter Tichy a développé une alternative libre à
belaran@999 1063 <emphasis remap="it">SCCS</emphasis> au début des années 80, qu'il
belaran@999 1064 nomma <emphasis remap="it">RCS (Revision Control System)</emphasis>.
belaran@999 1065 Comme <emphasis remap="it">SCCS</emphasis>, <emphasis remap="it">RCS</emphasis> demandait aux développeurs de travailler
belaran@999 1066 sur le même répertoire partagé, et de verrouiller les fichiers pour se
belaran@999 1067 prémunir de tout conflit issu de modifications concurrentes.
belaran@999 1068 </para>
belaran@999 1069
belaran@999 1070 <para id="x_c9">Un peu plus tard dans les années 1980, Dick Grune utilisa
belaran@999 1071 <emphasis remap="it">RCS</emphasis> comme une brique de base pour un
belaran@999 1072 ensemble de scripts <emphasis remap="it">shell</emphasis> qu'il
belaran@999 1073 intitula cmt, avant de la renommer en <emphasis remap="it">CVS
belaran@999 1074 (Concurrent Versions System)</emphasis>. La grande innovation de CVS
belaran@999 1075 était que les développeurs pouvaient travailler simultanément et
belaran@999 1076 indépendamment dans leur propre espace de travail. Ces espaces de
belaran@999 1077 travail privés assuraient que les développeurs ne se marchent pas
belaran@999 1078 mutuellement sur les pieds, comme c'était souvent le cas avec RCS et
belaran@999 1079 SCCS. Tous les développeurs disposaient donc de leur copie de tous les
belaran@999 1080 fichiers du projet, et ils pouvaient donc librement les modifier. Ils
belaran@999 1081 devaient néanmoins effectuer la <quote>fusion</quote> (<emphasis remap="it"><quote>merge</quote></emphasis>) de leurs fichiers, avant
belaran@999 1082 d'effectuer le <quote>commit</quote> de leurs modifications sur le dépôt
belaran@999 1083 central.
belaran@999 1084 </para>
belaran@999 1085
belaran@999 1086 <para>Brian Berliner reprit les scripts de Grune's et les réécrit en C,
belaran@999 1087 qu'il publia en 1989. Depuis, ce code a été modifié jusqu'à devenir la
belaran@999 1088 version moderne de CVS. CVS a acquis ainsi la capacité de fonctionner
belaran@999 1089 en réseau, transformant son architecture en client/serveur.
belaran@999 1090 L'architecture de CVS est centralisée, seul le serveur a une copie de
belaran@999 1091 l'historique du projet. L'espace de travail client ne contient qu'une
belaran@999 1092 copie de la dernière version du projet, et quelques métadonnées pour
belaran@999 1093 indiquer où le serveur se trouve. CVS a été un grand succès,
belaran@999 1094 aujourd'hui il est probablement l'outil de gestion de contrôle le plus
belaran@999 1095 utilisé au monde.
belaran@999 1096 </para>
belaran@999 1097
belaran@999 1098 <para>Au début des années 1990, Sun Microsystems développa un premier
belaran@999 1099 outil de gestion de source distribué, nommé TeamWare. Un espace de
belaran@999 1100 travail TeamWare contient une copie complète de l'historique du projet.
belaran@999 1101 TeamWare n'a pas de notion de dépôt central. (CVS utilisait RCS pour le
belaran@999 1102 stockage de l'historique, TeamWare utilisait SCCS).
belaran@999 1103 </para>
belaran@999 1104
belaran@999 1105 <para>Alors que les années 1990 avançaient, les utilisateurs ont pris
belaran@999 1106 conscience d'un certain nombre de problèmes avec CVS. Il enregistrait
belaran@999 1107 simultanément des modifications sur différents fichiers
belaran@999 1108 individuellement, au lieu de les regrouper dans une seule opération
belaran@999 1109 cohérente et atomique. Il ne gère pas bien sa hiérarchie de fichier, il
belaran@999 1110 est donc assez aisé de créer le chaos en renommant les fichiers et les
belaran@999 1111 répertoires. Pire encore, son code source est difficile à lire et à
belaran@999 1112 maintenir, ce qui agrandit largement le <quote>niveau de
belaran@999 1113 souffrance</quote> associé à la réparation de ces problèmes
belaran@999 1114 d'architecture de manière prohibitive.
belaran@999 1115 </para>
belaran@999 1116
belaran@999 1117 <para>En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient
belaran@999 1118 travaillé sur CVS, initièrent un projet pour le remplacer par un outil
belaran@999 1119 qui aurait une meilleure architecture et un code plus propre. Le
belaran@999 1120 résultat, Subversion, ne quitte pas le modèle centralisé et
belaran@999 1121 client/server de CVS, mais ajoute les opérations de
belaran@999 1122 <quote>commit</quote> atomique sur de multiples fichiers, une meilleure
belaran@999 1123 gestion des espaces de noms, et d'autres fonctionnalités qui en font un
belaran@999 1124 meilleur outil que CVS. Depuis sa première publication, il est
belaran@999 1125 rapidement devenu très populaire.
belaran@999 1126 </para>
belaran@999 1127
belaran@999 1128 <para>Plus ou moins simultanément, Graydon Hoare a commencé sur
belaran@999 1129 l'ambitieux système de gestion distribué Monotone. Bien que Monotone
belaran@999 1130 corrige plusieurs défauts de CVS tout en offrant une architecture
belaran@999 1131 <quote>peer-to-peer</quote>, il va aussi plus loin que la plupart des
belaran@999 1132 outils de révision de manière assez innovante. Il utilise des
belaran@999 1133 <quote>hashs</quote> cryptographiques comme identifiants, et il a une
belaran@999 1134 notion complète de <quote>confiance</quote> du code issu des
belaran@999 1135 différentes sources.
belaran@999 1136 </para>
belaran@999 1137
belaran@999 1138 <para>Mercurial est né en 2005. Bien que très influencé par Monotone,
belaran@999 1139 Mercurial se concentre sur la facilité d'utilisation, les performances
belaran@999 1140 et la capacité à monter en charge pour de très gros projets.
belaran@999 1141 </para>
belaran@999 1142
belaran@999 1143 </sect1>
belaran@999 1144
belaran@999 1145 </chapter>
belaran@999 1146
belaran@999 1147 <!--
belaran@999 1148 local variables:
belaran@999 1149 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 1150 end:
belaran@999 1151 -->
belaran@999 1152
belaran@999 1153 <!-- BEGIN ch02 -->
belaran@999 1154 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 1155
belaran@999 1156 <chapter id="chap:tour-basic">
belaran@999 1157 <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?>
belaran@999 1158 <title>Une rapide présentation de Mercurial : les bases</title>
belaran@999 1159
belaran@999 1160 <sect1>
belaran@999 1161 <title>Installer Mercurial sur votre système</title>
belaran@999 1162
belaran@999 1163 <para id="x_1">Des paquetages binaires de Mercurial sont disponibles pour la
belaran@999 1164 plupart des systèmes d'exploitation, ce qui rend facile l'utilisation
belaran@999 1165 immédiate de Mercurial sur votre ordinateur.</para>
belaran@999 1166
belaran@999 1167 <sect2>
belaran@999 1168 <title>Windows</title>
belaran@999 1169
belaran@999 1170 <para id="x_c">La meilleur version de Mercurial pour Windows est
belaran@999 1171 TortoiseHg, qui peut être téléchargée ici : <ulink url="http://bitbucket.org/tortoisehg/stable/wiki/Home">http://bitbucket.org/tortoisehg/stable/wiki/Home</ulink>.
belaran@999 1172 Ce logiciel n'a aucune dépendance exterieure; il fonctionne <quote>et
belaran@999 1173 c'est tout</quote>. Il fournit aussi bien les outils en ligne de
belaran@999 1174 commmande qu'une interface graphique.</para>
belaran@999 1175
belaran@999 1176 </sect2>
belaran@999 1177
belaran@999 1178 <sect2>
belaran@999 1179 <title>Mac OS X</title>
belaran@999 1180
belaran@999 1181 <para id="x_a">Lee Cantey publie un installeur de Mercurial pour Mac OS
belaran@999 1182 X sur <ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>.</para>
belaran@999 1183 </sect2>
belaran@999 1184
belaran@999 1185 <sect2>
belaran@999 1186 <title>Linux</title>
belaran@999 1187
belaran@999 1188 <para id="x_2">Parce que chaque distribution de Linux a ses propres
belaran@999 1189 outils de gestion de paquets, politiques et rythmes de
belaran@999 1190 développements, il est difficile de donner un ensemble
belaran@999 1191 d'instructions unique pour installer les binaires de Mercurial. La
belaran@999 1192 version de Mercurial avec laquelle vous vous retrouverez dépendra
belaran@999 1193 grandement de l'activité de la personne en charge du paquetage pour
belaran@999 1194 la distribution.</para>
belaran@999 1195
belaran@999 1196 <para id="x_3">Pour rester simple, je me concentrerai sur
belaran@999 1197 l'installation de Mercurial en ligne de commande, sous les
belaran@999 1198 distributions les plus courantes. La plupart des distributions
belaran@999 1199 fournissent des gestionnaires graphiques de paquetage qui vous
belaran@999 1200 permettront d'installer Mercurial en quelques clicks. Le paquetage
belaran@999 1201 devrait se nommer <literal moreinfo="none">mercurial</literal>.</para>
belaran@999 1202
belaran@999 1203 <itemizedlist>
belaran@999 1204 <listitem><para id="x_4">Ubuntu et Debian:</para>
belaran@999 1205 <programlisting format="linespecific">apt-get install mercurial</programlisting></listitem>
belaran@999 1206 <listitem><para id="x_5">Fedora:</para>
belaran@999 1207 <programlisting format="linespecific">yum install mercurial</programlisting></listitem>
belaran@999 1208 <listitem><para id="x_6">Gentoo:</para>
belaran@999 1209 <programlisting format="linespecific">emerge mercurial</programlisting></listitem>
belaran@999 1210 <listitem><para id="x_715">OpenSUSE:</para>
belaran@999 1211 <programlisting format="linespecific">zypper install
belaran@999 1212 mercurial</programlisting></listitem>
belaran@999 1213 </itemizedlist>
belaran@999 1214
belaran@999 1215 </sect2>
belaran@999 1216 <sect2>
belaran@999 1217 <title>Solaris</title>
belaran@999 1218
belaran@999 1219 <para id="x_09">SunFreeWare, à <ulink url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>,
belaran@999 1220 fournit des paquets précompilés pour Mercurial.</para>
belaran@999 1221 </sect2>
belaran@999 1222 </sect1>
belaran@999 1223
belaran@999 1224 <sect1>
belaran@999 1225 <title>Commencer à utiliser Mercurial</title>
belaran@999 1226
belaran@999 1227 <para id="x_e">Pour commencer, nous utiliserons la commande <command role="hg-cmd" moreinfo="none">hg version</command> pour vérifier si Mercurial est
belaran@999 1228 installé proprement. Les informations affichées sur la version ne sont
belaran@999 1229 pas réellement importantes en soit, c'est surtout de savoir si elles
belaran@999 1230 s'affichent qui nous intéresse.</para>
belaran@999 1231
belaran@999 1232 <!-- BEGIN tour.version -->
belaran@999 1233 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg version</userinput>
belaran@999 1234 Mercurial Distributed SCM (version 1.2.1)
belaran@999 1235
belaran@999 1236 Copyright (C) 2005-2009 Matt Mackall &lt;mpm@selenic.com&gt; and others
belaran@999 1237 This is free software; see the source for copying conditions. There is NO
belaran@999 1238 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
belaran@999 1239 </screen>
belaran@999 1240 <!-- END tour.version -->
belaran@999 1241
belaran@999 1242
belaran@999 1243 <sect2>
belaran@999 1244 <title>L'aide intégrée</title>
belaran@999 1245
belaran@999 1246 <para id="x_f">Mercurial fournit un système d'aide intégré, ce qui est
belaran@999 1247 inestimable quand vous vous retrouvez coincé à essayer de vous
belaran@999 1248 rappeler comment lancer une commande. Si vous êtes bloqué, exécutez
belaran@999 1249 simplement <command role="hg-cmd" moreinfo="none">hg help</command>; elle affichera
belaran@999 1250 une brève liste des commandes, avec une description pour chacune. Si
belaran@999 1251 vous demandez de l'aide sur une commande spécifique (voir
belaran@999 1252 ci-dessous), elle affichera des informations plus détaillées.</para>
belaran@999 1253
belaran@999 1254 <!-- BEGIN tour.help -->
belaran@999 1255 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help init</userinput>
belaran@999 1256 hg init [-e CMD] [--remotecmd CMD] [DEST]
belaran@999 1257
belaran@999 1258 create a new repository in the given directory
belaran@999 1259
belaran@999 1260 Initialize a new repository in the given directory. If the given
belaran@999 1261 directory does not exist, it is created.
belaran@999 1262
belaran@999 1263 If no directory is given, the current directory is used.
belaran@999 1264
belaran@999 1265 It is possible to specify an ssh:// URL as the destination.
belaran@999 1266 See 'hg help urls' for more information.
belaran@999 1267
belaran@999 1268 options:
belaran@999 1269
belaran@999 1270 -e --ssh specify ssh command to use
belaran@999 1271 --remotecmd specify hg command to run on the remote side
belaran@999 1272
belaran@999 1273 use "hg -v help init" to show global options
belaran@999 1274 </screen>
belaran@999 1275 <!-- END tour.help -->
belaran@999 1276
belaran@999 1277
belaran@999 1278 <para id="x_10">Pour un niveau d'informations encore plus détaillé
belaran@999 1279 (ce dont vous aurez rarement besoin), exécuter <command role="hg-cmd" moreinfo="none">hg
belaran@999 1280 help <option role="hg-opt-global">-v</option></command>. L'option
belaran@999 1281 <option role="hg-opt-global">-v</option> est l'abréviation de
belaran@999 1282 <option role="hg-opt-global">--verbose</option>, et indique à Mercurial
belaran@999 1283 d'ficher plus d'informations que d'habitude.</para>
belaran@999 1284
belaran@999 1285 </sect2>
belaran@999 1286 </sect1>
belaran@999 1287 <sect1>
belaran@999 1288 <title>Travailler avec un dépôt</title>
belaran@999 1289
belaran@999 1290 <para id="x_11">Avec Mercurial, tout se déroule au sein du
belaran@999 1291 <emphasis>dépôt</emphasis>. Le dépôt d'un projet contient tous
belaran@999 1292 les fichiers qui <quote>appartiennent</quote> au projet.</para>
belaran@999 1293
belaran@999 1294 <para id="x_12">Il n'y a rien de particulièrement magique au sujet de
belaran@999 1295 ce dépôt, c'est simplement une arborescence sur votre système de fichiers
belaran@999 1296 que Mercurial traite de manière spéciale. Vous pouvez renommer ou effacer
belaran@999 1297 ce répertoire à n'impporte quel moment, en utilisant la ligne de commande
belaran@999 1298 ou votre explorateur de fichiers.</para>
belaran@999 1299
belaran@999 1300 <sect2>
belaran@999 1301 <title>Faire une copie locale de votre dépôt</title>
belaran@999 1302
belaran@999 1303 <para id="x_13"><emphasis>Copier</emphasis> un dépôt est juste un
belaran@999 1304 peu spécial. Bien que vous puissiez utiliser une commande habituelle de
belaran@999 1305 copie pour copier votre dépôt, il vaut mieux utiliser une commande fournie par
belaran@999 1306 Mercurial. Cette commande est appelée <command role="hg-cmd" moreinfo="none">hg clone</command>,
belaran@999 1307 car elle crée une copie identique à un dépôt existant.</para>
belaran@999 1308
belaran@999 1309 <!-- BEGIN tour.clone -->
belaran@999 1310 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone http://hg.serpentine.com/tutorial/hello</userinput>
belaran@999 1311 destination directory: hello
belaran@999 1312 requesting all changes
belaran@999 1313 adding changesets
belaran@999 1314 adding manifests
belaran@999 1315 adding file changes
belaran@999 1316 added 5 changesets with 5 changes to 2 files
belaran@999 1317 updating working directory
belaran@999 1318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 1319 </screen>
belaran@999 1320 <!-- END tour.clone -->
belaran@999 1321
belaran@999 1322
belaran@999 1323 <para id="x_67c">Un avantage de la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 1324 clone</command> est que, comme nous l'avons vu ci dessus, elle nous
belaran@999 1325 permet de faire de cloner les dépôts à travers le réseau. Un autre
belaran@999 1326 est qu'elle se rappelle d'où a été cloné un dépôt, ce qui est utile
belaran@999 1327 quand on veut mettre à jour le clone.</para>
belaran@999 1328
belaran@999 1329 <para id="x_14">Si votre opération de clonage réussit, vous devriez maintenant
belaran@999 1330 avoir un répertoire local appelé <filename class="directory" moreinfo="none">hello</filename>.
belaran@999 1331 Ce répertoire contiendra quelques fichiers.</para>
belaran@999 1332
belaran@999 1333 <!-- BEGIN tour.ls -->
belaran@999 1334 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput>
belaran@999 1335 total 4
belaran@999 1336 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:05 hello
belaran@999 1337 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls hello</userinput>
belaran@999 1338 Makefile hello.c
belaran@999 1339 </screen>
belaran@999 1340 <!-- END tour.ls -->
belaran@999 1341
belaran@999 1342
belaran@999 1343 <para id="x_15">Ces fichiers ont le même contenu et historique dans votre dépôt
belaran@999 1344 qu'ils ont dans le dépôt que vous avez cloné.</para>
belaran@999 1345
belaran@999 1346 <para id="x_16">Chaque dépôt Mercurial est complet, autonome et
belaran@999 1347 indépendant. Il contient sa propre copie privée des fichiers du
belaran@999 1348 projet et de leur historique. Le clone d'un dépôt se souvient de la
belaran@999 1349 localisation du dépôt à partir duquel il a été clôné, mais il ne
belaran@999 1350 communique pas avec ce dernier, ou un autre, à moins que vous ne lui
belaran@999 1351 demandiez.</para>
belaran@999 1352
belaran@999 1353 <para id="x_17">Ce que tout ceci signifie pour le moment est que nous
belaran@999 1354 sommes libres d'expérimenter avec ce dépôt, confiants dans le fait
belaran@999 1355 qu'il s'agit d'un <quote>bac à sable</quote> qui n'affectera personne
belaran@999 1356 d'autre.</para>
belaran@999 1357
belaran@999 1358 </sect2>
belaran@999 1359 <sect2>
belaran@999 1360 <title>Quel est le contenu d'un dépôt ?</title>
belaran@999 1361
belaran@999 1362 <para id="x_18">Prêtons plus attention un instant au contenu d'un dépôt.
belaran@999 1363 Nous voyons qu'il contient un répertoire nommé <filename class="directory" moreinfo="none">.hg
belaran@999 1364 </filename>. C'est ici que Mercurial conserve toutes ses
belaran@999 1365 métadonnées.</para>
belaran@999 1366
belaran@999 1367 <!-- BEGIN tour.ls-a -->
belaran@999 1368 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello</userinput>
belaran@999 1369 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -a</userinput>
belaran@999 1370 . .. .hg Makefile hello.c
belaran@999 1371 </screen>
belaran@999 1372 <!-- END tour.ls-a -->
belaran@999 1373
belaran@999 1374
belaran@999 1375 <para id="x_19">Le contenu du répertoire <filename class="directory" moreinfo="none">.hg
belaran@999 1376 </filename> et ses sous répertoires sont les seuls propres à Mercurial.
belaran@999 1377 Tous les autres fichiers et répertoires dans le dépôt sont à vous, et
belaran@999 1378 vous pouvez en faire ce que vous voulez.</para>
belaran@999 1379
belaran@999 1380 <para id="x_1a">Pour introduire un peu de terminologie, le répertoire
belaran@999 1381 <filename class="directory" moreinfo="none">.hg</filename> est un <quote>vrai</quote>
belaran@999 1382 dépôt, et tous les fichiers et les répertoires qui coexistent avec lui,
belaran@999 1383 sont désignés sous le nom <emphasis>espace de travail</emphasis>. Une
belaran@999 1384 manière facile de se rappeler cette distinction est de retenir que le
belaran@999 1385 <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis>
belaran@999 1386 de votre projet, alors que l'<emphasis>espace de travail</emphasis>
belaran@999 1387 contient un "<emphasis>snapshot</emphasis>" de votre projet à un certain
belaran@999 1388 point de son historique.</para>
belaran@999 1389
belaran@999 1390 </sect2>
belaran@999 1391 </sect1>
belaran@999 1392 <sect1>
belaran@999 1393 <title>Une promenade dans l'historique</title>
belaran@999 1394
belaran@999 1395 <para id="x_1b">Une des premières choses que vous aurez envie
belaran@999 1396 de faire avec un nouveau dépôt, sera de comprendre son historique.
belaran@999 1397 La commande <command role="hg-cmd" moreinfo="none">hg log</command> vous donne une
belaran@999 1398 vue de l'historique.</para>
belaran@999 1399
belaran@999 1400 <!-- BEGIN tour.log -->
belaran@999 1401 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput>
belaran@999 1402 changeset: 4:2278160e78d4
belaran@999 1403 tag: tip
belaran@999 1404 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1405 date: Sat Aug 16 22:16:53 2008 +0200
belaran@999 1406 summary: Trim comments.
belaran@999 1407
belaran@999 1408 changeset: 3:0272e0d5a517
belaran@999 1409 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1410 date: Sat Aug 16 22:08:02 2008 +0200
belaran@999 1411 summary: Get make to generate the final binary from a .o file.
belaran@999 1412
belaran@999 1413 changeset: 2:fef857204a0c
belaran@999 1414 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1415 date: Sat Aug 16 22:05:04 2008 +0200
belaran@999 1416 summary: Introduce a typo into hello.c.
belaran@999 1417
belaran@999 1418 changeset: 1:82e55d328c8c
belaran@999 1419 user: mpm@selenic.com
belaran@999 1420 date: Fri Aug 26 01:21:28 2005 -0700
belaran@999 1421 summary: Create a makefile
belaran@999 1422
belaran@999 1423 changeset: 0:0a04b987be5a
belaran@999 1424 user: mpm@selenic.com
belaran@999 1425 date: Fri Aug 26 01:20:50 2005 -0700
belaran@999 1426 summary: Create a standard "hello, world" program
belaran@999 1427
belaran@999 1428 </screen>
belaran@999 1429 <!-- END tour.log -->
belaran@999 1430
belaran@999 1431
belaran@999 1432 <para id="x_1c">Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque
belaran@999 1433 révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous
belaran@999 1434 appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce
belaran@999 1435 qu'il contient un ensemble de modifications sur plusieurs fichiers.</para>
belaran@999 1436
belaran@999 1437 <para id="x_1d">La commande <command role="hg-cmd" moreinfo="none">hg log</command> affiche
belaran@999 1438 ainsi ces informations :</para>
belaran@999 1439
belaran@999 1440 <itemizedlist>
belaran@999 1441 <listitem><para id="x_1e"><literal moreinfo="none">changeset</literal> : Ce champ contient
belaran@999 1442 un nombre, séparé par deux points (:), d'une chaine hexadécimale. Il
belaran@999 1443 s'agit en fait d'<emphasis>identifiants</emphasis> d'un changeset. Il y a
belaran@999 1444 deux identifiants car le numéro de la révision est plus court et plus à
belaran@999 1445 facile à saisir qu'une séquence hexadécimale.</para>
belaran@999 1446 </listitem>
belaran@999 1447 <listitem><para id="x_1f"><literal moreinfo="none">user</literal> : L'identité de la personne
belaran@999 1448 qui a créée ce %%% laisser le terme anglais car il sera affiché
belaran@999 1449 changeset. C'est un champ libre de forme, mais la plupart du
belaran@999 1450 temps il contient le nom et l'email de la personne.</para>
belaran@999 1451 </listitem>
belaran@999 1452 <listitem><para id="x_20"><literal moreinfo="none">date</literal> : La date et l'heure à
belaran@999 1453 laquelle le \textit{changeset} a été créé, ainsi que le fuseau horaire dans
belaran@999 1454 lequelle il a été créé. (La date et l'heure sont locales à ce
belaran@999 1455 \textit{fuseau}, elles indiquent donc quelle date et heure il était
belaran@999 1456 pour la personne qui a créé ce changeset.</para>
belaran@999 1457 </listitem>
belaran@999 1458 <listitem><para id="x_21"><literal moreinfo="none">résumé</literal>: La première ligne du
belaran@999 1459 message que le créateur a associé à son changeset pour le décrire.</para>
belaran@999 1460 </listitem>
belaran@999 1461 <listitem><para id="x_67d">Certains changesets, comme le premier de la
belaran@999 1462 liste ci-dessus ont un champ <literal moreinfo="none">tag</literal>. Le tag est une autre
belaran@999 1463 façon d'identifier un changeset en lui donnant un nom simple à retenir.
belaran@999 1464 (Le tag nommé <literal moreinfo="none">tip</literal> est spécial : il fait toujours
belaran@999 1465 référence aux derniers changements dans le dépôt.)</para></listitem>
belaran@999 1466 </itemizedlist>
belaran@999 1467
belaran@999 1468 <para id="x_22">Par défaut, la commande <command role="hg-cmd" moreinfo="none">hg log</command>
belaran@999 1469 n'affiche qu'un résumé, il manque beaucoup de détails.</para>
belaran@999 1470
belaran@999 1471 <para id="x_23">La figure <xref linkend="fig:tour-basic:history"/> fournit une
belaran@999 1472 représentation graphique de l'historique du dépôt <filename class="directory" moreinfo="none">hello
belaran@999 1473 </filename>, pour rendre plus facile de voir dans quelle direction
belaran@999 1474 l'historique se <quote>déroule</quote>. Nous reviendrons régulièrement
belaran@999 1475 sur cette représentation dans ce chapitre et ceux qui suivent.</para>
belaran@999 1476
belaran@999 1477
belaran@999 1478 <figure id="fig:tour-basic:history" float="0">
belaran@999 1479 <title>Graphical history of the <filename class="directory" moreinfo="none">hello</filename> repository</title>
belaran@999 1480 <mediaobject>
belaran@999 1481 <imageobject><imagedata fileref="figs/tour-history.png"/></imageobject>
belaran@999 1482 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 1483 </mediaobject>
belaran@999 1484 </figure>
belaran@999 1485
belaran@999 1486
belaran@999 1487 <sect2>
belaran@999 1488 <title>Changesets, révisions, et collaboration</title>
belaran@999 1489
belaran@999 1490 <para id="x_25">Comme l'anglais est réputé pour être un langage maladroit,
belaran@999 1491 et que l'informatique est la source de bien des erreurs de terminologie
belaran@999 1492 (pourquoi utiliser un seul terme quand quatre feront l'affaire ?), la
belaran@999 1493 gestion de version a une variété de mots et de phrases qui veulent dire
belaran@999 1494 la même chose. Si vous discutez d'historique de Mercurial avec d'autres
belaran@999 1495 personnes, vous constaterez que souvent, le mot <quote>changeset</quote>
belaran@999 1496 est contracté simplement en <quote>change</quote> ou (à l'écrit)
belaran@999 1497 <quote>cset</quote>, et même parfois un changeset
belaran@999 1498 <quote>révision</quote>, abrégé en <quote>rev</quote>.</para>
belaran@999 1499
belaran@999 1500 <para id="x_26">Bien que le <emphasis>mot</emphasis> que vous utilisez pour
belaran@999 1501 désigner le concept de changeset importe peu, l'<emphasis>identifiant</emphasis>
belaran@999 1502 que vous utilisez pour désigner un <emphasis>changeset</emphasis> spécifique
belaran@999 1503 a une grande importance. Rappelez vous que le champ changeset affiché par la
belaran@999 1504 commande <command role="hg-cmd" moreinfo="none">hg log</command> identifie un changeset à
belaran@999 1505 la fois avec un numéro de révision et une séquence hexadécimale.</para>
belaran@999 1506
belaran@999 1507 <itemizedlist>
belaran@999 1508 <listitem><para id="x_27">Le numéro de révision est <emphasis>seulement
belaran@999 1509 valable dans ce dépôt</emphasis>,</para></listitem>
belaran@999 1510 <listitem><para id="x_28">La séquence hexadécimale est un
belaran@999 1511 <emphasis>identifiant permanent, et invariant</emphasis> qui
belaran@999 1512 pourra toujours être associé au changeset exact de <emphasis>chaque</emphasis>
belaran@999 1513 copie de votre dépôt.</para></listitem></itemizedlist>
belaran@999 1514
belaran@999 1515 <para id="x_29">La distinction est importante. Si vous envoyez un email
belaran@999 1516 à quelqu'un en parlant de la <quote>révision 33</quote>, il est très
belaran@999 1517 probable que sa révision 33 <emphasis>ne sera pas la même</emphasis>
belaran@999 1518 que la votre. La raison de ceci est que le numéro de révision dépend
belaran@999 1519 de l'ordre dans lequel les modifications sont arrivées dans le dépôt,
belaran@999 1520 et il n'y a aucune garantie que les mêmes changements soient arrivés
belaran@999 1521 dans le même ordre dans différents dépôts. Trois modifications
belaran@999 1522 <literal moreinfo="none">a,b,c</literal> peuvent aisément apparaitre dans un dépôt
belaran@999 1523 comme <literal moreinfo="none">0,1,2</literal>, et dans un autre comme <literal moreinfo="none">0,2,1
belaran@999 1524 </literal>.</para>
belaran@999 1525
belaran@999 1526 <para id="x_2a">Mercurial utilise les numéros de révision uniquement comme des raccourcis
belaran@999 1527 pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un,
belaran@999 1528 ou identifer un \textit{changeset} pour une quelconque raison (par exemple,
belaran@999 1529 un rapport de \textit{bug}), utilisez la séquence hexadécimale.</para>
belaran@999 1530
belaran@999 1531 </sect2>
belaran@999 1532 <sect2>
belaran@999 1533 <title>Afficher une révision spécifique</title>
belaran@999 1534
belaran@999 1535 <para id="x_2b">Pour réduire la sortie de <command role="hg-cmd" moreinfo="none">hg log
belaran@999 1536 </command> à une seule révision, utilisez l'option <option role="hg-opt-log">-r
belaran@999 1537 </option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser
belaran@999 1538 le numéro de révision ou la séquence hexadécimale comme identifiant, et
belaran@999 1539 demander autant de révisions que vous le souhaitez.</para>
belaran@999 1540
belaran@999 1541 <!-- BEGIN tour.log-r -->
belaran@999 1542 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 3</userinput>
belaran@999 1543 changeset: 3:0272e0d5a517
belaran@999 1544 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1545 date: Sat Aug 16 22:08:02 2008 +0200
belaran@999 1546 summary: Get make to generate the final binary from a .o file.
belaran@999 1547
belaran@999 1548 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 0272e0d5a517</userinput>
belaran@999 1549 changeset: 3:0272e0d5a517
belaran@999 1550 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1551 date: Sat Aug 16 22:08:02 2008 +0200
belaran@999 1552 summary: Get make to generate the final binary from a .o file.
belaran@999 1553
belaran@999 1554 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 1 -r 4</userinput>
belaran@999 1555 changeset: 1:82e55d328c8c
belaran@999 1556 user: mpm@selenic.com
belaran@999 1557 date: Fri Aug 26 01:21:28 2005 -0700
belaran@999 1558 summary: Create a makefile
belaran@999 1559
belaran@999 1560 changeset: 4:2278160e78d4
belaran@999 1561 tag: tip
belaran@999 1562 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1563 date: Sat Aug 16 22:16:53 2008 +0200
belaran@999 1564 summary: Trim comments.
belaran@999 1565
belaran@999 1566 </screen>
belaran@999 1567 <!-- END tour.log-r -->
belaran@999 1568
belaran@999 1569
belaran@999 1570 <para id="x_2c">Si vous voulez voir l'historique de plusieurs révisions
belaran@999 1571 sans avoir à les énumérer, vous pouvez utiliser la <emphasis>intervalle
belaran@999 1572 de numérotation</emphasis> qui vous permet d'exprimer l'idée <quote>je
belaran@999 1573 veux toutes les révisions entre $a$ et $b$, inclus</quote></para>
belaran@999 1574
belaran@999 1575 <!-- BEGIN tour.log.range -->
belaran@999 1576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 2:4</userinput>
belaran@999 1577 changeset: 2:fef857204a0c
belaran@999 1578 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1579 date: Sat Aug 16 22:05:04 2008 +0200
belaran@999 1580 summary: Introduce a typo into hello.c.
belaran@999 1581
belaran@999 1582 changeset: 3:0272e0d5a517
belaran@999 1583 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1584 date: Sat Aug 16 22:08:02 2008 +0200
belaran@999 1585 summary: Get make to generate the final binary from a .o file.
belaran@999 1586
belaran@999 1587 changeset: 4:2278160e78d4
belaran@999 1588 tag: tip
belaran@999 1589 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1590 date: Sat Aug 16 22:16:53 2008 +0200
belaran@999 1591 summary: Trim comments.
belaran@999 1592
belaran@999 1593 </screen>
belaran@999 1594 <!-- END tour.log.range -->
belaran@999 1595
belaran@999 1596
belaran@999 1597 <para id="x_2d">Mercurial respecte aussi l'ordre dans lequel vous spécifiez
belaran@999 1598 les révisions, ainsi <command role="hg-cmd" moreinfo="none">hg log -r 2:4</command>
belaran@999 1599 affichera <literal moreinfo="none">2,3,4</literal> alors que <command role="hg-cmd" moreinfo="none">hg
belaran@999 1600 log -r 4:2</command> affichera <literal moreinfo="none">4,3,2</literal>.</para>
belaran@999 1601
belaran@999 1602 </sect2>
belaran@999 1603 <sect2>
belaran@999 1604 <title>Informations détaillées</title>
belaran@999 1605
belaran@999 1606 <para id="x_2e">Le résumé affiché par <command role="hg-cmd" moreinfo="none">hg log</command>
belaran@999 1607 est suffisant si vous savez déjà ce que vous cherchez. En
belaran@999 1608 revanche, vous aurez probablement besoin de voir une description
belaran@999 1609 complète du changement, ou une liste des fichiers modifiés si vous
belaran@999 1610 cherchez à déterminer qu'un changeset est bien celui que vous
belaran@999 1611 recherchez. L'option \hgopt{-v} de la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 1612 log</command> (ou <option role="hp-opt-global">--verbose</option>) vous
belaran@999 1613 donne ces informations supplémentaires.</para>
belaran@999 1614
belaran@999 1615 <!-- BEGIN tour.log-v -->
belaran@999 1616 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -r 3</userinput>
belaran@999 1617 changeset: 3:0272e0d5a517
belaran@999 1618 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1619 date: Sat Aug 16 22:08:02 2008 +0200
belaran@999 1620 files: Makefile
belaran@999 1621 description:
belaran@999 1622 Get make to generate the final binary from a .o file.
belaran@999 1623
belaran@999 1624
belaran@999 1625 </screen>
belaran@999 1626 <!-- END tour.log-v -->
belaran@999 1627
belaran@999 1628
belaran@999 1629 <para id="x_2f">Si vous voulez voir à la fois la description
belaran@999 1630 et le contenu d'une modification, ajouter l'option <option role="hg-opt-log">-p</option> (ou <option role="hg-opt-log">
belaran@999 1631 --patch</option>). Ceci affiche le contenu d'une modification
belaran@999 1632 comme un <emphasis>diff unifié</emphasis>
belaran@999 1633 <!-- \footnote{NdT: \textit{unified diff}} -->
belaran@999 1634 (si vous n'avez jamais vu de diff unifié avant, consultez la
belaran@999 1635 section <xref linkend="sec:mq:patch"/> pour un rapide
belaran@999 1636 survol).</para>
belaran@999 1637
belaran@999 1638 <!-- BEGIN tour.log-vp -->
belaran@999 1639 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -p -r 2</userinput>
belaran@999 1640 changeset: 2:fef857204a0c
belaran@999 1641 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 1642 date: Sat Aug 16 22:05:04 2008 +0200
belaran@999 1643 files: hello.c
belaran@999 1644 description:
belaran@999 1645 Introduce a typo into hello.c.
belaran@999 1646
belaran@999 1647
belaran@999 1648 diff -r 82e55d328c8c -r fef857204a0c hello.c
belaran@999 1649 --- a/hello.c Fri Aug 26 01:21:28 2005 -0700
belaran@999 1650 +++ b/hello.c Sat Aug 16 22:05:04 2008 +0200
belaran@999 1651 @@ -11,6 +11,6 @@
belaran@999 1652
belaran@999 1653 int main(int argc, char **argv)
belaran@999 1654 {
belaran@999 1655 - printf("hello, world!\n");
belaran@999 1656 + printf("hello, world!\");
belaran@999 1657 return 0;
belaran@999 1658 }
belaran@999 1659
belaran@999 1660 </screen>
belaran@999 1661 <!-- END tour.log-vp -->
belaran@999 1662
belaran@999 1663
belaran@999 1664 <para id="x_67e">L'option <option role="hg-opt-log">-p</option> est
belaran@999 1665 incroyablement utile, il est donc important dans s'en rappeller.</para>
belaran@999 1666
belaran@999 1667 </sect2>
belaran@999 1668 </sect1>
belaran@999 1669 <sect1>
belaran@999 1670 <title>Tout sur les options de commandes</title>
belaran@999 1671
belaran@999 1672 <para id="x_30">Avant d'aller plus loin sur le fonctionnement
belaran@999 1673 des commandes de Mercurial, étudions un moment comment elles
belaran@999 1674 fonctionnent de manière générale. Vous trouverez ça probablement
belaran@999 1675 utile pour la suite de notre parcours.</para>
belaran@999 1676
belaran@999 1677 <para id="x_31">Mercurial utilise une approche directe et cohérente
belaran@999 1678 pour interpréter les options que vous passez aux commandes. Il suit une
belaran@999 1679 convention commune à la plupart des systèmes Unix et Linux modernes.</para>
belaran@999 1680
belaran@999 1681 <itemizedlist>
belaran@999 1682 <listitem><para id="x_32">Chaque option a un nom complet. Par exemple,
belaran@999 1683 comme nous l'avons déjà vu, la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 1684 log</command> accepte l'option <option role="hg-opt-log">--rev
belaran@999 1685 </option>.</para>
belaran@999 1686 </listitem>
belaran@999 1687 <listitem><para id="x_33">La plupart des options disposent de
belaran@999 1688 noms abrégés. Aussi, au lieu d'utiliser <option role="hg-opt-log">--rev
belaran@999 1689 </option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>.
belaran@999 1690 (Les options qui n'ont pas de noms abrégés sont généralement
belaran@999 1691 rarement utilisées).</para>
belaran@999 1692 </listitem>
belaran@999 1693 <listitem><para id="x_34">Les noms complets commencent par deux
belaran@999 1694 tirets (i.e. <option role="hg-opt-log">--rev</option>),
belaran@999 1695 alors que les options courtes commencent avec un seul (i.e.
belaran@999 1696 <option role="hg-opt-log">-r</option>).</para>
belaran@999 1697 </listitem>
belaran@999 1698 <listitem><para id="x_35">Les noms des options sont cohérents
belaran@999 1699 entre les commandes. Par exemple, chaque commande qui accepte
belaran@999 1700 un changeset ID ou un numéro de révision accepte aussi <option role="hg-opt-log">-r</option> et <option role="hg-opt-log">--rev
belaran@999 1701 </option> comme arguments.</para>
belaran@999 1702 </listitem>
belaran@999 1703 </itemizedlist>
belaran@999 1704
belaran@999 1705 <para id="x_36">Dans les exemples de ce livre, j'utilise les noms abrégés
belaran@999 1706 plutôt que les noms complets. Ceci est une préférence personnelle, pas
belaran@999 1707 une recommandation.</para>
belaran@999 1708
belaran@999 1709 <para id="x_37">La plupart des commandes qui affichent une quelconque sortie
belaran@999 1710 à l'écran, afficheront davantage avec l'option <option role="hg-opt-global">
belaran@999 1711 -v</option> (ou <option role="hg-opt-global">--verbose</option>), et
belaran@999 1712 moins avec l'option <option role="hg-opt-global">-q</option> (ou
belaran@999 1713 <option role="hg-opt-global">--quiet</option>).</para>
belaran@999 1714
belaran@999 1715 <note>
belaran@999 1716 <title>Option naming consistency</title>
belaran@999 1717
belaran@999 1718 <para id="x_680">Presque toujours, les commandes de Mercurial utilisent
belaran@999 1719 des noms d'options cohérentes pour référer à des concepts identiques.
belaran@999 1720 Par exemple, si une commande concerne les changesets, vous les
belaran@999 1721 identifierez toujours avec l'option <option role="hg-opt-log">-r</option>.
belaran@999 1722 Cette utilisation cohérente des noms d'options permet de mémoriser plus
belaran@999 1723 facilement quelles options accepte une commande.</para>
belaran@999 1724 </note>
belaran@999 1725
belaran@999 1726
belaran@999 1727 </sect1>
belaran@999 1728 <sect1>
belaran@999 1729 <title>Faire et vérifier des modifications</title>
belaran@999 1730
belaran@999 1731 <para id="x_38">Maintenant que nous avons une bonne idée des
belaran@999 1732 commandes pour consulter l'historique de Mercurial, regardons
belaran@999 1733 comment faire des modifications et les examiner.</para>
belaran@999 1734
belaran@999 1735 <para id="x_39">La première chose que nous allons faire c'est isoler notre
belaran@999 1736 expérience dans un dépôt à part. Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg clone</command>, mais nous n'avons pas besoin de faire
belaran@999 1737 une copie de dépôt distant. Comme nous avons déjà une copie locale, nous
belaran@999 1738 pouvons juste faire un clone de celle-ci à la place. C'est beaucoup plus
belaran@999 1739 rapide que de faire une copie à travers le réseau, et un dépôt cloné
belaran@999 1740 localement prend également moins d'espace disque<footnote>
belaran@999 1741 <para id="x_681">L'économie d'espace disque apparait clairement quand les
belaran@999 1742 dépôts source et destination sont sur le même système de fichier, où, dans
belaran@999 1743 ce cas, Mercurial utilisera des liens physiques pour effectuer des partages
belaran@999 1744 copie-lors-des-écritures de ses métadonnées internes. Si cette explication
belaran@999 1745 ne signifie rien pour vous, ne vous inquietez pas : tout ceci se passe de
belaran@999 1746 manière transparente et automatiquement. Vous n'avez pas du tout besoin de
belaran@999 1747 comprendre ceci.</para></footnote>.</para>
belaran@999 1748
belaran@999 1749 <!-- BEGIN tour.reclone -->
belaran@999 1750 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 1751 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-hello</userinput>
belaran@999 1752 updating working directory
belaran@999 1753 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 1754 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput>
belaran@999 1755 </screen>
belaran@999 1756 <!-- END tour.reclone -->
belaran@999 1757
belaran@999 1758
belaran@999 1759 <para id="x_3a">On notera au passage qu'il est souvent considéré comme
belaran@999 1760 une bonne pratique de conserver une copie <quote>immaculée</quote>
belaran@999 1761 du dépôt distant, à partir de laquelle vous pourrez faire des
belaran@999 1762 copies locales temporaires pour créer des <quote>bacs à sable</quote>
belaran@999 1763 pour chaque tâche sur laquelle vous souhaitez travailler. Ceci
belaran@999 1764 vous permet de travailler sur plusieurs choses en parallèle,
belaran@999 1765 chacune isolée les unes des autres en attendant que ces tâches
belaran@999 1766 soient finies et que vous soyez prêt à les réintégrer. Parce
belaran@999 1767 que les copies locales sont peu coûteuses, il est très rapide
belaran@999 1768 de créer ou détruire des dépôts dès que vous n'en avez plus
belaran@999 1769 besoin.</para>
belaran@999 1770
belaran@999 1771 <para id="x_3b">Dans notre dépôt <filename class="directory" moreinfo="none">my-hello</filename>, nous avons un fichier
belaran@999 1772 <filename moreinfo="none">hello.c</filename> qui contient le classique <quote>hello,
belaran@999 1773 world</quote>.</para>
belaran@999 1774
belaran@999 1775 <!-- BEGIN tour.cat1 -->
belaran@999 1776 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
belaran@999 1777 /*
belaran@999 1778 * Placed in the public domain by Bryan O'Sullivan. This program is
belaran@999 1779 * not covered by patents in the United States or other countries.
belaran@999 1780 */
belaran@999 1781
belaran@999 1782 #include &lt;stdio.h&gt;
belaran@999 1783
belaran@999 1784 int main(int argc, char **argv)
belaran@999 1785 {
belaran@999 1786 printf("hello, world!\");
belaran@999 1787 return 0;
belaran@999 1788 }
belaran@999 1789 </screen>
belaran@999 1790 <!-- END tour.cat1 -->
belaran@999 1791
belaran@999 1792
belaran@999 1793 <para id="x_682">Editons ce fichier pour qu'il affiche une autre ligne
belaran@999 1794 sur la sortie standard.</para>
belaran@999 1795
belaran@999 1796 <!-- BEGIN tour.cat2 -->
belaran@999 1797 <screen format="linespecific"># ... edit edit edit ...
belaran@999 1798 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
belaran@999 1799 /*
belaran@999 1800 * Placed in the public domain by Bryan O'Sullivan. This program is
belaran@999 1801 * not covered by patents in the United States or other countries.
belaran@999 1802 */
belaran@999 1803
belaran@999 1804 #include &lt;stdio.h&gt;
belaran@999 1805
belaran@999 1806 int main(int argc, char **argv)
belaran@999 1807 {
belaran@999 1808 printf("hello, world!\");
belaran@999 1809 printf("hello again!\n");
belaran@999 1810 return 0;
belaran@999 1811 }
belaran@999 1812 </screen>
belaran@999 1813 <!-- END tour.cat2 -->
belaran@999 1814
belaran@999 1815
belaran@999 1816 <para id="x_3c">La commande Mercurial <command role="hg-cmd" moreinfo="none">hg
belaran@999 1817 status</command> nous dira ce que Mercurial sait des fichiers du
belaran@999 1818 dépôts.</para>
belaran@999 1819
belaran@999 1820 <!-- BEGIN tour.status -->
belaran@999 1821 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput>
belaran@999 1822 Makefile hello.c
belaran@999 1823 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 1824 M hello.c
belaran@999 1825 </screen>
belaran@999 1826 <!-- END tour.status -->
belaran@999 1827
belaran@999 1828
belaran@999 1829 <para id="x_3d">La commande <command role="hg-cmd" moreinfo="none">hg status</command>
belaran@999 1830 n'affichera pas le contenu des fichiers, mais une ligne commençant par
belaran@999 1831 <quote><literal moreinfo="none">M</literal></quote> pour <filename moreinfo="none">hello.c</filename>.
belaran@999 1832 A moins que vous lui demandiez, la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 1833 status</command> n'affichera aucune information sur les fichiers que
belaran@999 1834 vous n'avez pas modifiés.</para>
belaran@999 1835
belaran@999 1836 <para id="x_3e">Le <quote><literal moreinfo="none">M</literal></quote> indique que
belaran@999 1837 Mercurial a remarqué que nous avons modifié le fichier
belaran@999 1838 <filename moreinfo="none">hello.c</filename>. Nous n'avons pas besoin
belaran@999 1839 <emphasis>d'informer</emphasis> Mercurial que nous allons modifier un
belaran@999 1840 fichier avant de commencer à le faire, ou que nous avons modifié un
belaran@999 1841 fichier après avoir commencé à le faire, il est capable de découvrir ça
belaran@999 1842 tout seul. </para>
belaran@999 1843
belaran@999 1844 <para id="x_3f">C'est déjà pratique de savoir que nous avons modifié le
belaran@999 1845 fichier <filename moreinfo="none">hello.c</filename>, mais nous préférerions savoir
belaran@999 1846 exactement <emphasis>ce que</emphasis> nous avons changé. Pour ceci, nous
belaran@999 1847 utilisons la commande <command role="hg-cmd" moreinfo="none">hg diff</command>.</para>
belaran@999 1848
belaran@999 1849 <!-- BEGIN tour.diff -->
belaran@999 1850 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 1851 diff -r 2278160e78d4 hello.c
belaran@999 1852 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200
belaran@999 1853 +++ b/hello.c Sun Aug 16 14:05:26 2009 +0000
belaran@999 1854 @@ -8,5 +8,6 @@
belaran@999 1855 int main(int argc, char **argv)
belaran@999 1856 {
belaran@999 1857 printf("hello, world!\");
belaran@999 1858 + printf("hello again!\n");
belaran@999 1859 return 0;
belaran@999 1860 }
belaran@999 1861 </screen>
belaran@999 1862 <!-- END tour.diff -->
belaran@999 1863
belaran@999 1864
belaran@999 1865 <tip>
belaran@999 1866 <title>Comprendre les patches</title>
belaran@999 1867
belaran@999 1868 <para id="x_683">Penser à jeter un oeil à <xref linkend="sec:mq:patch"/> si vous n'arrivez pas à lire la sortie
belaran@999 1869 ci-dessus.</para>
belaran@999 1870 </tip>
belaran@999 1871 </sect1>
belaran@999 1872 <sect1>
belaran@999 1873 <title>Enregister vos modifications dans une nouvelle révision</title>
belaran@999 1874
belaran@999 1875 <para id="x_40">Nous pouvons modifier des fichiers, compiler et tester
belaran@999 1876 nos modifications, et utiliser les commandes <command role="hg-cmd" moreinfo="none">hg
belaran@999 1877 status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command> pour
belaran@999 1878 voir les modifications effectuées, jusqu'à ce que nous soyons assez
belaran@999 1879 satisfaits pour décider d'enregistrer notre travail dans un
belaran@999 1880 \textit{changeset}.</para>
belaran@999 1881
belaran@999 1882 <para id="x_41">La commande <command role="hg-cmd" moreinfo="none">hg commit</command>
belaran@999 1883 vous laisse créer une nouvelle révision, nous désignerons généralement
belaran@999 1884 cette opération par <quote>faire un commit</quote> ou
belaran@999 1885 <quote>committer</quote>.</para>
belaran@999 1886
belaran@999 1887 <sect2>
belaran@999 1888 <title>Définir le nom d'utilisateur</title>
belaran@999 1889
belaran@999 1890 <para id="x_42">Quand vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg commit</command> pour la première fois, il n'est
belaran@999 1891 pas garanti qu'elle réussisse du premier coup. En effet, Mercurial
belaran@999 1892 enregistre votre nom et votre adresse avec chaque modification que
belaran@999 1893 vous effectuez, de manière à ce que vous soyez capable (ou d'autres
belaran@999 1894 le soient) de savoir qui a fait quelle modification. Mercurial essaye
belaran@999 1895 automatiquement de découvrir un nom d'utilisateur qui ait un minimum
belaran@999 1896 de sens pour effectuer l'opération de commit avec. Il va essayer
belaran@999 1897 chacune des méthodes suivantes, dans l'ordre :</para>
belaran@999 1898
belaran@999 1899 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 1900 <listitem><para id="x_43">Si vous spécifiez l'option <option role="hg-opt-commit">-u</option> avec la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, suivi d'un nom
belaran@999 1901 d'utilisateur, ceci aura toujours la priorité sur les autres
belaran@999 1902 méthodes ci dessous.</para></listitem>
belaran@999 1903 <listitem><para id="x_44">Si vous avez défini une variable
belaran@999 1904 d'environnement <envar>HGUSER</envar>, c'est cette valeur qui est
belaran@999 1905 alors utilisée.</para></listitem>
belaran@999 1906 <listitem><para id="x_45">Si vous créez un fichier nommé <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire
belaran@999 1907 \textit{home}, avec une entrée <envar role="rc-item-ui">username</envar>, c'est la valeur associée
belaran@999 1908 qui sera utilisée. Pour voir à quoi ressemble le contenu de ce
belaran@999 1909 fichier regardez la section <xref linkend="sec:tour-basic:username"/>
belaran@999 1910 ci-dessous.</para></listitem>
belaran@999 1911 <listitem><para id="x_46">Si vous avez défini une variable
belaran@999 1912 d'environnement <envar>EMAIL</envar> celle ci sera utilisée
belaran@999 1913 ensuite.</para></listitem>
belaran@999 1914 <listitem><para id="x_47">Enfin, Mercurial interrogera votre système
belaran@999 1915 pour trouver votre nom d'utilisateur local ainsi que le nom de la
belaran@999 1916 machine hôte, et il fabriquera un nom d'utilisateur à partir de
belaran@999 1917 ces données. Comme il arrive souvent que ce genre de noms soit
belaran@999 1918 totalement inutile, il vous préviendra en affichant un message
belaran@999 1919 d'avertissement.</para></listitem>
belaran@999 1920 </orderedlist>
belaran@999 1921
belaran@999 1922 <para id="x_48">Si tous ces mécanismes échouent, Mercurial n'exécutera
belaran@999 1923 pas la commande, affichant un message d'erreur. Dans ce cas, il ne
belaran@999 1924 vous laissera pas effectuer de commit tant que vous n'aurez pas
belaran@999 1925 défini un nom d'utilisateur.</para>
belaran@999 1926
belaran@999 1927 <para id="x_49">Vous devriez penser à utiliser la variable
belaran@999 1928 d'environement <envar>HGUSER</envar> et l'option <option role="hg-opt-commit">-u</option> comme moyen pour
belaran@999 1929 <emphasis>changer</emphasis> le nom d'utilisateur par défaut. Pour
belaran@999 1930 une utilisation normale, la manière la plus simple et robuste
belaran@999 1931 d'opérer est de créer un fichier <filename role="special" moreinfo="none">.hgrc</filename>, voir ci-dessous pour les détails
belaran@999 1932 à ce sujet.</para>
belaran@999 1933
belaran@999 1934 <sect3 id="sec:tour-basic:username">
belaran@999 1935 <title>Créer un fichier de configuration pour Mercurial</title>
belaran@999 1936
belaran@999 1937 <para id="x_4a">Pour définir un nom d'utilisateur, utilisez votre
belaran@999 1938 éditeur de texte favori pour créer un fichier <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire home.
belaran@999 1939 Mercurial va utiliser ce fichier pour retrouver votre
belaran@999 1940 configuration personnelle. Le contenu initial devrait
belaran@999 1941 ressembler à ceci :</para>
belaran@999 1942
belaran@999 1943 <tip>
belaran@999 1944 <title><quote>Home directory</quote> sous Windows</title>
belaran@999 1945
belaran@999 1946 <para id="x_716">Quand on parle de répertoire home, sur une version
belaran@999 1947 anglaise d'une installation de Windows, il s'agira habituellement
belaran@999 1948 d'un répertoire nommée comme votre nom dans <filename moreinfo="none">C:\Documents
belaran@999 1949 and Settings</filename>. Vous pouvez trouver de quelle répertoire
belaran@999 1950 il s'agit en lançant une fenêtre d'interpréteur de commande et en
belaran@999 1951 exécutant la commande suivante :</para>
belaran@999 1952
belaran@999 1953 <screen format="linespecific"><prompt moreinfo="none">C:\</prompt> <userinput moreinfo="none">echo
belaran@999 1954 %UserProfile</userinput></screen>
belaran@999 1955 </tip>
belaran@999 1956
belaran@999 1957 <programlisting format="linespecific"># This is a Mercurial configuration file.
belaran@999 1958 [ui]
belaran@999 1959 username = Firstname Lastname &lt;email.address@domain.net&gt;</programlisting>
belaran@999 1960
belaran@999 1961 <para id="x_4b">La ligne avec <literal moreinfo="none">[ui]</literal> commence une
belaran@999 1962 <emphasis>section</emphasis> du fichier de configuration, ainsi la ligne
belaran@999 1963 <quote><literal moreinfo="none">username = ...</literal></quote> signifie <quote>
belaran@999 1964 définir la valeur de l'élément <literal moreinfo="none">username</literal> dans la
belaran@999 1965 section <literal moreinfo="none">ui</literal></quote>. Une section continue jusqu'à ce
belaran@999 1966 qu'une nouvelle commence, ou que la fin du fichier soit atteinte.
belaran@999 1967 Mercurial ignore les lignes vides et traite tout texte situé à la suite
belaran@999 1968 d'un <quote><literal moreinfo="none">#</literal></quote> jusqu'à la fin de la ligne
belaran@999 1969 comme un commentaire.</para>
belaran@999 1970
belaran@999 1971 </sect3>
belaran@999 1972 <sect3>
belaran@999 1973 <title>Choisir un nom d'utilisateur</title>
belaran@999 1974
belaran@999 1975 <para id="x_4c">Vous pouvez utiliser n'importe quelle valeur
belaran@999 1976 pour votre <literal moreinfo="none">username</literal>, car cette information
belaran@999 1977 est destinée à d'autres personnes et non à être interprétée
belaran@999 1978 par Mercurial. La convention que la plupart des personnes
belaran@999 1979 suivent est d'utiliser leurs noms suivies de leurs adresses emails,
belaran@999 1980 comme montré ci-dessus :</para>
belaran@999 1981 <note>
belaran@999 1982 <para id="x_4d">Le mécanisme interne du serveur web intégré à Mercurial,
belaran@999 1983 masque les adresses emails, pour rendre plus difficile leurs
belaran@999 1984 récupérations par les outils utilisés par les spammmers.
belaran@999 1985 Ceci réduit la probabilité que de recevoir encore plus de
belaran@999 1986 spam si vous vous publiez un dépôt sur internet.</para>
belaran@999 1987 </note>
belaran@999 1988 </sect3>
belaran@999 1989 </sect2>
belaran@999 1990 <sect2>
belaran@999 1991 <title>Rédiger un message de \textit{commit}</title>
belaran@999 1992
belaran@999 1993 <para id="x_4e">Lorsqu'on effectue une opération de commit, Mercurial
belaran@999 1994 lance automatiquement un éditeur de texte pour permettre de saisir
belaran@999 1995 un message qui décrira les modifications effectuées dans cette
belaran@999 1996 révision. Ce message est nommé le <emphasis>message de commit</emphasis>.
belaran@999 1997 Ce sera un enregistrement pour tout lecteur expliquant le pourquoi
belaran@999 1998 et le comment de vos modifications, et il sera affiché par la
belaran@999 1999 commande <command role="hg-cmd" moreinfo="none">hg log</command>.</para>
belaran@999 2000
belaran@999 2001 <!-- BEGIN tour.commit -->
belaran@999 2002 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit</userinput>
belaran@999 2003 </screen>
belaran@999 2004 <!-- END tour.commit -->
belaran@999 2005
belaran@999 2006
belaran@999 2007 <para id="x_4f">L'éditeur que la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2008 commit</command> déclenche ne contiendra qu'une ligne vide suivi
belaran@999 2009 d'un certain nombre de lignes commençant par <quote><literal moreinfo="none">HG:
belaran@999 2010 </literal></quote>.</para>
belaran@999 2011
belaran@999 2012 <programlisting format="linespecific">
belaran@999 2013 This is where I type my commit comment.
belaran@999 2014
belaran@999 2015 HG: Enter commit message. Lines beginning with 'HG:' are removed.
belaran@999 2016 HG: --
belaran@999 2017 HG: user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2018 HG: branch 'default'
belaran@999 2019 HG: changed hello.c</programlisting>
belaran@999 2020
belaran@999 2021
belaran@999 2022 <para id="x_50">Mercurial ignore les lignes qui commencent
belaran@999 2023 avec <quote><literal moreinfo="none">HG:</literal></quote>, il ne les
belaran@999 2024 utilise que pour nous indiquer quels fichiers modifiés il se
belaran@999 2025 prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a
belaran@999 2026 aucune conséquence sur l'opération de commit.
belaran@999 2027 </para>
belaran@999 2028
belaran@999 2029 </sect2>
belaran@999 2030 <sect2>
belaran@999 2031 <title>Rédiger un message \textit{approprié}</title>
belaran@999 2032
belaran@999 2033 <para id="x_51">Comme <command role="hg-cmd" moreinfo="none">hg log</command> n'affiche
belaran@999 2034 que la première ligne du message de commit par défaut, il est souvent
belaran@999 2035 considéré comme une bonne pratique de rédiger des messages de commit
belaran@999 2036 qui tiennent sur une seule ligne. Voilà un exemple concret de message
belaran@999 2037 de commit qui <emphasis>ne suit pas</emphasis> cette directive, et
belaran@999 2038 qui a donc un résumé peu lisible.</para>
belaran@999 2039
belaran@999 2040 <programlisting format="linespecific">
belaran@999 2041 changeset: 73:584af0e231be
belaran@999 2042 user: Censored Person &lt;censored.person@example.org&gt;
belaran@999 2043 date: Tue Sep 26 21:37:07 2006 -0700
belaran@999 2044 summary: include buildmeister/commondefs. Add an exports and install
belaran@999 2045 </programlisting>
belaran@999 2046
belaran@999 2047 <para id="x_52">A ce sujet, il faut noter qu'il n'existe pas de règle
belaran@999 2048 absolue dans ce domaine. Mercurial lui-même n'interprète pas les
belaran@999 2049 contenus des messages de commit, ainsi votre projet est libre de
belaran@999 2050 concevoir différentes politiques de mise en page des messages.</para>
belaran@999 2051
belaran@999 2052 <para id="x_53">Ma préférence personnelle va au message court, mais
belaran@999 2053 informatif, qui offre des précisions supplémentaires par rapport à ce
belaran@999 2054 que pourrait m'apprendre une commande <command role="hg-cmd" moreinfo="none">hg log
belaran@999 2055 --patch</command>.</para>
belaran@999 2056
belaran@999 2057 <para id="x_55">Si vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2058 commit</command> sans aucun argument, elle enregistre tous les
belaran@999 2059 changements qui ont été fait, et qui sont indiqué par les commandes
belaran@999 2060 <command role="hg-cmd" moreinfo="none">hg status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command>.</para>
belaran@999 2061
belaran@999 2062 <note>
belaran@999 2063 <title>Une surprise pour les utilisateurs habitués à Subversion</title>
belaran@999 2064
belaran@999 2065 <para id="x_717">Comme n'importe quel autre commande de Mercurial, si
belaran@999 2066 vous soumettez pas de manière explicite les noms des fichiers à
belaran@999 2067 committer à la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, elle
belaran@999 2068 va travailler sur l'ensemble du répertoire de travail. Soyez conscient
belaran@999 2069 de ceci si vous venez du monde Subversion ou CVS, car vous pourriez
belaran@999 2070 attendre qu'elle opère uniquement le répertoire courant et ses sous
belaran@999 2071 répertoires.</para>
belaran@999 2072 </note>
belaran@999 2073 </sect2>
belaran@999 2074 <sect2>
belaran@999 2075 <title>Annuler un \textit{commit}</title>
belaran@999 2076
belaran@999 2077 <para id="x_54">Si, en rédigeant le message, vous décidez que
belaran@999 2078 finalement vous ne voulez pas effectuer ce commit, il suffit
belaran@999 2079 de quitter simplement l'éditeur sans sauver. Ceci n'aura aucune
belaran@999 2080 conséquence sur le dépôt ou les fichiers du répertoire de
belaran@999 2081 travail.</para>
belaran@999 2082 </sect2>
belaran@999 2083
belaran@999 2084 <sect2>
belaran@999 2085 <title>Admirer votre travail</title>
belaran@999 2086
belaran@999 2087 <para id="x_56">Une fois que votre \textit{commit} est terminé, vous
belaran@999 2088 pouvez utiliser la commande <command role="hg-cmd" moreinfo="none">hg tip</command>
belaran@999 2089 pour afficher le \textit{changeset} que vous venez de créer. Cette
belaran@999 2090 commande produit une sortie à l'écran qui est identique à celle du
belaran@999 2091 <command role="hg-cmd" moreinfo="none">hg log</command>, mais qui n'affiche que la
belaran@999 2092 dernière révision du dépôt.</para>
belaran@999 2093
belaran@999 2094 <!-- BEGIN tour.tip -->
belaran@999 2095 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -vp</userinput>
belaran@999 2096 changeset: 5:c94f208d1dfb
belaran@999 2097 tag: tip
belaran@999 2098 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2099 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2100 files: hello.c
belaran@999 2101 description:
belaran@999 2102 Added an extra line of output
belaran@999 2103
belaran@999 2104
belaran@999 2105 diff -r 2278160e78d4 -r c94f208d1dfb hello.c
belaran@999 2106 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200
belaran@999 2107 +++ b/hello.c Sun Aug 16 14:05:26 2009 +0000
belaran@999 2108 @@ -8,5 +8,6 @@
belaran@999 2109 int main(int argc, char **argv)
belaran@999 2110 {
belaran@999 2111 printf("hello, world!\");
belaran@999 2112 + printf("hello again!\n");
belaran@999 2113 return 0;
belaran@999 2114 }
belaran@999 2115
belaran@999 2116 </screen>
belaran@999 2117 <!-- END tour.tip -->
belaran@999 2118
belaran@999 2119
belaran@999 2120 <para id="x_57">On fait couramment référence à la dernière révision
belaran@999 2121 du dépôt comme étant la <emphasis>révision tip</emphasis>, ou plus
belaran@999 2122 simplement le <emphasis>tip</emphasis>.</para>
belaran@999 2123
belaran@999 2124 <para id="x_684">Au passage, la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2125 tip</command> accepte la plupart des options qu'accepte
belaran@999 2126 <command role="hg-cmd" moreinfo="none">hg log</command>. Ainsi <option role="hg-opt-global">-v</option> ci dessus implique <quote>soit
belaran@999 2127 verbeux</quote>, <option role="hg-opt-tip">-p</option>
belaran@999 2128 veux dire <quote>affiche le patch</quote>. L'utilisation de l'option
belaran@999 2129 <option role="hg-opt-tip">-p</option> pour afficher un patch est un
belaran@999 2130 autre exemple de la cohérence des commandes évoquée plus tôt.</para>
belaran@999 2131
belaran@999 2132 </sect2>
belaran@999 2133 </sect1>
belaran@999 2134 <sect1>
belaran@999 2135 <title>Partager ses modifications</title>
belaran@999 2136
belaran@999 2137 <para id="x_58">Nous avons mentionné plus haut que les dépôts
belaran@999 2138 de Mercurial sont autosuffisants. Ce qui signifie que la nouvelle
belaran@999 2139 révision que vous venez de créer existe seulement dans votre
belaran@999 2140 répertoire <filename class="directory" moreinfo="none">my-hello</filename>. Étudions
belaran@999 2141 comment propager cette modification dans d'autres dépôts.</para>
belaran@999 2142
belaran@999 2143 <sect2 id="sec:tour:pull">
belaran@999 2144 <title>Récupérer les modifications d'autres dépôts</title>
belaran@999 2145
belaran@999 2146 <para id="x_59">Pour commencer, construisons un clone de notre dépôt
belaran@999 2147 <filename class="directory" moreinfo="none">hello</filename> qui ne contiendra pas
belaran@999 2148 le changement que nous venons d'effectuer. Nous l'appellerons notre
belaran@999 2149 dépôt temporaire <filename class="directory" moreinfo="none">hello-pull</filename>.</para>
belaran@999 2150
belaran@999 2151 <!-- BEGIN tour.clone-pull -->
belaran@999 2152 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 2153 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-pull</userinput>
belaran@999 2154 updating working directory
belaran@999 2155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2156 </screen>
belaran@999 2157 <!-- END tour.clone-pull -->
belaran@999 2158
belaran@999 2159
belaran@999 2160 <para id="x_5a">Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg pull</command> pour envoyer les modifications
belaran@999 2161 depuis <filename class="directory" moreinfo="none">my-hello</filename> dans <filename class="directory" moreinfo="none">hello-pull</filename>. Néanmoins, récupérer
belaran@999 2162 aveuglement des modifications depuis un dépôt a quelque chose d'un
belaran@999 2163 peu effrayant. Mercurial propose donc une commande <command role="hg-cmd" moreinfo="none">hg incoming</command> qui permet de savoir quelles
belaran@999 2164 modifications la commande <command role="hg-cmd" moreinfo="none">hg pull</command>
belaran@999 2165 <emphasis>pourrait</emphasis> entraîner dans notre dépôt, et ceci
belaran@999 2166 sans effectuer réellement de modification dessus.</para>
belaran@999 2167
belaran@999 2168 <!-- BEGIN tour.incoming -->
belaran@999 2169 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello-pull</userinput>
belaran@999 2170 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg incoming ../my-hello</userinput>
belaran@999 2171 comparing with ../my-hello
belaran@999 2172 searching for changes
belaran@999 2173 changeset: 5:c94f208d1dfb
belaran@999 2174 tag: tip
belaran@999 2175 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2176 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2177 summary: Added an extra line of output
belaran@999 2178
belaran@999 2179 </screen>
belaran@999 2180 <!-- END tour.incoming -->
belaran@999 2181
belaran@999 2182
belaran@999 2183 <para id="x_5c">Apporter les modifications rapatriées dans un dépôt se
belaran@999 2184 résume donc à exécuter la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2185 pull</command>, et préciser depuis quel dépôt effectuer le <command role="hg-cmd" moreinfo="none">hg pull</command>.</para>
belaran@999 2186
belaran@999 2187 <!-- BEGIN tour.pull -->
belaran@999 2188 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 2189 changeset: 4:2278160e78d4
belaran@999 2190 tag: tip
belaran@999 2191 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2192 date: Sat Aug 16 22:16:53 2008 +0200
belaran@999 2193 summary: Trim comments.
belaran@999 2194
belaran@999 2195 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput>
belaran@999 2196 pulling from ../my-hello
belaran@999 2197 searching for changes
belaran@999 2198 adding changesets
belaran@999 2199 adding manifests
belaran@999 2200 adding file changes
belaran@999 2201 added 1 changesets with 1 changes to 1 files
belaran@999 2202 (run 'hg update' to get a working copy)
belaran@999 2203 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 2204 changeset: 5:c94f208d1dfb
belaran@999 2205 tag: tip
belaran@999 2206 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2207 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2208 summary: Added an extra line of output
belaran@999 2209
belaran@999 2210 </screen>
belaran@999 2211 <!-- END tour.pull -->
belaran@999 2212
belaran@999 2213
belaran@999 2214 <para id="x_5d">Comme vous le voyez avec une sortie avant et après de la
belaran@999 2215 commande <command role="hg-cmd" moreinfo="none">hg tip</command>, nous avons réussi à
belaran@999 2216 récupérer aisément les modifications dans notre dépôt. Il reste néanmoins
belaran@999 2217 quelque chose à faire avant de placer ces modifications dans l'espace de
belaran@999 2218 travail.</para>
belaran@999 2219
belaran@999 2220 <tip>
belaran@999 2221 <title>Récupérer des changements précis</title>
belaran@999 2222
belaran@999 2223 <para id="x_5b">Il est possible à cause du délai entre l'exécution de la
belaran@999 2224 commande <command role="hg-cmd" moreinfo="none">hg incoming</command> et l'exécution de
belaran@999 2225 la commande <command role="hg-cmd" moreinfo="none">hg pull</command>, que vous ne
belaran@999 2226 puissiez pas voir toutes les modifications que vous rapporterez d'un
belaran@999 2227 autre dépôt. Supposons que vous récupériez les modifications d'un dépôt
belaran@999 2228 situé quelque part sur le réseau. Alors que vous regardez le résultat de
belaran@999 2229 la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>, et avant que
belaran@999 2230 vous ne décidiez de récupérer ces modifications, quelqu'un peut ajouter
belaran@999 2231 de nouvelles révisions dans le dépôt distant. Ce qui signifie que vous
belaran@999 2232 récupérez plus de révision que ce que vous aviez regardées en utilisant
belaran@999 2233 la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>.</para>
belaran@999 2234
belaran@999 2235 <para id="x_718">Si vous voulez seulement récupérer ce que vous aviez
belaran@999 2236 vérifier à l'aide de la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2237 incoming</command>, ou que pour d'autres raisons vous souhaitiez ne
belaran@999 2238 récupérer qu'un sous ensemble des révisions supplémentaires
belaran@999 2239 disponibles, indiquant simplement les modifications que vous souhaitez
belaran@999 2240 récupérer par leurs ID de révision, soit <command moreinfo="none">hg pull
belaran@999 2241 -r7e95bb</command>. </para>
belaran@999 2242 </tip>
belaran@999 2243
belaran@999 2244 </sect2>
belaran@999 2245 <sect2>
belaran@999 2246 <title>Mise à jour de l'espace de travail</title>
belaran@999 2247
belaran@999 2248 <para id="x_5e">Nous avons jusqu'à maintenant grossièrement défini la
belaran@999 2249 relation entre un dépôt et un espace de travail. La commande <command role="hg-cmd" moreinfo="none">hg pull</command> que nous avons exécutée dans la section
belaran@999 2250 <xref linkend="sec:tour:pull"/> a apporté des modifications, que nous
belaran@999 2251 avons vérifiées, dans notre dépôt, mais il n'y a aucune trace de ces
belaran@999 2252 modifications dans notre espace de travail. En effet, <command role="hg-cmd" moreinfo="none">hg pull</command> ne touche pas (par défaut) à l'espace
belaran@999 2253 de travail. C'est la commande <command role="hg-cmd" moreinfo="none">hg update</command>
belaran@999 2254 qui s'en charge.</para>
belaran@999 2255
belaran@999 2256 <!-- BEGIN tour.update -->
belaran@999 2257 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput>
belaran@999 2258 printf("hello, world!\");
belaran@999 2259 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update tip</userinput>
belaran@999 2260 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2261 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput>
belaran@999 2262 printf("hello, world!\");
belaran@999 2263 printf("hello again!\n");
belaran@999 2264 </screen>
belaran@999 2265 <!-- END tour.update -->
belaran@999 2266
belaran@999 2267
belaran@999 2268 <para id="x_5f">Il peut sembler un peu étrange que la commande <command role="hg-cmd" moreinfo="none">hg pull</command> ne mette pas à jour l'espace de travail
belaran@999 2269 automatiquement. Il y a en fait une très bonne raison à cela : vous
belaran@999 2270 pouvez utilisez la commande <command role="hg-cmd" moreinfo="none">hg update</command>
belaran@999 2271 pour mettre à jour votre espace de travail à l'état dans lequel il était
belaran@999 2272 à <emphasis>n'importe quelle révision</emphasis> de l'historique du dépôt.
belaran@999 2273 Si vous aviez un espace de travail contenant une ancienne
belaran@999 2274 révision—pour chercher l'origine d'un bug, par exemple—et
belaran@999 2275 que vous effectuiez un <command role="hg-cmd" moreinfo="none">hg pull</command> qui
belaran@999 2276 mettrait à jour automatiquement votre espace de travail, vous ne seriez
belaran@999 2277 probablement pas très satisfait.</para>
belaran@999 2278
belaran@999 2279 <para id="x_60">Néanmoins, comme les opérations de pull sont très souvent
belaran@999 2280 suivies d'un update, Mercurial vous permet de combiner les
belaran@999 2281 deux aisément en passant l'option <option role="hg-opt-pull">-u</option>
belaran@999 2282 à la commande <command role="hg-cmd" moreinfo="none">hg pull</command>.</para>
belaran@999 2283
belaran@999 2284 <para id="x_61">Si vous étudiez de nouveau la sortie de la commande <command role="hg-cmd" moreinfo="none">hg pull</command> dans la section <xref linkend="sec:tour:pull"/> quand nous l'avons exécutée sans l'option
belaran@999 2285 <option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a
belaran@999 2286 affiché un rappel assez utile : vous devez encore effectuer une
belaran@999 2287 opération pour mettre à jour votre espace de travail.</para>
belaran@999 2288
belaran@999 2289 <para id="x_62">Pour découvrir sur quelle révision de l'espace de
belaran@999 2290 travail on se trouve, utilisez la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2291 parents</command>.</para>
belaran@999 2292
belaran@999 2293 <!-- BEGIN tour.parents -->
belaran@999 2294 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 2295 changeset: 5:c94f208d1dfb
belaran@999 2296 tag: tip
belaran@999 2297 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2298 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2299 summary: Added an extra line of output
belaran@999 2300
belaran@999 2301 </screen>
belaran@999 2302 <!-- END tour.parents -->
belaran@999 2303
belaran@999 2304
belaran@999 2305 <para id="x_63">Si vous regardez de nouveau le dessin <xref linkend="fig:tour-basic:history"/>, vous verrez les flèches reliant
belaran@999 2306 entre elles les révisions. Le nœud d'où la flèche
belaran@999 2307 <emphasis>part</emphasis> est dans chaque cas un parent,
belaran@999 2308 et le nœud où la flèche <emphasis>arrive</emphasis> est un
belaran@999 2309 enfant.</para>
belaran@999 2310
belaran@999 2311 <para id="x_64">Pour mettre à jour l'espace de travail d'une révision
belaran@999 2312 particulière, indiquez un numéro de révision ou un \textit{changeset
belaran@999 2313 ID} à la commande <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
belaran@999 2314
belaran@999 2315 <!-- BEGIN tour.older -->
belaran@999 2316 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update 2</userinput>
belaran@999 2317 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2318 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 2319 changeset: 2:fef857204a0c
belaran@999 2320 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2321 date: Sat Aug 16 22:05:04 2008 +0200
belaran@999 2322 summary: Introduce a typo into hello.c.
belaran@999 2323
belaran@999 2324 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
belaran@999 2325 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2326 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 2327 changeset: 5:c94f208d1dfb
belaran@999 2328 tag: tip
belaran@999 2329 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2330 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2331 summary: Added an extra line of output
belaran@999 2332
belaran@999 2333 </screen>
belaran@999 2334 <!-- END tour.older -->
belaran@999 2335
belaran@999 2336
belaran@999 2337 <para id="x_65">Si vous ne précisez pas de manière explicite de numéro
belaran@999 2338 de révision la commande <command role="hg-cmd" moreinfo="none">hg update</command>
belaran@999 2339 mettra à jour votre espace de travail avec le contenu de la révison
belaran@999 2340 \textit{tip}, comme montré dans l'exemple ci dessus lors du second
belaran@999 2341 appel à <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
belaran@999 2342
belaran@999 2343 </sect2>
belaran@999 2344 <sect2>
belaran@999 2345 <title>Transférer les modifications vers un autre dépôt</title>
belaran@999 2346
belaran@999 2347 <para id="x_66">Mercurial vous laisse transférer les modifications vers
belaran@999 2348 un autre dépôt, depuis votre dépôt actuel. Comme dans l'exemple du
belaran@999 2349 <command role="hg-cmd" moreinfo="none">hg pull</command> ci-dessus, nous allons créer
belaran@999 2350 un dépôt temporaire vers lequel transférer nos modifications.</para>
belaran@999 2351
belaran@999 2352 <!-- BEGIN tour.clone-push -->
belaran@999 2353 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 2354 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-push</userinput>
belaran@999 2355 updating working directory
belaran@999 2356 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2357 </screen>
belaran@999 2358 <!-- END tour.clone-push -->
belaran@999 2359
belaran@999 2360
belaran@999 2361 <para id="x_67">La commande <command role="hg-cmd" moreinfo="none">hg outgoing</command>
belaran@999 2362 nous indique quels changements nous allons transférer vers l'autre
belaran@999 2363 serveur.</para>
belaran@999 2364
belaran@999 2365 <!-- BEGIN tour.outgoing -->
belaran@999 2366 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput>
belaran@999 2367 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing ../hello-push</userinput>
belaran@999 2368 comparing with ../hello-push
belaran@999 2369 searching for changes
belaran@999 2370 changeset: 5:c94f208d1dfb
belaran@999 2371 tag: tip
belaran@999 2372 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2373 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2374 summary: Added an extra line of output
belaran@999 2375
belaran@999 2376 </screen>
belaran@999 2377 <!-- END tour.outgoing -->
belaran@999 2378
belaran@999 2379
belaran@999 2380 <para id="x_68">Et la commande <command role="hg-cmd" moreinfo="none">hg push</command>
belaran@999 2381 effectue réellement le transfert.</para>
belaran@999 2382
belaran@999 2383 <!-- BEGIN tour.push -->
belaran@999 2384 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput>
belaran@999 2385 pushing to ../hello-push
belaran@999 2386 searching for changes
belaran@999 2387 adding changesets
belaran@999 2388 adding manifests
belaran@999 2389 adding file changes
belaran@999 2390 added 1 changesets with 1 changes to 1 files
belaran@999 2391 </screen>
belaran@999 2392 <!-- END tour.push -->
belaran@999 2393
belaran@999 2394
belaran@999 2395 <para id="x_69">Comme avec <command role="hg-cmd" moreinfo="none">hg pull</command>, la
belaran@999 2396 commande <command role="hg-cmd" moreinfo="none">hg push</command> ne met pas à jour
belaran@999 2397 le répertoire de travail du dépôt dans lequel il transfère les
belaran@999 2398 modifications. À l'inverse de <command role="hg-cmd" moreinfo="none">hg
belaran@999 2399 pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> ne fournit
belaran@999 2400 pas d'option <literal moreinfo="none">-u</literal> pour forcer la mise à jour de
belaran@999 2401 l'espace de travail cible. Cette asymétrie est délibéré : le dépot
belaran@999 2402 vers lequel nous transférons peut très bien être un serveur distant
belaran@999 2403 et partagé par plusieurs personnes. Si nous devions mettre à jour son
belaran@999 2404 répertoire de travail alors que quelqu'un d'autre travaille dessus,
belaran@999 2405 nous risquerions de perturber son travail.</para>
belaran@999 2406
belaran@999 2407 <para id="x_6a">Qu'est ce qui se passe lorsque vous essayez de récupérer
belaran@999 2408 ou de transférer vos modifications et que le dépôt cible a déjà reçu
belaran@999 2409 ces modifications ? Rien de bien excitant.</para>
belaran@999 2410
belaran@999 2411 <!-- BEGIN tour.push.nothing -->
belaran@999 2412 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput>
belaran@999 2413 pushing to ../hello-push
belaran@999 2414 searching for changes
belaran@999 2415 no changes found
belaran@999 2416 </screen>
belaran@999 2417 <!-- END tour.push.nothing -->
belaran@999 2418
belaran@999 2419
belaran@999 2420 </sect2>
belaran@999 2421
belaran@999 2422 <sect2>
belaran@999 2423 <title>Emplacements par défaut</title>
belaran@999 2424
belaran@999 2425 <para id="x_719">Quand nous faisons un clone d'un dépôt, Mercurial
belaran@999 2426 enregistre l'emplacement du dépôt d'origine dans le fichier
belaran@999 2427 <filename moreinfo="none">.hg/hgrc</filename> de notre nouveau dépôt. Si nous ne
belaran@999 2428 fournissons pas d'emplacement à la commande <command moreinfo="none">hg
belaran@999 2429 pull</command> ou à la commande <command moreinfo="none">hg push</command>, ces
belaran@999 2430 commandes utiliseront alors cet emplacement comme valeur par défaut.
belaran@999 2431 Les commandes <command moreinfo="none">hg incoming</command> et <command moreinfo="none">hg
belaran@999 2432 outgoing</command> feront de même.</para>
belaran@999 2433
belaran@999 2434 <para id="x_71a">Si vous regardez le fichier
belaran@999 2435 <filename moreinfo="none">.hg/hgrc</filename>, vous constaterez que son contenu
belaran@999 2436 ressemble à ce qui suit.</para>
belaran@999 2437
belaran@999 2438 <programlisting format="linespecific">[paths]
belaran@999 2439 default = http://www.selenic.com/repo/hg</programlisting>
belaran@999 2440
belaran@999 2441 <para id="x_71b">Il est possible—et souvent
belaran@999 2442 pratique—d'avoir un emplacement par défaut pour les commandes
belaran@999 2443 <command moreinfo="none">hg push</command> et <command moreinfo="none">hg outgoing</command>
belaran@999 2444 différent de celui des commandes <command moreinfo="none">hg pull</command> et
belaran@999 2445 <command moreinfo="none">hg incoming</command>. C'est faisable en ajoutant une entrée
belaran@999 2446 <literal moreinfo="none">default-push</literal> à la section
belaran@999 2447 <literal moreinfo="none">[paths]</literal> du <filename moreinfo="none">.hg/hgrc</filename>, comme
belaran@999 2448 suit.</para>
belaran@999 2449
belaran@999 2450 <programlisting format="linespecific">[paths]
belaran@999 2451 default = http://www.selenic.com/repo/hg
belaran@999 2452 default-push = http://hg.example.com/hg</programlisting>
belaran@999 2453
belaran@999 2454 </sect2>
belaran@999 2455 <sect2>
belaran@999 2456 <title>Partager ses modifications à travers le réseau</title>
belaran@999 2457
belaran@999 2458 <para id="x_6b">Les commandes que nous avons étudiées dans les sections
belaran@999 2459 précédentes ne sont pas limitées aux dépôts locaux. Chacune fonctionne
belaran@999 2460 de la même manière à travers une connexion réseau, il suffit de lui
belaran@999 2461 passer une URL à la place d'un chemin de fichier local.</para>
belaran@999 2462
belaran@999 2463 <!-- BEGIN tour.outgoing.net -->
belaran@999 2464 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing http://hg.serpentine.com/tutorial/hello</userinput>
belaran@999 2465 comparing with http://hg.serpentine.com/tutorial/hello
belaran@999 2466 searching for changes
belaran@999 2467 changeset: 5:c94f208d1dfb
belaran@999 2468 tag: tip
belaran@999 2469 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2470 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2471 summary: Added an extra line of output
belaran@999 2472
belaran@999 2473 </screen>
belaran@999 2474 <!-- END tour.outgoing.net -->
belaran@999 2475
belaran@999 2476
belaran@999 2477 <para id="x_6c">Dans cet exemple, nous allons voir quels changements
belaran@999 2478 nous pourrions transférer vers le dépôt distant, mais le dépôt est,
belaran@999 2479 de manière tout à fait compréhensible, pas configuré pour accepter
belaran@999 2480 des modifications d'utilisateurs anonymes.</para>
belaran@999 2481
belaran@999 2482 <!-- BEGIN tour.push.net -->
belaran@999 2483 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push http://hg.serpentine.com/tutorial/hello</userinput>
belaran@999 2484 pushing to http://hg.serpentine.com/tutorial/hello
belaran@999 2485 searching for changes
belaran@999 2486 ssl required
belaran@999 2487 </screen>
belaran@999 2488 <!-- END tour.push.net -->
belaran@999 2489
belaran@999 2490
belaran@999 2491 </sect2>
belaran@999 2492
belaran@999 2493 </sect1>
belaran@999 2494
belaran@999 2495 <sect1>
belaran@999 2496 <title>Commencer un nouveau projet</title>
belaran@999 2497
belaran@999 2498 <para id="x_71c">Il est tout aussi aisé de commencer un nouveau projet
belaran@999 2499 que de travailler sur un qui existe déjà. La commande <command moreinfo="none">hg
belaran@999 2500 init</command> crée un nouveau dépôt Mercurial vide.</para>
belaran@999 2501
belaran@999 2502 <!-- BEGIN ch01/new.init -->
belaran@999 2503 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myproject</userinput>
belaran@999 2504 </screen>
belaran@999 2505 <!-- END ch01/new.init -->
belaran@999 2506
belaran@999 2507
belaran@999 2508 <para id="x_71d">Ceci crée simplement un répertoire nommé
belaran@999 2509 <filename moreinfo="none">myproject</filename> dans le répertoire courant.</para>
belaran@999 2510
belaran@999 2511 <!-- BEGIN ch01/new.ls -->
belaran@999 2512 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput>
belaran@999 2513 total 12
belaran@999 2514 -rw-r--r-- 1 rpelisse rpelisse 47 Aug 16 14:04 goodbye.c
belaran@999 2515 -rw-r--r-- 1 rpelisse rpelisse 45 Aug 16 14:04 hello.c
belaran@999 2516 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 myproject
belaran@999 2517 </screen>
belaran@999 2518 <!-- END ch01/new.ls -->
belaran@999 2519
belaran@999 2520
belaran@999 2521 <para id="x_71e">Nous pouvons dire que <filename moreinfo="none">myproject</filename> est
belaran@999 2522 un dépôt Mercurial car il contient un répertoire
belaran@999 2523 <filename moreinfo="none">.hg</filename>.</para>
belaran@999 2524
belaran@999 2525 <!-- BEGIN ch01/new.ls2 -->
belaran@999 2526 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -al myproject</userinput>
belaran@999 2527 total 12
belaran@999 2528 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .
belaran@999 2529 drwx------ 3 rpelisse rpelisse 4096 Aug 16 14:04 ..
belaran@999 2530 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .hg
belaran@999 2531 </screen>
belaran@999 2532 <!-- END ch01/new.ls2 -->
belaran@999 2533
belaran@999 2534
belaran@999 2535 <para id="x_71f">Si vous voulons ajouter quelques fichiers préexistants
belaran@999 2536 dans ce dépôt, il suffit de les recopier dans le répertoire de travail,
belaran@999 2537 et demander à Mercurial de commencer à les suivre en utilisant la
belaran@999 2538 commande <command moreinfo="none">hg add</command>.</para>
belaran@999 2539
belaran@999 2540 <!-- BEGIN ch01/new.add -->
belaran@999 2541 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput>
belaran@999 2542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../hello.c .</userinput>
belaran@999 2543 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../goodbye.c .</userinput>
belaran@999 2544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add</userinput>
belaran@999 2545 adding goodbye.c
belaran@999 2546 adding hello.c
belaran@999 2547 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 2548 A goodbye.c
belaran@999 2549 A hello.c
belaran@999 2550 </screen>
belaran@999 2551 <!-- END ch01/new.add -->
belaran@999 2552
belaran@999 2553
belaran@999 2554 <para id="x_720">Une fois que nous sommes satisfaits de notre projet,
belaran@999 2555 nous pouvons commencer à ajouter nos révisions.</para>
belaran@999 2556
belaran@999 2557 <!-- BEGIN ch01/new.commit -->
belaran@999 2558 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Initial commit'</userinput>
belaran@999 2559 </screen>
belaran@999 2560 <!-- END ch01/new.commit -->
belaran@999 2561
belaran@999 2562
belaran@999 2563 <para id="x_721">Il ne prend que quelques instants pour commencer à
belaran@999 2564 utiliser Mercurial sur un nouveau projet, ce qui fait aussi de ses
belaran@999 2565 points forts. Travailler avec une gestion de révision devient très
belaran@999 2566 facile, nous pouvons même l'utiliser pour les plus petits projets où
belaran@999 2567 nous aurions probablement jamais penser utiliser un outils aussi
belaran@999 2568 complexe.</para>
belaran@999 2569 </sect1>
belaran@999 2570 </chapter>
belaran@999 2571
belaran@999 2572 <!--
belaran@999 2573 local variables:
belaran@999 2574 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 2575 end:
belaran@999 2576 -->
belaran@999 2577
belaran@999 2578 <!-- BEGIN ch03 -->
belaran@999 2579 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 2580
belaran@999 2581 <chapter id="chap:tour-merge">
belaran@999 2582 <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?>
belaran@999 2583 <title>Un rapide tour de Mercurial: fusionner les travaux</title>
belaran@999 2584
belaran@999 2585 <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer
belaran@999 2586 des changements dedans, et récupérer ou transférer depuis un
belaran@999 2587 autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les
belaran@999 2588 modifications de différents dépôts.</para>
belaran@999 2589
belaran@999 2590 <sect1>
belaran@999 2591 <title>Fusionner différents travaux</title>
belaran@999 2592 <para id="x_339">La fusion est un aspect fondamental lorsqu'on
belaran@999 2593 travaille iavec un gestionnaire de source distribué.</para>
belaran@999 2594
belaran@999 2595 <itemizedlist>
belaran@999 2596 <listitem>
belaran@999 2597 <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un
belaran@999 2598 projet sur lequel ils collaborent. Alice corrige un bug
belaran@999 2599 dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
belaran@999 2600 sien. Ils veulent un dépôt partagé avec à la fois le correctif du
belaran@999 2601 bug et la nouvelle fonctionnalité.</para>
belaran@999 2602 </listitem>
belaran@999 2603 <listitem>
belaran@999 2604 <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur
belaran@999 2605 un seul projet en même temps, chacun isolé dans son propre dépôt.
belaran@999 2606 Travailler ainsi signifie que je dois régulièrement fusionner une
belaran@999 2607 partie de mon code avec celui des autres.</para>
belaran@999 2608 </listitem>
belaran@999 2609 </itemizedlist>
belaran@999 2610
belaran@999 2611 <para id="x_33c">Parce que la fusion est une opération si commune à réaliser,
belaran@999 2612 Mercurial la rend facile. Étudions ensemble le déroulement des
belaran@999 2613 opérations. Nous commencerons encore par faire un clone d'un autre
belaran@999 2614 dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons
belaran@999 2615 quelques modifications dessus.</para>
belaran@999 2616
belaran@999 2617 <!-- BEGIN tour.merge.clone -->
belaran@999 2618 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 2619 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-new-hello</userinput>
belaran@999 2620 updating working directory
belaran@999 2621 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 2622 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-new-hello</userinput>
belaran@999 2623 # Make some simple edits to hello.c.
belaran@999 2624 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">my-text-editor hello.c</userinput>
belaran@999 2625 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'A new hello for a new day.'</userinput>
belaran@999 2626 </screen>
belaran@999 2627 <!-- END tour.merge.clone -->
belaran@999 2628
belaran@999 2629
belaran@999 2630 <para id="x_33d">Nous devrions avoir maintenant deux copies de
belaran@999 2631 <filename moreinfo="none">hello.c</filename> avec des contenus différents. Les
belaran@999 2632 historiques de ces deux dépôts ont aussi divergés, comme illustré dans
belaran@999 2633 la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para>
belaran@999 2634
belaran@999 2635 <!-- BEGIN tour.merge.cat1 -->
belaran@999 2636 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
belaran@999 2637 /*
belaran@999 2638 * Placed in the public domain by Bryan O'Sullivan. This program is
belaran@999 2639 * not covered by patents in the United States or other countries.
belaran@999 2640 */
belaran@999 2641
belaran@999 2642 #include &lt;stdio.h&gt;
belaran@999 2643
belaran@999 2644 int main(int argc, char **argv)
belaran@999 2645 {
belaran@999 2646 printf("once more, hello.\n");
belaran@999 2647 printf("hello, world!\");
belaran@999 2648 printf("hello again!\n");
belaran@999 2649 return 0;
belaran@999 2650 }
belaran@999 2651 </screen>
belaran@999 2652 <!-- END tour.merge.cat1 -->
belaran@999 2653
belaran@999 2654
belaran@999 2655 <para id="x_722">Et ici est notre légèrement différente version du
belaran@999 2656 dépôt.</para>
belaran@999 2657
belaran@999 2658 <!-- BEGIN tour.merge.cat2 -->
belaran@999 2659 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat ../my-hello/hello.c</userinput>
belaran@999 2660 /*
belaran@999 2661 * Placed in the public domain by Bryan O'Sullivan. This program is
belaran@999 2662 * not covered by patents in the United States or other countries.
belaran@999 2663 */
belaran@999 2664
belaran@999 2665 #include &lt;stdio.h&gt;
belaran@999 2666
belaran@999 2667 int main(int argc, char **argv)
belaran@999 2668 {
belaran@999 2669 printf("hello, world!\");
belaran@999 2670 printf("hello again!\n");
belaran@999 2671 return 0;
belaran@999 2672 }
belaran@999 2673 </screen>
belaran@999 2674 <!-- END tour.merge.cat2 -->
belaran@999 2675
belaran@999 2676
belaran@999 2677 <figure id="fig:tour-merge:sep-repos" float="0">
belaran@999 2678 <title>Historique divergent des dépôts <filename class="directory" moreinfo="none">my-hello</filename> et <filename class="directory" moreinfo="none">my-new-hello</filename>.</title>
belaran@999 2679 <mediaobject>
belaran@999 2680 <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject>
belaran@999 2681 <textobject><phrase>XXX ajoute un test</phrase></textobject>
belaran@999 2682 </mediaobject>
belaran@999 2683 </figure>
belaran@999 2684
belaran@999 2685 <para id="x_33f">Nous savons déjà que récupérer les modifications depuis
belaran@999 2686 notre dépôt <filename class="directory" moreinfo="none">my-hello</filename> n'aura
belaran@999 2687 aucun effet sur l'espace de travail.</para>
belaran@999 2688
belaran@999 2689 <!-- BEGIN tour.merge.pull -->
belaran@999 2690 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput>
belaran@999 2691 pulling from ../my-hello
belaran@999 2692 searching for changes
belaran@999 2693 adding changesets
belaran@999 2694 adding manifests
belaran@999 2695 adding file changes
belaran@999 2696 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 2697 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 2698 </screen>
belaran@999 2699 <!-- END tour.merge.pull -->
belaran@999 2700
belaran@999 2701
belaran@999 2702 <para id="x_340">Néanmoins, la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2703 pull</command> nous indique quelque chose au sujet des
belaran@999 2704 <quote>heads</quote>.</para>
belaran@999 2705
belaran@999 2706 <sect2>
belaran@999 2707 <title>Les révisions 'heads'</title>
belaran@999 2708
belaran@999 2709 <para id="x_341">Rappellez vous que Mercurial enregistre quelle révision
belaran@999 2710 est le parent de chaque révision. Si une révision a un parent, nous
belaran@999 2711 l'appelons un enfant(child) ou un descendant de ce parent. Une
belaran@999 2712 "head" est une révision qui n'a donc pas d'enfant. La révision tip
belaran@999 2713 est donc une "head", car c'est la révision la plus récente du dépôt
belaran@999 2714 qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir
belaran@999 2715 plusieurs "head".</para>
belaran@999 2716
belaran@999 2717 <figure id="fig:tour-merge:pull" float="0">
belaran@999 2718 <title>Contenu du dépôt après une récupération ("pull") depuis le
belaran@999 2719 dépôt <filename class="directory" moreinfo="none">my-hello</filename> vers le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename></title>
belaran@999 2720 <mediaobject>
belaran@999 2721 <imageobject>
belaran@999 2722 <imagedata fileref="tour-merge-pull"/>
belaran@999 2723 </imageobject>
belaran@999 2724 <textobject><phrase>XXX ajoute un texte</phrase></textobject>
belaran@999 2725 </mediaobject>
belaran@999 2726 </figure>
belaran@999 2727
belaran@999 2728 <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>,
belaran@999 2729 vous pouvez constater l'effet d'un \textit{pull} depuis le dépôt
belaran@999 2730 <filename class="directory" moreinfo="none">my-hello</filename> dans le dépôt
belaran@999 2731 <filename class="directory" moreinfo="none">my-new-hello</filename>. L'historique qui
belaran@999 2732 était déjà présent dans le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename> reste intact, mais une
belaran@999 2733 nouvelle révision a été ajoutée. En vous reportant à la figure <xref linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que le
belaran@999 2734 <emphasis>ID de révision (changeset ID)</emphasis> reste le même dans
belaran@999 2735 le nouveau dépôt, mais que le <emphasis>numéro de
belaran@999 2736 révision</emphasis> reste le même. (Ceci est un parfait exemple de
belaran@999 2737 pourquoi il n'est fiable d'utiliser les numéros de révision lorsque
belaran@999 2738 l'on discute d'un \textit{changeset}.) Vous pouvez voir les "heads"
belaran@999 2739 présentes dans le dépôt en utilisant la commande <command role="hg-cmd" moreinfo="none">hg heads</command>.</para>
belaran@999 2740
belaran@999 2741 <!-- BEGIN tour.merge.heads -->
belaran@999 2742 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
belaran@999 2743 changeset: 6:c94f208d1dfb
belaran@999 2744 tag: tip
belaran@999 2745 parent: 4:2278160e78d4
belaran@999 2746 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2747 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2748 summary: Added an extra line of output
belaran@999 2749
belaran@999 2750 changeset: 5:5f06f94fbeca
belaran@999 2751 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2752 date: Sun Aug 16 14:05:31 2009 +0000
belaran@999 2753 summary: A new hello for a new day.
belaran@999 2754
belaran@999 2755 </screen>
belaran@999 2756 <!-- END tour.merge.heads -->
belaran@999 2757
belaran@999 2758 </sect2>
belaran@999 2759
belaran@999 2760 <sect2>
belaran@999 2761 <title>Effectuer la fusion</title>
belaran@999 2762
belaran@999 2763 <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la
belaran@999 2764 commande <command role="hg-cmd" moreinfo="none">hg update</command> pour mettre à
belaran@999 2765 jour votre espace de travail au nouveau "tip"</para>
belaran@999 2766
belaran@999 2767 <!-- BEGIN tour.merge.update -->
belaran@999 2768 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
belaran@999 2769 abort: crosses branches (use 'hg merge' or 'hg update -C')
belaran@999 2770 </screen>
belaran@999 2771 <!-- END tour.merge.update -->
belaran@999 2772
belaran@999 2773
belaran@999 2774
belaran@999 2775 <para id="x_345">Mercurial nous prévient que la commande <command role="hg-cmd" moreinfo="none">hg update</command> n'effectuera pas
belaran@999 2776 la fusion, il ne veut pas mettre à jour l'espace de travail quand il
belaran@999 2777 estime que nous pourrions avoir besoin d'une fusion, à moins de lui
belaran@999 2778 forcer la main. À la place, il faut utiliser la commande <command role="hg-cmd" moreinfo="none">hg merge</command> pour fusionner les deux
belaran@999 2779 "heads".</para>
belaran@999 2780
belaran@999 2781 <para id="x_723">Pour commencer une fusion (merge) entre deux "heads",
belaran@999 2782 nous utilisons la commande <command role="hg-cmd" moreinfo="none">hg merge</command>.</para>
belaran@999 2783
belaran@999 2784 <!-- BEGIN tour.merge.merge -->
belaran@999 2785 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 2786 merging hello.c
belaran@999 2787 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
belaran@999 2788 (branch merge, don't forget to commit)
belaran@999 2789 </screen>
belaran@999 2790 <!-- END tour.merge.merge -->
belaran@999 2791
belaran@999 2792
belaran@999 2793 <para id="x_347">Nous résolvons les conflits dans le fichier
belaran@999 2794 <filename moreinfo="none">hello.c</filename>. Ceci met à jour le répertoire de travail
belaran@999 2795 de sorte qu'il ne contienne les modifications ne provenance des
belaran@999 2796 <emphasis>deux</emphasis> "heads", ce qui est indiqué par la
belaran@999 2797 la sortie de la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 2798 parents</command> et le contenu du fichier
belaran@999 2799 <filename moreinfo="none">hello.c</filename>.</para>
belaran@999 2800
belaran@999 2801 <!-- BEGIN tour.merge.parents -->
belaran@999 2802 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 2803 changeset: 5:5f06f94fbeca
belaran@999 2804 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2805 date: Sun Aug 16 14:05:31 2009 +0000
belaran@999 2806 summary: A new hello for a new day.
belaran@999 2807
belaran@999 2808 changeset: 6:c94f208d1dfb
belaran@999 2809 tag: tip
belaran@999 2810 parent: 4:2278160e78d4
belaran@999 2811 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2812 date: Sun Aug 16 14:05:26 2009 +0000
belaran@999 2813 summary: Added an extra line of output
belaran@999 2814
belaran@999 2815 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
belaran@999 2816 /*
belaran@999 2817 * Placed in the public domain by Bryan O'Sullivan. This program is
belaran@999 2818 * not covered by patents in the United States or other countries.
belaran@999 2819 */
belaran@999 2820
belaran@999 2821 #include &lt;stdio.h&gt;
belaran@999 2822
belaran@999 2823 int main(int argc, char **argv)
belaran@999 2824 {
belaran@999 2825 printf("once more, hello.\n");
belaran@999 2826 printf("hello, world!\");
belaran@999 2827 printf("hello again!\n");
belaran@999 2828 return 0;
belaran@999 2829 }
belaran@999 2830 </screen>
belaran@999 2831 <!-- END tour.merge.parents -->
belaran@999 2832
belaran@999 2833 </sect2>
belaran@999 2834
belaran@999 2835 <sect2>
belaran@999 2836 <title>Effectuer l'ajout (commit) du résultat de la fusion</title>
belaran@999 2837
belaran@999 2838 <para id="x_348">Dès l'instant où vous avez effectué une fusion
belaran@999 2839 (merge), <command role="hg-cmd" moreinfo="none">hg parents</command> vous
belaran@999 2840 affichera deux parents, avant que vous n'exécutiez la commande
belaran@999 2841 <command role="hg-cmd" moreinfo="none">hg commit</command> sur le résultat de la
belaran@999 2842 fusion.</para>
belaran@999 2843
belaran@999 2844 <!-- BEGIN tour.merge.commit -->
belaran@999 2845 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merged changes'</userinput>
belaran@999 2846 </screen>
belaran@999 2847 <!-- END tour.merge.commit -->
belaran@999 2848
belaran@999 2849
belaran@999 2850 <para id="x_349">Nous avons maintenant un nouveau tip, remarquer qu'il
belaran@999 2851 contient <emphasis>à la fois</emphasis> nos anciennes "heads" et leurs
belaran@999 2852 parents. Ce sont les mêmes révisions que nous avions affichées avec
belaran@999 2853 la commande <command role="hg-cmd" moreinfo="none">hg parents</command>.</para>
belaran@999 2854
belaran@999 2855 <!-- BEGIN tour.merge.tip -->
belaran@999 2856 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 2857 changeset: 7:b8e1e756ef55
belaran@999 2858 tag: tip
belaran@999 2859 parent: 5:5f06f94fbeca
belaran@999 2860 parent: 6:c94f208d1dfb
belaran@999 2861 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 2862 date: Sun Aug 16 14:05:33 2009 +0000
belaran@999 2863 summary: Merged changes
belaran@999 2864
belaran@999 2865 </screen>
belaran@999 2866 <!-- END tour.merge.tip -->
belaran@999 2867
belaran@999 2868
belaran@999 2869 <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>,
belaran@999 2870 vous pouvez voir une représentation de ce qui se passe dans l'espace
belaran@999 2871 de travail pendant la fusion, et comment ceci affecte le dépôt lors
belaran@999 2872 du "commit". Pendant la fusion, l'espace de travail, qui a deux
belaran@999 2873 révisions (changesets) comme parents, voit ces derniers devenir le parent
belaran@999 2874 d'une nouvelle révision (changeset).</para>
belaran@999 2875
belaran@999 2876 <figure id="fig:tour-merge:merge" float="0">
belaran@999 2877 <title>Working directory and repository during merge, and
belaran@999 2878 following commit</title>
belaran@999 2879 <mediaobject>
belaran@999 2880 <imageobject>
belaran@999 2881 <imagedata fileref="figs/tour-merge-merge.png"/>
belaran@999 2882 </imageobject>
belaran@999 2883 <textobject><phrase>XXX ajoute texte</phrase></textobject>
belaran@999 2884 </mediaobject>
belaran@999 2885 </figure>
belaran@999 2886
belaran@999 2887 </sect2>
belaran@999 2888 </sect1>
belaran@999 2889
belaran@999 2890 <sect1>
belaran@999 2891 <title>Fusionner les modifications en conflit</title>
belaran@999 2892
belaran@999 2893 <para id="x_34b">La plupart des fusions sont assez simple à réaliser, mais
belaran@999 2894 parfois vous vous retrouverez à fusionner des fichiers où la modification
belaran@999 2895 touche la même portion de code, au sein d'un même fichier. À moins
belaran@999 2896 que ces modification ne soient identiques, ceci aboutira à un
belaran@999 2897 <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier
belaran@999 2898 les différentes modifications dans un tout cohérent.</para>
belaran@999 2899
belaran@999 2900 <figure id="fig:tour-merge:conflict" float="0">
belaran@999 2901 <title>Modifications en conflits dans un document</title>
belaran@999 2902 <mediaobject>
belaran@999 2903 <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
belaran@999 2904 <textobject><phrase>XXX ajoute texte</phrase></textobject>
belaran@999 2905 </mediaobject>
belaran@999 2906 </figure>
belaran@999 2907
belaran@999 2908 <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/>
belaran@999 2909 illustre un cas de modifications conflictuelles dans un document. Nous
belaran@999 2910 avons commencé avec une version simple de ce fichier, puis nous avons
belaran@999 2911 ajouté des modifications, pendant que quelqu'un d'autre modifiait le même
belaran@999 2912 texte. Notre tâche dans la résolution du conflit est de décider à quoi le
belaran@999 2913 fichier devrait ressembler.</para>
belaran@999 2914
belaran@999 2915 <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer
belaran@999 2916 les conflits. À la place, il exécute un programme externe appelé
belaran@999 2917 <command moreinfo="none">hgmerge</command>. Il s'agit d'un script shell qui est
belaran@999 2918 embarqué par Mercurial, vous pouvez le modifier si vous le voulez.
belaran@999 2919 Ce qu'il fait par défaut est d'essayer de trouver un des différents
belaran@999 2920 outils de fusion qui seront probablement installés sur le système.
belaran@999 2921 Il commence par les outils totalement automatiques, et si ils
belaran@999 2922 échouent (parce que la résolution du conflit nécessite une
belaran@999 2923 intervention humaine) ou si ils sont absents, le script tente
belaran@999 2924 d'exécuter certains outils graphiques de fusion.</para>
belaran@999 2925
belaran@999 2926 <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter
belaran@999 2927 un autre programme ou un autre script en définissant la variable
belaran@999 2928 d'environnement <envar>HGMERGE</envar> avec le nom
belaran@999 2929 du programme de votre choix.</para>
belaran@999 2930
belaran@999 2931 <sect2>
belaran@999 2932 <title>Utiliser un outil graphique de fusion</title>
belaran@999 2933
belaran@999 2934 <para id="x_350">Mon outil de fusion préféré est
belaran@999 2935 <command moreinfo="none">kdiff3</command>, que j'utilise ici pour illustrer les
belaran@999 2936 fonctionnalités classiques des outils graphiques de fusion. Vous pouvez
belaran@999 2937 voir une capture d'écran de l'utilisation de <command moreinfo="none">kdiff3</command>
belaran@999 2938 dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil
belaran@999 2939 effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a
belaran@999 2940 trois différentes versions du fichier qui nous intéresse. Le fichier
belaran@999 2941 découpe la partie supérieure de la fenêtre en trois panneaux:</para>
belaran@999 2942 <itemizedlist>
belaran@999 2943 <listitem><para id="x_351">A gauche on la version de
belaran@999 2944 <emphasis>base</emphasis> du fichier, soit la plus récente version
belaran@999 2945 des deux versions qu'on souhaite fusionner.</para></listitem>
belaran@999 2946 <listitem><para id="x_352">Au centre, il y a <quote>notre</quote>
belaran@999 2947 version du fichier, avec le contenu que nous avons modifié.</para></listitem>
belaran@999 2948 <listitem><para id="x_353">Sur la droite, on trouve
belaran@999 2949 <quote>leur</quote> version du fichier, celui qui contient la
belaran@999 2950 révision que nous souhaitons intégré.</para>
belaran@999 2951 </listitem></itemizedlist>
belaran@999 2952 <para id="x_354">Dans le panneau en dessous, on trouve le
belaran@999 2953 <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche
belaran@999 2954 consiste donc à remplacement tous les textes en rouges,
belaran@999 2955 qui indiquent des conflits non résolus, avec une fusion manuelle et
belaran@999 2956 pertinente de <quote>notre</quote> version et de la <quote>leur</quote>.
belaran@999 2957 </para>
belaran@999 2958
belaran@999 2959 <para id="x_355">Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>,
belaran@999 2960 si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun
belaran@999 2961 d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs
belaran@999 2962 fichiers respectifs.</para>
belaran@999 2963
belaran@999 2964 <figure id="fig:tour-merge:kdiff3" float="0">
belaran@999 2965 <title>Utiliser <command moreinfo="none">kdiff3</command> pour fusionner les
belaran@999 2966 différentes version d'un fichier.</title>
belaran@999 2967 <mediaobject>
belaran@999 2968 <imageobject>
belaran@999 2969 <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject>
belaran@999 2970 <textobject>
belaran@999 2971 <phrase>XXX ajoute texte</phrase>
belaran@999 2972 </textobject>
belaran@999 2973 </mediaobject>
belaran@999 2974 </figure>
belaran@999 2975
belaran@999 2976 <para id="x_357">Pour chaque portion de fichier posant problème, nous
belaran@999 2977 pouvons choisir de résoudre le conflit en utilisant une combinaison de
belaran@999 2978 texte depuis la version de base, la notre, ou la leur. Nous pouvons
belaran@999 2979 aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para>
belaran@999 2980
belaran@999 2981 <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de
belaran@999 2982 fusion disponibles, bien trop pour en parler de tous ici. Leurs
belaran@999 2983 disponibilités varient selon les plate formes ainsi que leurs
belaran@999 2984 avantages et inconvénients. La plupart sont optimisé pour
belaran@999 2985 la fusion de fichier contenant un texte plat, certains sont spécialisé
belaran@999 2986 dans un format de fichier précis (généralement XML).</para>
belaran@999 2987 </sect2>
belaran@999 2988
belaran@999 2989 <sect2>
belaran@999 2990 <title>Un exemple concret</title>
belaran@999 2991
belaran@999 2992 <para id="x_359">Dans cet exemple, nous allons reproduire la
belaran@999 2993 modification de l'historique du fichier de la figure <xref linkend="fig:tour-merge:conflict"/> ci dessus. Commençons par créer
belaran@999 2994 un dépôt avec une version de base de notre document.</para>
belaran@999 2995
belaran@999 2996 <!-- BEGIN tour-merge-conflict.wife -->
belaran@999 2997 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
belaran@999 2998 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
belaran@999 2999 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Mariam Abacha, the wife of former</userinput>
belaran@999 3000 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
belaran@999 3001 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
belaran@999 3002 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add letter.txt</userinput>
belaran@999 3003 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, first draft'</userinput>
belaran@999 3004 </screen>
belaran@999 3005 <!-- END tour-merge-conflict.wife -->
belaran@999 3006
belaran@999 3007
belaran@999 3008 <para id="x_35a">Créons un clone de ce dépôt et faisons une
belaran@999 3009 modification dans le fichier.</para>
belaran@999 3010
belaran@999 3011 <!-- BEGIN tour-merge-conflict.cousin -->
belaran@999 3012 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 3013 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-cousin</userinput>
belaran@999 3014 updating working directory
belaran@999 3015 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 3016 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-cousin</userinput>
belaran@999 3017 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
belaran@999 3018 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
belaran@999 3019 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Shehu Musa Abacha, cousin to the former</userinput>
belaran@999 3020 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
belaran@999 3021 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
belaran@999 3022 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with cousin'</userinput>
belaran@999 3023 </screen>
belaran@999 3024 <!-- END tour-merge-conflict.cousin -->
belaran@999 3025
belaran@999 3026
belaran@999 3027 <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une
belaran@999 3028 modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
belaran@999 3029 de devoir effectuer des fusions (merges) avec vos propres travaux quand
belaran@999 3030 vous isolez les tâches dans des dépôts distincts. En effet, vous
belaran@999 3031 aurez alors à trouver et résoudre certains conflits).</para>
belaran@999 3032
belaran@999 3033 <!-- BEGIN tour-merge-conflict.son -->
belaran@999 3034 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 3035 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-son</userinput>
belaran@999 3036 updating working directory
belaran@999 3037 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 3038 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-son</userinput>
belaran@999 3039 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
belaran@999 3040 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
belaran@999 3041 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Alhaji Abba Abacha, son of the former</userinput>
belaran@999 3042 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
belaran@999 3043 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
belaran@999 3044 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with son'</userinput>
belaran@999 3045 </screen>
belaran@999 3046 <!-- END tour-merge-conflict.son -->
belaran@999 3047
belaran@999 3048
belaran@999 3049 <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont
belaran@999 3050 créées, nous allons configurer l'environnement de manière appropriée pour
belaran@999 3051 exécuter notre fusion (merge).</para>
belaran@999 3052
belaran@999 3053 <!-- BEGIN tour-merge-conflict.pull -->
belaran@999 3054 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 3055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam-cousin scam-merge</userinput>
belaran@999 3056 updating working directory
belaran@999 3057 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 3058 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-merge</userinput>
belaran@999 3059 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../scam-son</userinput>
belaran@999 3060 pulling from ../scam-son
belaran@999 3061 searching for changes
belaran@999 3062 adding changesets
belaran@999 3063 adding manifests
belaran@999 3064 adding file changes
belaran@999 3065 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 3066 not updating, since new heads added
belaran@999 3067 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 3068 </screen>
belaran@999 3069 <!-- END tour-merge-conflict.pull -->
belaran@999 3070
belaran@999 3071
belaran@999 3072 <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial
belaran@999 3073 habituelle <command moreinfo="none">hgmerge</command> pour effectuer le
belaran@999 3074 fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé
belaran@999 3075 pour utiliser un outil graphique. À la place, je vais définir la
belaran@999 3076 variable d'environnement <envar>HGMERGE</envar> pour indiquer à
belaran@999 3077 Mercurial d'utiliser la commande non-interactive <command moreinfo="none">merge</command>.
belaran@999 3078 Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>.
belaran@999 3079 Si vous exécutez cet exemple depuis votre ordinateur, ne vous
belaran@999 3080 occupez pas de définir <envar>HGMERGE</envar>.</para>
belaran@999 3081
belaran@999 3082 <!-- BEGIN tour-merge-conflict.merge -->
belaran@999 3083 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=merge</userinput>
belaran@999 3084 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 3085 merging letter.txt
belaran@999 3086 merge: warning: conflicts during merge
belaran@999 3087 merging letter.txt failed!
belaran@999 3088 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
belaran@999 3089 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
belaran@999 3090 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat letter.txt</userinput>
belaran@999 3091 Greetings!
belaran@999 3092 &lt;&lt;&lt;&lt;&lt;&lt;&lt; /tmp/tour-merge-conflictk3twLJ/scam-merge/letter.txt
belaran@999 3093 I am Shehu Musa Abacha, cousin to the former
belaran@999 3094 =======
belaran@999 3095 I am Alhaji Abba Abacha, son of the former
belaran@999 3096 &gt;&gt;&gt;&gt;&gt;&gt;&gt; /tmp/letter.txt~other.4O623C
belaran@999 3097 Nigerian dictator Sani Abacha.
belaran@999 3098 </screen>
belaran@999 3099 <!-- END tour-merge-conflict.merge -->
belaran@999 3100
belaran@999 3101
belaran@999 3102
belaran@999 3103 <para id="x_35f">Parce que <command moreinfo="none">merge</command> ne peut pas résoudre
belaran@999 3104 les modifications conflictuelles, il laisse des <emphasis>marqueurs de
belaran@999 3105 différences</emphasis> à l'intérieur du fichier qui a des conflits,
belaran@999 3106 indiquant clairement quelles lignes sont en conflits, et si elles
belaran@999 3107 viennent de notre fichier ou du fichier externe.
belaran@999 3108 </para>
belaran@999 3109
belaran@999 3110 <para id="x_360">Mercurial peut distinguer, à la manière dont la
belaran@999 3111 commande <command moreinfo="none">merge</command> se termine, qu'elle n'a pas été
belaran@999 3112 capable d'effectuer la fusion (merge), alors il nous indique que nous
belaran@999 3113 devons effectuer de nouveau cette opération. Ceci peut être très utile
belaran@999 3114 si, par exemple, nous exécutons un outil graphique de fusion et que
belaran@999 3115 nous le quittons sans nous rendre compte qu'il reste des conflits ou
belaran@999 3116 simplement par erreur.</para>
belaran@999 3117
belaran@999 3118 <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue,
belaran@999 3119 il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en
belaran@999 3120 modifiant nous même les fichiers, et enfin effectuer le "commit" du
belaran@999 3121 fichier:</para>
belaran@999 3122
belaran@999 3123 <!-- BEGIN tour-merge-conflict.commit -->
belaran@999 3124 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
belaran@999 3125 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
belaran@999 3126 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Bryan O'Sullivan, no relation of the former</userinput>
belaran@999 3127 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
belaran@999 3128 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
belaran@999 3129 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -m letter.txt</userinput>
belaran@999 3130 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Send me your money'</userinput>
belaran@999 3131 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 3132 changeset: 3:0954bda76c6b
belaran@999 3133 tag: tip
belaran@999 3134 parent: 1:1ac156b6e708
belaran@999 3135 parent: 2:7ee20631b33b
belaran@999 3136 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 3137 date: Sun Aug 16 14:05:34 2009 +0000
belaran@999 3138 summary: Send me your money
belaran@999 3139
belaran@999 3140 </screen>
belaran@999 3141 <!-- END tour-merge-conflict.commit -->
belaran@999 3142
belaran@999 3143
belaran@999 3144 <note>
belaran@999 3145 <title>Où est la <command moreinfo="none">hg resolve</command> ?</title>
belaran@999 3146
belaran@999 3147 <para id="x_724">La commande <command moreinfo="none">hg resolve</command> a été
belaran@999 3148 introduit dans la version 1.1 de Mercurial, qui a été publié en
belaran@999 3149 décembre 2008. Si vous utilisez une version plus anciennne de
belaran@999 3150 Mercurial (exécutez la command <command moreinfo="none">hg version</command> pour en
belaran@999 3151 avoir le coeur net), cette commande ne sera pas disponible. Si votre
belaran@999 3152 version de Mercurial est plus ancienne que la 1.1, vous devriez très
belaran@999 3153 fortement considérer une mise à jour à une version plus récente avant
belaran@999 3154 d'essayer de régler des fusions complexes.</para>
belaran@999 3155 </note>
belaran@999 3156 </sect2>
belaran@999 3157 </sect1>
belaran@999 3158
belaran@999 3159 <sect1 id="sec:tour-merge:fetch">
belaran@999 3160 <title>Simplification de la séquence pull-merge-commit</title>
belaran@999 3161
belaran@999 3162 <para id="x_362">La procédure pour effectuer la fusion indiquée
belaran@999 3163 ci-dessus est simple, mais requiert le lancement de trois commandes à la
belaran@999 3164 suite.</para>
belaran@999 3165
belaran@999 3166 <programlisting format="linespecific">hg pull -u
belaran@999 3167 hg merge
belaran@999 3168 hg commit -m 'Merged remote changes'</programlisting>
belaran@999 3169
belaran@999 3170 <para id="x_363">Lors du "commit" final, vous devez également saisir un
belaran@999 3171 message, qui aura vraisemblablement assez peu d'intérêt.</para>
belaran@999 3172
belaran@999 3173 <para id="x_364">Il serait assez sympathique de pouvoir réduire le
belaran@999 3174 nombre d'opérations nécessaire, si possible. De fait Mercurial est
belaran@999 3175 fourni avec une extension appelé <literal role="hg-ext" moreinfo="none">fetch</literal>
belaran@999 3176 qui fait justement cela.</para>
belaran@999 3177
belaran@999 3178 <para id="x_365">Mercurial fourni un mécanisme d'extension flexible qui permet à chacun
belaran@999 3179 d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
belaran@999 3180 léger et facile à utiliser. Certains extensions ajoutent de nouvelles
belaran@999 3181 commandes que vous pouvez utiliser en ligne de commande, alors que
belaran@999 3182 d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des
belaran@999 3183 possibilités au serveur.</para>
belaran@999 3184
belaran@999 3185 <para id="x_366">L'extension <literal role="hg-ext" moreinfo="none">fetch</literal>
belaran@999 3186 ajoute une nouvelle commande nommée, sans surprise, <command role="hg-cmd" moreinfo="none">hg fetch</command>. Cette extension résulte en une
belaran@999 3187 combinaison de <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg update</command> and <command role="hg-cmd" moreinfo="none">hg
belaran@999 3188 merge</command>. Elle commence par récupérer les modifications d'un
belaran@999 3189 autre dépôt dans le dépôt courant. Si elle trouve que les
belaran@999 3190 modifications ajoutent une nouvelle "head", elle effectue un "merge",
belaran@999 3191 et ensuite "commit" le résultat du "merge" avec un message généré
belaran@999 3192 automatiquement. Si aucune "head" n'ont été ajouté, elle met à jour le
belaran@999 3193 répertoire de travail au niveau de la nouvelle révision tip.</para>
belaran@999 3194
belaran@999 3195 <para id="x_367">Activer l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> est facile. Modifiez votre <filename role="special" moreinfo="none">.hgrc</filename>, et soit allez à la section <literal role="rc-extensions" moreinfo="none">extensions</literal> soit créer une section
belaran@999 3196 <literal role="rc-extensions" moreinfo="none">extensions</literal>. Ensuite ajoutez
belaran@999 3197 une ligne qui consiste simplement en <quote>\Verb+fetch =</quote>.</para>
belaran@999 3198
belaran@999 3199 <programlisting format="linespecific">[extensions]
belaran@999 3200 fetch =</programlisting>
belaran@999 3201
belaran@999 3202 <para id="x_368">(Normalement, sur la partie droite de
belaran@999 3203 <quote><literal moreinfo="none">=</literal></quote> devrait apparaître le chemin de
belaran@999 3204 l'extension, mais étant donné que l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> fait partie de la distribution standard,
belaran@999 3205 Mercurial sait où la trouver.) </para>
belaran@999 3206
belaran@999 3207 </sect1>
belaran@999 3208
belaran@999 3209 <sect1>
belaran@999 3210 <title>Renommer, copier, et fusionner (merge)</title>
belaran@999 3211
belaran@999 3212 <para id="x_729">En cours de la vie d'un projet, nous allons souvent
belaran@999 3213 vouloir changer la disposition de ses fichiers et de ses répertoires.
belaran@999 3214 Ceci peut être aussi simple que de changer le nom d'un seul fichier,
belaran@999 3215 et aussi compliqué que de restructurer une hiérarchie entiere de fichier
belaran@999 3216 au sein du projet.</para>
belaran@999 3217
belaran@999 3218 <para id="x_72a">Mercurial permet de faire ce genre de modification de
belaran@999 3219 manière fluide, à condition de l'informer de ce que nous faisons. Si
belaran@999 3220 vous voulez renommenr un ficher, vous devriez utiliser les commande
belaran@999 3221 <command moreinfo="none">hg rename</command><footnote>
belaran@999 3222 <para id="x_72b">Si vous un utilisateur de Unix, vous serez content
belaran@999 3223 de savoir que la commande <command moreinfo="none">hg rename</command> command
belaran@999 3224 peut être abrégée en <command moreinfo="none">hg mv</command>.</para>
belaran@999 3225 </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre
belaran@999 3226 la bonne décision, plus tard, en cas de fusionv (merge).</para>
belaran@999 3227
belaran@999 3228 <para id="x_72c">Nous étudierojns en détail l'utilisation de ces commandes,
belaran@999 3229 en détail, dans le chapitre <xref linkend="chap:daily.copy"/>.</para>
belaran@999 3230 </sect1>
belaran@999 3231 </chapter>
belaran@999 3232
belaran@999 3233 <!--
belaran@999 3234 local variables:
belaran@999 3235 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 3236 end:
belaran@999 3237 -->
belaran@999 3238
belaran@999 3239 <!-- BEGIN ch04 -->
belaran@999 3240 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 3241
belaran@999 3242 <chapter id="chap:concepts">
belaran@999 3243 <?dbhtml filename="behind-the-scenes.html"?>
belaran@999 3244 <title>Derrière le décor</title>
belaran@999 3245
belaran@999 3246 <para id="x_2e8">À la différence de beaucoup d'outils de gestion de versions,
belaran@999 3247 les concepts sur lesquels se base Mercurial sont assez simples pour
belaran@999 3248 qu'il soit facile de comprendre comment le logiciel fonctionne.
belaran@999 3249 Bien que leur connaissance ne soit pas nécéssaire, je trouve utile
belaran@999 3250 d'avoir un <quote>modèle mental</quote> de ce qui se passe.</para>
belaran@999 3251
belaran@999 3252 <para id="x_2e9">En effet, cette compréhension m'apporte la confiance que
belaran@999 3253 Mercurial a été développé avec soin pour être à la fois
belaran@999 3254 <emphasis>sûr</emphasis> et <emphasis>efficace</emphasis>. De surcroît,
belaran@999 3255 si il m'est facile de garder en tête ce que le logiciel fait lorsque
belaran@999 3256 j'accompli des tâches de révision, j'aurai moins de risques d'être
belaran@999 3257 surpris par son comportement.</para>
belaran@999 3258
belaran@999 3259 <para id="x_2ea">Dans ce chapitre, nous décrirons tout d'abord les concepts
belaran@999 3260 essentiels de l'architecture de Mercurial, pour ensuite discuter quelques
belaran@999 3261 uns des détails intéressants de son implémentation.</para>
belaran@999 3262
belaran@999 3263 <sect1>
belaran@999 3264 <title>Conservation de l'historique sous Mercurial</title>
belaran@999 3265 <sect2>
belaran@999 3266 <title>Suivi de l'historique pour un seul fichier</title>
belaran@999 3267
belaran@999 3268 <para id="x_2eb">Lorsque Mercurial effectue un suivi des modifications
belaran@999 3269 faites à un fichier, il conserve l'historique pour ce fichier dans un
belaran@999 3270 <emphasis>filelog</emphasis> sous forme de métadonnées. Chaque entrée
belaran@999 3271 dans le filelog contient assez d'informations pour reconstituer une
belaran@999 3272 révision du fichier correspondant. Les filelogs sont des fichiers
belaran@999 3273 stockés dans le répertoire <filename role="special" class="directory" moreinfo="none">.hg/store/data</filename>. Un filelog contient
belaran@999 3274 des informations de deux types: les données de révision, et un index
belaran@999 3275 pour permettre à Mercurial une recherche efficace d'une révision
belaran@999 3276 donnée.</para>
belaran@999 3277
belaran@999 3278 <para id="x_2ec">Lorsqu'un fichier devient trop gros ou a un long
belaran@999 3279 historique, son filelog se voit stocker dans un fichier de données
belaran@999 3280 (avec un suffixe <quote><literal moreinfo="none">.d</literal></quote>) et un fichier
belaran@999 3281 index (avec un suffixe<quote><literal moreinfo="none">.i</literal></quote>)
belaran@999 3282 distincts. La relation entre un fichier dans le répertoire de travail
belaran@999 3283 et le filelog couvrant le suivi de son historique dans le dépôt est
belaran@999 3284 illustré à la figure <xref linkend="fig:concepts:filelog"/>.</para>
belaran@999 3285
belaran@999 3286 <figure id="fig:concepts:filelog" float="0">
belaran@999 3287 <title>Relations entre les fichiers dans le répertoire de travail et
belaran@999 3288 leurs filelogs dans le dépôt</title>
belaran@999 3289 <mediaobject> <imageobject><imagedata fileref="figs/filelog.png"/></imageobject>
belaran@999 3290 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3291 </mediaobject> </figure>
belaran@999 3292
belaran@999 3293 </sect2>
belaran@999 3294 <sect2>
belaran@999 3295 <title>Gestion des fichiers suivis</title>
belaran@999 3296
belaran@999 3297 <para id="x_2ee">Mercurial a recours à une structure nommée
belaran@999 3298 <emphasis>manifest</emphasis> pour rassembler les informations sur
belaran@999 3299 les fichiers dont il gère le suivi. Chaque entrée dans ce manifest
belaran@999 3300 contient des informations sur les fichiers présents dans une révision
belaran@999 3301 donnée. Une entrée store la liste des fichiers faisant partie de la
belaran@999 3302 révision, la version de chaque fichier, et quelques autres
belaran@999 3303 métadonnées sur ces fichiers.</para>
belaran@999 3304
belaran@999 3305 </sect2>
belaran@999 3306 <sect2>
belaran@999 3307 <title>Recording changeset information</title>
belaran@999 3308
belaran@999 3309 <para id="x_2ef">The <emphasis>changelog</emphasis> contains
belaran@999 3310 information about each changeset. Each revision records who
belaran@999 3311 committed a change, the changeset comment, other pieces of
belaran@999 3312 changeset-related information, and the revision of the manifest to
belaran@999 3313 use.</para>
belaran@999 3314
belaran@999 3315 </sect2>
belaran@999 3316 <sect2>
belaran@999 3317 <title>Relationships between revisions</title>
belaran@999 3318
belaran@999 3319 <para id="x_2f0">Within a changelog, a manifest, or a filelog, each
belaran@999 3320 revision stores a pointer to its immediate parent (or to its
belaran@999 3321 two parents, if it's a merge revision). As I mentioned above,
belaran@999 3322 there are also relationships between revisions
belaran@999 3323 <emphasis>across</emphasis> these structures, and they are
belaran@999 3324 hierarchical in nature.</para>
belaran@999 3325
belaran@999 3326 <para id="x_2f1">For every changeset in a repository, there is exactly one
belaran@999 3327 revision stored in the changelog. Each revision of the
belaran@999 3328 changelog contains a pointer to a single revision of the
belaran@999 3329 manifest. A revision of the manifest stores a pointer to a
belaran@999 3330 single revision of each filelog tracked when that changeset
belaran@999 3331 was created. These relationships are illustrated in
belaran@999 3332 <xref linkend="fig:concepts:metadata"/>.</para>
belaran@999 3333
belaran@999 3334 <figure id="fig:concepts:metadata" float="0">
belaran@999 3335 <title>Metadata relationships</title>
belaran@999 3336 <mediaobject>
belaran@999 3337 <imageobject><imagedata fileref="figs/metadata.png"/></imageobject>
belaran@999 3338 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3339 </mediaobject>
belaran@999 3340 </figure>
belaran@999 3341
belaran@999 3342 <para id="x_2f3">As the illustration shows, there is
belaran@999 3343 <emphasis>not</emphasis> a <quote>one to one</quote>
belaran@999 3344 relationship between revisions in the changelog, manifest, or
belaran@999 3345 filelog. If a file that
belaran@999 3346 Mercurial tracks hasn't changed between two changesets, the
belaran@999 3347 entry for that file in the two revisions of the manifest will
belaran@999 3348 point to the same revision of its filelog<footnote>
belaran@999 3349 <para id="x_725">It is possible (though unusual) for the manifest to
belaran@999 3350 remain the same between two changesets, in which case the
belaran@999 3351 changelog entries for those changesets will point to the
belaran@999 3352 same revision of the manifest.</para>
belaran@999 3353 </footnote>.</para>
belaran@999 3354
belaran@999 3355 </sect2>
belaran@999 3356 </sect1>
belaran@999 3357 <sect1>
belaran@999 3358 <title>Safe, efficient storage</title>
belaran@999 3359
belaran@999 3360 <para id="x_2f4">The underpinnings of changelogs, manifests, and filelogs are
belaran@999 3361 provided by a single structure called the
belaran@999 3362 <emphasis>revlog</emphasis>.</para>
belaran@999 3363
belaran@999 3364 <sect2>
belaran@999 3365 <title>Efficient storage</title>
belaran@999 3366
belaran@999 3367 <para id="x_2f5">The revlog provides efficient storage of revisions using a
belaran@999 3368 <emphasis>delta</emphasis> mechanism. Instead of storing a
belaran@999 3369 complete copy of a file for each revision, it stores the
belaran@999 3370 changes needed to transform an older revision into the new
belaran@999 3371 revision. For many kinds of file data, these deltas are
belaran@999 3372 typically a fraction of a percent of the size of a full copy
belaran@999 3373 of a file.</para>
belaran@999 3374
belaran@999 3375 <para id="x_2f6">Some obsolete revision control systems can only work with
belaran@999 3376 deltas of text files. They must either store binary files as
belaran@999 3377 complete snapshots or encoded into a text representation, both
belaran@999 3378 of which are wasteful approaches. Mercurial can efficiently
belaran@999 3379 handle deltas of files with arbitrary binary contents; it
belaran@999 3380 doesn't need to treat text as special.</para>
belaran@999 3381
belaran@999 3382 </sect2>
belaran@999 3383 <sect2 id="sec:concepts:txn">
belaran@999 3384 <title>Safe operation</title>
belaran@999 3385
belaran@999 3386 <para id="x_2f7">Mercurial only ever <emphasis>appends</emphasis> data to
belaran@999 3387 the end of a revlog file. It never modifies a section of a
belaran@999 3388 file after it has written it. This is both more robust and
belaran@999 3389 efficient than schemes that need to modify or rewrite
belaran@999 3390 data.</para>
belaran@999 3391
belaran@999 3392 <para id="x_2f8">In addition, Mercurial treats every write as part of a
belaran@999 3393 <emphasis>transaction</emphasis> that can span a number of
belaran@999 3394 files. A transaction is <emphasis>atomic</emphasis>: either
belaran@999 3395 the entire transaction succeeds and its effects are all
belaran@999 3396 visible to readers in one go, or the whole thing is undone.
belaran@999 3397 This guarantee of atomicity means that if you're running two
belaran@999 3398 copies of Mercurial, where one is reading data and one is
belaran@999 3399 writing it, the reader will never see a partially written
belaran@999 3400 result that might confuse it.</para>
belaran@999 3401
belaran@999 3402 <para id="x_2f9">The fact that Mercurial only appends to files makes it
belaran@999 3403 easier to provide this transactional guarantee. The easier it
belaran@999 3404 is to do stuff like this, the more confident you should be
belaran@999 3405 that it's done correctly.</para>
belaran@999 3406
belaran@999 3407 </sect2>
belaran@999 3408 <sect2>
belaran@999 3409 <title>Fast retrieval</title>
belaran@999 3410
belaran@999 3411 <para id="x_2fa">Mercurial cleverly avoids a pitfall common to
belaran@999 3412 all earlier revision control systems: the problem of
belaran@999 3413 <emphasis>inefficient retrieval</emphasis>. Most revision
belaran@999 3414 control systems store the contents of a revision as an
belaran@999 3415 incremental series of modifications against a
belaran@999 3416 <quote>snapshot</quote>. (Some base the snapshot on the
belaran@999 3417 oldest revision, others on the newest.) To reconstruct a
belaran@999 3418 specific revision, you must first read the snapshot, and then
belaran@999 3419 every one of the revisions between the snapshot and your
belaran@999 3420 target revision. The more history that a file accumulates,
belaran@999 3421 the more revisions you must read, hence the longer it takes to
belaran@999 3422 reconstruct a particular revision.</para>
belaran@999 3423
belaran@999 3424 <figure id="fig:concepts:snapshot" float="0">
belaran@999 3425 <title>Snapshot of a revlog, with incremental deltas</title>
belaran@999 3426 <mediaobject>
belaran@999 3427 <imageobject><imagedata fileref="figs/snapshot.png"/></imageobject>
belaran@999 3428 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3429 </mediaobject>
belaran@999 3430 </figure>
belaran@999 3431
belaran@999 3432 <para id="x_2fc">The innovation that Mercurial applies to this problem is
belaran@999 3433 simple but effective. Once the cumulative amount of delta
belaran@999 3434 information stored since the last snapshot exceeds a fixed
belaran@999 3435 threshold, it stores a new snapshot (compressed, of course),
belaran@999 3436 instead of another delta. This makes it possible to
belaran@999 3437 reconstruct <emphasis>any</emphasis> revision of a file
belaran@999 3438 quickly. This approach works so well that it has since been
belaran@999 3439 copied by several other revision control systems.</para>
belaran@999 3440
belaran@999 3441 <para id="x_2fd"><xref linkend="fig:concepts:snapshot"/> illustrates
belaran@999 3442 the idea. In an entry in a revlog's index file, Mercurial
belaran@999 3443 stores the range of entries from the data file that it must
belaran@999 3444 read to reconstruct a particular revision.</para>
belaran@999 3445
belaran@999 3446 <sect3>
belaran@999 3447 <title>Aside: the influence of video compression</title>
belaran@999 3448
belaran@999 3449 <para id="x_2fe">If you're familiar with video compression or
belaran@999 3450 have ever watched a TV feed through a digital cable or
belaran@999 3451 satellite service, you may know that most video compression
belaran@999 3452 schemes store each frame of video as a delta against its
belaran@999 3453 predecessor frame.</para>
belaran@999 3454
belaran@999 3455 <para id="x_2ff">Mercurial borrows this idea to make it
belaran@999 3456 possible to reconstruct a revision from a snapshot and a
belaran@999 3457 small number of deltas.</para>
belaran@999 3458
belaran@999 3459 </sect3>
belaran@999 3460 </sect2>
belaran@999 3461 <sect2>
belaran@999 3462 <title>Identification and strong integrity</title>
belaran@999 3463
belaran@999 3464 <para id="x_300">Along with delta or snapshot information, a revlog entry
belaran@999 3465 contains a cryptographic hash of the data that it represents.
belaran@999 3466 This makes it difficult to forge the contents of a revision,
belaran@999 3467 and easy to detect accidental corruption.</para>
belaran@999 3468
belaran@999 3469 <para id="x_301">Hashes provide more than a mere check against corruption;
belaran@999 3470 they are used as the identifiers for revisions. The changeset
belaran@999 3471 identification hashes that you see as an end user are from
belaran@999 3472 revisions of the changelog. Although filelogs and the
belaran@999 3473 manifest also use hashes, Mercurial only uses these behind the
belaran@999 3474 scenes.</para>
belaran@999 3475
belaran@999 3476 <para id="x_302">Mercurial verifies that hashes are correct when it
belaran@999 3477 retrieves file revisions and when it pulls changes from
belaran@999 3478 another repository. If it encounters an integrity problem, it
belaran@999 3479 will complain and stop whatever it's doing.</para>
belaran@999 3480
belaran@999 3481 <para id="x_303">In addition to the effect it has on retrieval efficiency,
belaran@999 3482 Mercurial's use of periodic snapshots makes it more robust
belaran@999 3483 against partial data corruption. If a revlog becomes partly
belaran@999 3484 corrupted due to a hardware error or system bug, it's often
belaran@999 3485 possible to reconstruct some or most revisions from the
belaran@999 3486 uncorrupted sections of the revlog, both before and after the
belaran@999 3487 corrupted section. This would not be possible with a
belaran@999 3488 delta-only storage model.</para>
belaran@999 3489 </sect2>
belaran@999 3490 </sect1>
belaran@999 3491
belaran@999 3492 <sect1>
belaran@999 3493 <title>Revision history, branching, and merging</title>
belaran@999 3494
belaran@999 3495 <para id="x_304">Every entry in a Mercurial revlog knows the identity of its
belaran@999 3496 immediate ancestor revision, usually referred to as its
belaran@999 3497 <emphasis>parent</emphasis>. In fact, a revision contains room
belaran@999 3498 for not one parent, but two. Mercurial uses a special hash,
belaran@999 3499 called the <quote>null ID</quote>, to represent the idea
belaran@999 3500 <quote>there is no parent here</quote>. This hash is simply a
belaran@999 3501 string of zeroes.</para>
belaran@999 3502
belaran@999 3503 <para id="x_305">In <xref linkend="fig:concepts:revlog"/>, you can see
belaran@999 3504 an example of the conceptual structure of a revlog. Filelogs,
belaran@999 3505 manifests, and changelogs all have this same structure; they
belaran@999 3506 differ only in the kind of data stored in each delta or
belaran@999 3507 snapshot.</para>
belaran@999 3508
belaran@999 3509 <para id="x_306">The first revision in a revlog (at the bottom of the image)
belaran@999 3510 has the null ID in both of its parent slots. For a
belaran@999 3511 <quote>normal</quote> revision, its first parent slot contains
belaran@999 3512 the ID of its parent revision, and its second contains the null
belaran@999 3513 ID, indicating that the revision has only one real parent. Any
belaran@999 3514 two revisions that have the same parent ID are branches. A
belaran@999 3515 revision that represents a merge between branches has two normal
belaran@999 3516 revision IDs in its parent slots.</para>
belaran@999 3517
belaran@999 3518 <figure id="fig:concepts:revlog" float="0">
belaran@999 3519 <title>The conceptual structure of a revlog</title>
belaran@999 3520 <mediaobject>
belaran@999 3521 <imageobject><imagedata fileref="figs/revlog.png"/></imageobject>
belaran@999 3522 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3523 </mediaobject>
belaran@999 3524 </figure>
belaran@999 3525
belaran@999 3526 </sect1>
belaran@999 3527 <sect1>
belaran@999 3528 <title>The working directory</title>
belaran@999 3529
belaran@999 3530 <para id="x_307">In the working directory, Mercurial stores a snapshot of the
belaran@999 3531 files from the repository as of a particular changeset.</para>
belaran@999 3532
belaran@999 3533 <para id="x_308">The working directory <quote>knows</quote> which changeset
belaran@999 3534 it contains. When you update the working directory to contain a
belaran@999 3535 particular changeset, Mercurial looks up the appropriate
belaran@999 3536 revision of the manifest to find out which files it was tracking
belaran@999 3537 at the time that changeset was committed, and which revision of
belaran@999 3538 each file was then current. It then recreates a copy of each of
belaran@999 3539 those files, with the same contents it had when the changeset
belaran@999 3540 was committed.</para>
belaran@999 3541
belaran@999 3542 <para id="x_309">The <emphasis>dirstate</emphasis> is a special
belaran@999 3543 structure that contains Mercurial's knowledge of the working
belaran@999 3544 directory. It is maintained as a file named
belaran@999 3545 <filename moreinfo="none">.hg/dirstate</filename> inside a repository. The
belaran@999 3546 dirstate details which changeset the working directory is
belaran@999 3547 updated to, and all of the files that Mercurial is tracking in
belaran@999 3548 the working directory. It also lets Mercurial quickly notice
belaran@999 3549 changed files, by recording their checkout times and
belaran@999 3550 sizes.</para>
belaran@999 3551
belaran@999 3552 <para id="x_30a">Just as a revision of a revlog has room for two parents, so
belaran@999 3553 that it can represent either a normal revision (with one parent)
belaran@999 3554 or a merge of two earlier revisions, the dirstate has slots for
belaran@999 3555 two parents. When you use the <command role="hg-cmd" moreinfo="none">hg
belaran@999 3556 update</command> command, the changeset that you update to is
belaran@999 3557 stored in the <quote>first parent</quote> slot, and the null ID
belaran@999 3558 in the second. When you <command role="hg-cmd" moreinfo="none">hg
belaran@999 3559 merge</command> with another changeset, the first parent
belaran@999 3560 remains unchanged, and the second parent is filled in with the
belaran@999 3561 changeset you're merging with. The <command role="hg-cmd" moreinfo="none">hg
belaran@999 3562 parents</command> command tells you what the parents of the
belaran@999 3563 dirstate are.</para>
belaran@999 3564
belaran@999 3565 <sect2>
belaran@999 3566 <title>What happens when you commit</title>
belaran@999 3567
belaran@999 3568 <para id="x_30b">The dirstate stores parent information for more than just
belaran@999 3569 book-keeping purposes. Mercurial uses the parents of the
belaran@999 3570 dirstate as <emphasis>the parents of a new
belaran@999 3571 changeset</emphasis> when you perform a commit.</para>
belaran@999 3572
belaran@999 3573 <figure id="fig:concepts:wdir" float="0">
belaran@999 3574 <title>The working directory can have two parents</title>
belaran@999 3575 <mediaobject>
belaran@999 3576 <imageobject><imagedata fileref="figs/wdir.png"/></imageobject>
belaran@999 3577 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3578 </mediaobject>
belaran@999 3579 </figure>
belaran@999 3580
belaran@999 3581 <para id="x_30d"><xref linkend="fig:concepts:wdir"/> shows the
belaran@999 3582 normal state of the working directory, where it has a single
belaran@999 3583 changeset as parent. That changeset is the
belaran@999 3584 <emphasis>tip</emphasis>, the newest changeset in the
belaran@999 3585 repository that has no children.</para>
belaran@999 3586
belaran@999 3587 <figure id="fig:concepts:wdir-after-commit" float="0">
belaran@999 3588 <title>The working directory gains new parents after a
belaran@999 3589 commit</title>
belaran@999 3590 <mediaobject>
belaran@999 3591 <imageobject><imagedata fileref="figs/wdir-after-commit.png"/></imageobject>
belaran@999 3592 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3593 </mediaobject>
belaran@999 3594 </figure>
belaran@999 3595
belaran@999 3596 <para id="x_30f">It's useful to think of the working directory as
belaran@999 3597 <quote>the changeset I'm about to commit</quote>. Any files
belaran@999 3598 that you tell Mercurial that you've added, removed, renamed,
belaran@999 3599 or copied will be reflected in that changeset, as will
belaran@999 3600 modifications to any files that Mercurial is already tracking;
belaran@999 3601 the new changeset will have the parents of the working
belaran@999 3602 directory as its parents.</para>
belaran@999 3603
belaran@999 3604 <para id="x_310">After a commit, Mercurial will update the
belaran@999 3605 parents of the working directory, so that the first parent is
belaran@999 3606 the ID of the new changeset, and the second is the null ID.
belaran@999 3607 This is shown in <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial
belaran@999 3608 doesn't touch any of the files in the working directory when
belaran@999 3609 you commit; it just modifies the dirstate to note its new
belaran@999 3610 parents.</para>
belaran@999 3611
belaran@999 3612 </sect2>
belaran@999 3613 <sect2>
belaran@999 3614 <title>Creating a new head</title>
belaran@999 3615
belaran@999 3616 <para id="x_311">It's perfectly normal to update the working directory to a
belaran@999 3617 changeset other than the current tip. For example, you might
belaran@999 3618 want to know what your project looked like last Tuesday, or
belaran@999 3619 you could be looking through changesets to see which one
belaran@999 3620 introduced a bug. In cases like this, the natural thing to do
belaran@999 3621 is update the working directory to the changeset you're
belaran@999 3622 interested in, and then examine the files in the working
belaran@999 3623 directory directly to see their contents as they were when you
belaran@999 3624 committed that changeset. The effect of this is shown in
belaran@999 3625 <xref linkend="fig:concepts:wdir-pre-branch"/>.</para>
belaran@999 3626
belaran@999 3627 <figure id="fig:concepts:wdir-pre-branch" float="0">
belaran@999 3628 <title>The working directory, updated to an older
belaran@999 3629 changeset</title>
belaran@999 3630 <mediaobject>
belaran@999 3631 <imageobject><imagedata fileref="figs/wdir-pre-branch.png"/></imageobject>
belaran@999 3632 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3633 </mediaobject>
belaran@999 3634 </figure>
belaran@999 3635
belaran@999 3636 <para id="x_313">Having updated the working directory to an
belaran@999 3637 older changeset, what happens if you make some changes, and
belaran@999 3638 then commit? Mercurial behaves in the same way as I outlined
belaran@999 3639 above. The parents of the working directory become the
belaran@999 3640 parents of the new changeset. This new changeset has no
belaran@999 3641 children, so it becomes the new tip. And the repository now
belaran@999 3642 contains two changesets that have no children; we call these
belaran@999 3643 <emphasis>heads</emphasis>. You can see the structure that
belaran@999 3644 this creates in <xref linkend="fig:concepts:wdir-branch"/>.</para>
belaran@999 3645
belaran@999 3646 <figure id="fig:concepts:wdir-branch" float="0">
belaran@999 3647 <title>After a commit made while synced to an older
belaran@999 3648 changeset</title>
belaran@999 3649 <mediaobject>
belaran@999 3650 <imageobject><imagedata fileref="figs/wdir-branch.png"/></imageobject>
belaran@999 3651 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3652 </mediaobject>
belaran@999 3653 </figure>
belaran@999 3654
belaran@999 3655 <note>
belaran@999 3656 <para id="x_315">If you're new to Mercurial, you should keep
belaran@999 3657 in mind a common <quote>error</quote>, which is to use the
belaran@999 3658 <command role="hg-cmd" moreinfo="none">hg pull</command> command without any
belaran@999 3659 options. By default, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 3660 pull</command> command <emphasis>does not</emphasis>
belaran@999 3661 update the working directory, so you'll bring new changesets
belaran@999 3662 into your repository, but the working directory will stay
belaran@999 3663 synced at the same changeset as before the pull. If you
belaran@999 3664 make some changes and commit afterwards, you'll thus create
belaran@999 3665 a new head, because your working directory isn't synced to
belaran@999 3666 whatever the current tip is. To combine the operation of a
belaran@999 3667 pull, followed by an update, run <command moreinfo="none">hg pull
belaran@999 3668 -u</command>.</para>
belaran@999 3669
belaran@999 3670 <para id="x_316">I put the word <quote>error</quote> in quotes
belaran@999 3671 because all that you need to do to rectify the situation
belaran@999 3672 where you created a new head by accident is
belaran@999 3673 <command role="hg-cmd" moreinfo="none">hg merge</command>, then <command role="hg-cmd" moreinfo="none">hg commit</command>. In other words, this
belaran@999 3674 almost never has negative consequences; it's just something
belaran@999 3675 of a surprise for newcomers. I'll discuss other ways to
belaran@999 3676 avoid this behavior, and why Mercurial behaves in this
belaran@999 3677 initially surprising way, later on.</para>
belaran@999 3678 </note>
belaran@999 3679
belaran@999 3680 </sect2>
belaran@999 3681 <sect2>
belaran@999 3682 <title>Merging changes</title>
belaran@999 3683
belaran@999 3684 <para id="x_317">When you run the <command role="hg-cmd" moreinfo="none">hg
belaran@999 3685 merge</command> command, Mercurial leaves the first parent
belaran@999 3686 of the working directory unchanged, and sets the second parent
belaran@999 3687 to the changeset you're merging with, as shown in <xref linkend="fig:concepts:wdir-merge"/>.</para>
belaran@999 3688
belaran@999 3689 <figure id="fig:concepts:wdir-merge" float="0">
belaran@999 3690 <title>Merging two heads</title>
belaran@999 3691 <mediaobject>
belaran@999 3692 <imageobject>
belaran@999 3693 <imagedata fileref="figs/wdir-merge.png"/>
belaran@999 3694 </imageobject>
belaran@999 3695 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 3696 </mediaobject>
belaran@999 3697 </figure>
belaran@999 3698
belaran@999 3699 <para id="x_319">Mercurial also has to modify the working directory, to
belaran@999 3700 merge the files managed in the two changesets. Simplified a
belaran@999 3701 little, the merging process goes like this, for every file in
belaran@999 3702 the manifests of both changesets.</para>
belaran@999 3703 <itemizedlist>
belaran@999 3704 <listitem><para id="x_31a">If neither changeset has modified a file, do
belaran@999 3705 nothing with that file.</para>
belaran@999 3706 </listitem>
belaran@999 3707 <listitem><para id="x_31b">If one changeset has modified a file, and the
belaran@999 3708 other hasn't, create the modified copy of the file in the
belaran@999 3709 working directory.</para>
belaran@999 3710 </listitem>
belaran@999 3711 <listitem><para id="x_31c">If one changeset has removed a file, and the
belaran@999 3712 other hasn't (or has also deleted it), delete the file
belaran@999 3713 from the working directory.</para>
belaran@999 3714 </listitem>
belaran@999 3715 <listitem><para id="x_31d">If one changeset has removed a file, but the
belaran@999 3716 other has modified the file, ask the user what to do: keep
belaran@999 3717 the modified file, or remove it?</para>
belaran@999 3718 </listitem>
belaran@999 3719 <listitem><para id="x_31e">If both changesets have modified a file,
belaran@999 3720 invoke an external merge program to choose the new
belaran@999 3721 contents for the merged file. This may require input from
belaran@999 3722 the user.</para>
belaran@999 3723 </listitem>
belaran@999 3724 <listitem><para id="x_31f">If one changeset has modified a file, and the
belaran@999 3725 other has renamed or copied the file, make sure that the
belaran@999 3726 changes follow the new name of the file.</para>
belaran@999 3727 </listitem></itemizedlist>
belaran@999 3728 <para id="x_320">There are more details—merging has plenty of corner
belaran@999 3729 cases—but these are the most common choices that are
belaran@999 3730 involved in a merge. As you can see, most cases are
belaran@999 3731 completely automatic, and indeed most merges finish
belaran@999 3732 automatically, without requiring your input to resolve any
belaran@999 3733 conflicts.</para>
belaran@999 3734
belaran@999 3735 <para id="x_321">When you're thinking about what happens when you commit
belaran@999 3736 after a merge, once again the working directory is <quote>the
belaran@999 3737 changeset I'm about to commit</quote>. After the <command role="hg-cmd" moreinfo="none">hg merge</command> command completes, the
belaran@999 3738 working directory has two parents; these will become the
belaran@999 3739 parents of the new changeset.</para>
belaran@999 3740
belaran@999 3741 <para id="x_322">Mercurial lets you perform multiple merges, but
belaran@999 3742 you must commit the results of each individual merge as you
belaran@999 3743 go. This is necessary because Mercurial only tracks two
belaran@999 3744 parents for both revisions and the working directory. While
belaran@999 3745 it would be technically feasible to merge multiple changesets
belaran@999 3746 at once, Mercurial avoids this for simplicity. With multi-way
belaran@999 3747 merges, the risks of user confusion, nasty conflict
belaran@999 3748 resolution, and making a terrible mess of a merge would grow
belaran@999 3749 intolerable.</para>
belaran@999 3750
belaran@999 3751 </sect2>
belaran@999 3752
belaran@999 3753 <sect2>
belaran@999 3754 <title>Merging and renames</title>
belaran@999 3755
belaran@999 3756 <para id="x_69a">A surprising number of revision control systems pay little
belaran@999 3757 or no attention to a file's <emphasis>name</emphasis> over
belaran@999 3758 time. For instance, it used to be common that if a file got
belaran@999 3759 renamed on one side of a merge, the changes from the other
belaran@999 3760 side would be silently dropped.</para>
belaran@999 3761
belaran@999 3762 <para id="x_69b">Mercurial records metadata when you tell it to perform a
belaran@999 3763 rename or copy. It uses this metadata during a merge to do the
belaran@999 3764 right thing in the case of a merge. For instance, if I rename
belaran@999 3765 a file, and you edit it without renaming it, when we merge our
belaran@999 3766 work the file will be renamed and have your edits
belaran@999 3767 applied.</para>
belaran@999 3768 </sect2>
belaran@999 3769 </sect1>
belaran@999 3770
belaran@999 3771 <sect1>
belaran@999 3772 <title>Other interesting design features</title>
belaran@999 3773
belaran@999 3774 <para id="x_323">In the sections above, I've tried to highlight some of the
belaran@999 3775 most important aspects of Mercurial's design, to illustrate that
belaran@999 3776 it pays careful attention to reliability and performance.
belaran@999 3777 However, the attention to detail doesn't stop there. There are
belaran@999 3778 a number of other aspects of Mercurial's construction that I
belaran@999 3779 personally find interesting. I'll detail a few of them here,
belaran@999 3780 separate from the <quote>big ticket</quote> items above, so that
belaran@999 3781 if you're interested, you can gain a better idea of the amount
belaran@999 3782 of thinking that goes into a well-designed system.</para>
belaran@999 3783
belaran@999 3784 <sect2>
belaran@999 3785 <title>Clever compression</title>
belaran@999 3786
belaran@999 3787 <para id="x_324">When appropriate, Mercurial will store both snapshots and
belaran@999 3788 deltas in compressed form. It does this by always
belaran@999 3789 <emphasis>trying to</emphasis> compress a snapshot or delta,
belaran@999 3790 but only storing the compressed version if it's smaller than
belaran@999 3791 the uncompressed version.</para>
belaran@999 3792
belaran@999 3793 <para id="x_325">This means that Mercurial does <quote>the right
belaran@999 3794 thing</quote> when storing a file whose native form is
belaran@999 3795 compressed, such as a <literal moreinfo="none">zip</literal> archive or a JPEG
belaran@999 3796 image. When these types of files are compressed a second
belaran@999 3797 time, the resulting file is usually bigger than the
belaran@999 3798 once-compressed form, and so Mercurial will store the plain
belaran@999 3799 <literal moreinfo="none">zip</literal> or JPEG.</para>
belaran@999 3800
belaran@999 3801 <para id="x_326">Deltas between revisions of a compressed file are usually
belaran@999 3802 larger than snapshots of the file, and Mercurial again does
belaran@999 3803 <quote>the right thing</quote> in these cases. It finds that
belaran@999 3804 such a delta exceeds the threshold at which it should store a
belaran@999 3805 complete snapshot of the file, so it stores the snapshot,
belaran@999 3806 again saving space compared to a naive delta-only
belaran@999 3807 approach.</para>
belaran@999 3808
belaran@999 3809 <sect3>
belaran@999 3810 <title>Network recompression</title>
belaran@999 3811
belaran@999 3812 <para id="x_327">When storing revisions on disk, Mercurial uses the
belaran@999 3813 <quote>deflate</quote> compression algorithm (the same one
belaran@999 3814 used by the popular <literal moreinfo="none">zip</literal> archive format),
belaran@999 3815 which balances good speed with a respectable compression
belaran@999 3816 ratio. However, when transmitting revision data over a
belaran@999 3817 network connection, Mercurial uncompresses the compressed
belaran@999 3818 revision data.</para>
belaran@999 3819
belaran@999 3820 <para id="x_328">If the connection is over HTTP, Mercurial recompresses
belaran@999 3821 the entire stream of data using a compression algorithm that
belaran@999 3822 gives a better compression ratio (the Burrows-Wheeler
belaran@999 3823 algorithm from the widely used <literal moreinfo="none">bzip2</literal>
belaran@999 3824 compression package). This combination of algorithm and
belaran@999 3825 compression of the entire stream (instead of a revision at a
belaran@999 3826 time) substantially reduces the number of bytes to be
belaran@999 3827 transferred, yielding better network performance over most
belaran@999 3828 kinds of network.</para>
belaran@999 3829
belaran@999 3830 <para id="x_329">If the connection is over
belaran@999 3831 <command moreinfo="none">ssh</command>, Mercurial
belaran@999 3832 <emphasis>doesn't</emphasis> recompress the stream, because
belaran@999 3833 <command moreinfo="none">ssh</command> can already do this itself. You can
belaran@999 3834 tell Mercurial to always use <command moreinfo="none">ssh</command>'s
belaran@999 3835 compression feature by editing the
belaran@999 3836 <filename moreinfo="none">.hgrc</filename> file in your home directory as
belaran@999 3837 follows.</para>
belaran@999 3838
belaran@999 3839 <programlisting format="linespecific">[ui]
belaran@999 3840 ssh = ssh -C</programlisting>
belaran@999 3841
belaran@999 3842 </sect3>
belaran@999 3843 </sect2>
belaran@999 3844 <sect2>
belaran@999 3845 <title>Read/write ordering and atomicity</title>
belaran@999 3846
belaran@999 3847 <para id="x_32a">Appending to files isn't the whole story when
belaran@999 3848 it comes to guaranteeing that a reader won't see a partial
belaran@999 3849 write. If you recall <xref linkend="fig:concepts:metadata"/>,
belaran@999 3850 revisions in the changelog point to revisions in the manifest,
belaran@999 3851 and revisions in the manifest point to revisions in filelogs.
belaran@999 3852 This hierarchy is deliberate.</para>
belaran@999 3853
belaran@999 3854 <para id="x_32b">A writer starts a transaction by writing filelog and
belaran@999 3855 manifest data, and doesn't write any changelog data until
belaran@999 3856 those are finished. A reader starts by reading changelog
belaran@999 3857 data, then manifest data, followed by filelog data.</para>
belaran@999 3858
belaran@999 3859 <para id="x_32c">Since the writer has always finished writing filelog and
belaran@999 3860 manifest data before it writes to the changelog, a reader will
belaran@999 3861 never read a pointer to a partially written manifest revision
belaran@999 3862 from the changelog, and it will never read a pointer to a
belaran@999 3863 partially written filelog revision from the manifest.</para>
belaran@999 3864
belaran@999 3865 </sect2>
belaran@999 3866 <sect2>
belaran@999 3867 <title>Concurrent access</title>
belaran@999 3868
belaran@999 3869 <para id="x_32d">The read/write ordering and atomicity guarantees mean that
belaran@999 3870 Mercurial never needs to <emphasis>lock</emphasis> a
belaran@999 3871 repository when it's reading data, even if the repository is
belaran@999 3872 being written to while the read is occurring. This has a big
belaran@999 3873 effect on scalability; you can have an arbitrary number of
belaran@999 3874 Mercurial processes safely reading data from a repository
belaran@999 3875 all at once, no matter whether it's being written to or
belaran@999 3876 not.</para>
belaran@999 3877
belaran@999 3878 <para id="x_32e">The lockless nature of reading means that if you're
belaran@999 3879 sharing a repository on a multi-user system, you don't need to
belaran@999 3880 grant other local users permission to
belaran@999 3881 <emphasis>write</emphasis> to your repository in order for
belaran@999 3882 them to be able to clone it or pull changes from it; they only
belaran@999 3883 need <emphasis>read</emphasis> permission. (This is
belaran@999 3884 <emphasis>not</emphasis> a common feature among revision
belaran@999 3885 control systems, so don't take it for granted! Most require
belaran@999 3886 readers to be able to lock a repository to access it safely,
belaran@999 3887 and this requires write permission on at least one directory,
belaran@999 3888 which of course makes for all kinds of nasty and annoying
belaran@999 3889 security and administrative problems.)</para>
belaran@999 3890
belaran@999 3891 <para id="x_32f">Mercurial uses locks to ensure that only one process can
belaran@999 3892 write to a repository at a time (the locking mechanism is safe
belaran@999 3893 even over filesystems that are notoriously hostile to locking,
belaran@999 3894 such as NFS). If a repository is locked, a writer will wait
belaran@999 3895 for a while to retry if the repository becomes unlocked, but
belaran@999 3896 if the repository remains locked for too long, the process
belaran@999 3897 attempting to write will time out after a while. This means
belaran@999 3898 that your daily automated scripts won't get stuck forever and
belaran@999 3899 pile up if a system crashes unnoticed, for example. (Yes, the
belaran@999 3900 timeout is configurable, from zero to infinity.)</para>
belaran@999 3901
belaran@999 3902 <sect3>
belaran@999 3903 <title>Safe dirstate access</title>
belaran@999 3904
belaran@999 3905 <para id="x_330">As with revision data, Mercurial doesn't take a lock to
belaran@999 3906 read the dirstate file; it does acquire a lock to write it.
belaran@999 3907 To avoid the possibility of reading a partially written copy
belaran@999 3908 of the dirstate file, Mercurial writes to a file with a
belaran@999 3909 unique name in the same directory as the dirstate file, then
belaran@999 3910 renames the temporary file atomically to
belaran@999 3911 <filename moreinfo="none">dirstate</filename>. The file named
belaran@999 3912 <filename moreinfo="none">dirstate</filename> is thus guaranteed to be
belaran@999 3913 complete, not partially written.</para>
belaran@999 3914
belaran@999 3915 </sect3>
belaran@999 3916 </sect2>
belaran@999 3917 <sect2>
belaran@999 3918 <title>Avoiding seeks</title>
belaran@999 3919
belaran@999 3920 <para id="x_331">Critical to Mercurial's performance is the avoidance of
belaran@999 3921 seeks of the disk head, since any seek is far more expensive
belaran@999 3922 than even a comparatively large read operation.</para>
belaran@999 3923
belaran@999 3924 <para id="x_332">This is why, for example, the dirstate is stored in a
belaran@999 3925 single file. If there were a dirstate file per directory that
belaran@999 3926 Mercurial tracked, the disk would seek once per directory.
belaran@999 3927 Instead, Mercurial reads the entire single dirstate file in
belaran@999 3928 one step.</para>
belaran@999 3929
belaran@999 3930 <para id="x_333">Mercurial also uses a <quote>copy on write</quote> scheme
belaran@999 3931 when cloning a repository on local storage. Instead of
belaran@999 3932 copying every revlog file from the old repository into the new
belaran@999 3933 repository, it makes a <quote>hard link</quote>, which is a
belaran@999 3934 shorthand way to say <quote>these two names point to the same
belaran@999 3935 file</quote>. When Mercurial is about to write to one of a
belaran@999 3936 revlog's files, it checks to see if the number of names
belaran@999 3937 pointing at the file is greater than one. If it is, more than
belaran@999 3938 one repository is using the file, so Mercurial makes a new
belaran@999 3939 copy of the file that is private to this repository.</para>
belaran@999 3940
belaran@999 3941 <para id="x_334">A few revision control developers have pointed out that
belaran@999 3942 this idea of making a complete private copy of a file is not
belaran@999 3943 very efficient in its use of storage. While this is true,
belaran@999 3944 storage is cheap, and this method gives the highest
belaran@999 3945 performance while deferring most book-keeping to the operating
belaran@999 3946 system. An alternative scheme would most likely reduce
belaran@999 3947 performance and increase the complexity of the software, but
belaran@999 3948 speed and simplicity are key to the <quote>feel</quote> of
belaran@999 3949 day-to-day use.</para>
belaran@999 3950
belaran@999 3951 </sect2>
belaran@999 3952 <sect2>
belaran@999 3953 <title>Other contents of the dirstate</title>
belaran@999 3954
belaran@999 3955 <para id="x_335">Because Mercurial doesn't force you to tell it when you're
belaran@999 3956 modifying a file, it uses the dirstate to store some extra
belaran@999 3957 information so it can determine efficiently whether you have
belaran@999 3958 modified a file. For each file in the working directory, it
belaran@999 3959 stores the time that it last modified the file itself, and the
belaran@999 3960 size of the file at that time.</para>
belaran@999 3961
belaran@999 3962 <para id="x_336">When you explicitly <command role="hg-cmd" moreinfo="none">hg
belaran@999 3963 add</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>,
belaran@999 3964 <command role="hg-cmd" moreinfo="none">hg rename</command> or <command role="hg-cmd" moreinfo="none">hg copy</command> files, Mercurial updates the
belaran@999 3965 dirstate so that it knows what to do with those files when you
belaran@999 3966 commit.</para>
belaran@999 3967
belaran@999 3968 <para id="x_337">The dirstate helps Mercurial to efficiently
belaran@999 3969 check the status of files in a repository.</para>
belaran@999 3970
belaran@999 3971 <itemizedlist>
belaran@999 3972 <listitem>
belaran@999 3973 <para id="x_726">When Mercurial checks the state of a file in the
belaran@999 3974 working directory, it first checks a file's modification
belaran@999 3975 time against the time in the dirstate that records when
belaran@999 3976 Mercurial last wrote the file. If the last modified time
belaran@999 3977 is the same as the time when Mercurial wrote the file, the
belaran@999 3978 file must not have been modified, so Mercurial does not
belaran@999 3979 need to check any further.</para>
belaran@999 3980 </listitem>
belaran@999 3981 <listitem>
belaran@999 3982 <para id="x_727">If the file's size has changed, the file must have
belaran@999 3983 been modified. If the modification time has changed, but
belaran@999 3984 the size has not, only then does Mercurial need to
belaran@999 3985 actually read the contents of the file to see if it has
belaran@999 3986 changed.</para>
belaran@999 3987 </listitem>
belaran@999 3988 </itemizedlist>
belaran@999 3989
belaran@999 3990 <para id="x_728">Storing the modification time and size dramatically
belaran@999 3991 reduces the number of read operations that Mercurial needs to
belaran@999 3992 perform when we run commands like <command moreinfo="none">hg status</command>.
belaran@999 3993 This results in large performance improvements.</para>
belaran@999 3994 </sect2>
belaran@999 3995 </sect1>
belaran@999 3996 </chapter>
belaran@999 3997
belaran@999 3998 <!--
belaran@999 3999 local variables:
belaran@999 4000 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 4001 end:
belaran@999 4002 -->
belaran@999 4003
belaran@999 4004 <!-- BEGIN ch05 -->
belaran@999 4005 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 4006
belaran@999 4007 <chapter id="chap:daily">
belaran@999 4008 <?dbhtml filename="mercurial-in-daily-use.html"?>
belaran@999 4009 <title>Mercurial pour une utilisation de tous les jours</title>
belaran@999 4010
belaran@999 4011 <sect1>
belaran@999 4012 <title>Informer Mercurial des fichier à suivre</title>
belaran@999 4013
belaran@999 4014 <para id="x_1a3">Mercurial ne suit pas les fichiers de votre dépôt tant
belaran@999 4015 que vous ne lui avez pas dit de les gérer. La commande <command role="hg-cmd" moreinfo="none">hg status</command> vous dira quels fichiers sont
belaran@999 4016 inconnus de Mercurial. Il utilise un
belaran@999 4017 <quote><literal moreinfo="none">?</literal></quote> pour montrer ces fichiers.</para>
belaran@999 4018
belaran@999 4019 <para id="x_1a4">Pour informer Mercurial de suivre un fichier, utilisez
belaran@999 4020 la commande <command role="hg-cmd" moreinfo="none">hg add</command>. Une fois que vous
belaran@999 4021 avez ajouté un fichier, la ligne correspondante à ce fichier dans la
belaran@999 4022 sortie de <command role="hg-cmd" moreinfo="none">hg status</command> change de
belaran@999 4023 <quote><literal moreinfo="none">?</literal></quote> à
belaran@999 4024 <quote><literal moreinfo="none">A</literal></quote>.</para>
belaran@999 4025
belaran@999 4026 <!-- BEGIN daily.files.add -->
belaran@999 4027 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init add-example</userinput>
belaran@999 4028 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd add-example</userinput>
belaran@999 4029 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; myfile.txt</userinput>
belaran@999 4030 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4031 ? myfile.txt
belaran@999 4032 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile.txt</userinput>
belaran@999 4033 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4034 A myfile.txt
belaran@999 4035 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added one file'</userinput>
belaran@999 4036 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4037 </screen>
belaran@999 4038 <!-- END daily.files.add -->
belaran@999 4039
belaran@999 4040
belaran@999 4041 <para id="x_1a5">Après avoir exécuté un <command role="hg-cmd" moreinfo="none">hg
belaran@999 4042 commit</command>, les fichiers que vous avez ajoutés avant le commit
belaran@999 4043 ne seront plus listés dans la sortie de <command role="hg-cmd" moreinfo="none">hg
belaran@999 4044 status</command>. La raison de ceci est que, par défaut, <command role="hg-cmd" moreinfo="none">hg status</command> ne vous montre que les fichiers
belaran@999 4045 <quote>intéressants</quote> —ceux que vous avez (par exemple)
belaran@999 4046 modifiés, supprimés ou renommés. Si vous aviez un dépôt qui contient un
belaran@999 4047 millier de fichiers, vous ne voudriez certainement que rarement entendre
belaran@999 4048 parler des fichiers que Mercurial suit, mais qui n'ont pas changés.
belaran@999 4049 (Vous pouvez quand même avoir cette information, nous y reviendrons
belaran@999 4050 plus tard.)</para>
belaran@999 4051
belaran@999 4052 <para id="x_1a6">Une fois que vous ajoutez un fichier, Mercurial ne fait
belaran@999 4053 rien du tout avec celui-ci immédiatement. Au lieu de ça, il va prendre
belaran@999 4054 un "snapshot" de l'état du fichier la prochaine fois que vous
belaran@999 4055 exécuterez un commit. Il continuera ensuite à suivre les changements
belaran@999 4056 que vous avez fait au fichier chaque fois que vous committerez, et ce,
belaran@999 4057 jusqu'à ce que vous supprimiez le fichier.</para>
belaran@999 4058
belaran@999 4059 <sect2>
belaran@999 4060 <title>Nommage des fichiers explicite versus implicite</title>
belaran@999 4061
belaran@999 4062 <para id="x_1a7">Un comportement utile que Mercurial possède est que si
belaran@999 4063 vous passez le nom d'un répertoire à une commande, toute commande
belaran@999 4064 Mercurial la traitera comme : <quote>Je veux opérer sur chaque fichier
belaran@999 4065 dans ce répertoire et ses sous-répertoires</quote>.</para>
belaran@999 4066
belaran@999 4067 <!-- BEGIN daily.files.add-dir -->
belaran@999 4068 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
belaran@999 4069 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/somefile.txt</userinput>
belaran@999 4070 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c &gt; b/source.cpp</userinput>
belaran@999 4071 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b/d</userinput>
belaran@999 4072 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo d &gt; b/d/test.h</userinput>
belaran@999 4073 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput>
belaran@999 4074 adding b/d/test.h
belaran@999 4075 adding b/somefile.txt
belaran@999 4076 adding b/source.cpp
belaran@999 4077 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added all files in subdirectory'</userinput>
belaran@999 4078 </screen>
belaran@999 4079 <!-- END daily.files.add-dir -->
belaran@999 4080
belaran@999 4081
belaran@999 4082 <para id="x_1a8">Remarquez que dans cet exemple, Mercurial affiche le
belaran@999 4083 nom des fichiers qu'il a ajouté, alors qu'il ne l'a pas fait lorsque
belaran@999 4084 nous avons ajouté le fichier nommé <filename moreinfo="none">myfile.txt</filename>
belaran@999 4085 dans l'exemple précédent.</para>
belaran@999 4086
belaran@999 4087 <para id="x_1a9">Ce qu'il se passe est que dans le premier cas, nous
belaran@999 4088 avons nommé explicitement le fichier à ajouter sur la ligne de
belaran@999 4089 commande. Ce que Mercurial suppose dans ce cas est que nous savons ce
belaran@999 4090 que nous faisons, il n'affiche donc rien en sortie.</para>
belaran@999 4091
belaran@999 4092 <para id="x_1aa">Cependant, lorsque nous avons
belaran@999 4093 <emphasis>implicitement</emphasis> donné les fichiers à l'aide du nom
belaran@999 4094 d'un répertoire, Mercurial prend l'initiative d'afficher le nom de
belaran@999 4095 chaque fichier avec lequel il fait quelque chose. Ceci clarifie ce
belaran@999 4096 qu'il se passe et réduit la probabilité d'une mauvaise surprise
belaran@999 4097 restée silencieuse. Ce comportement est commun à la plupart des
belaran@999 4098 commandes Mercurial.</para>
belaran@999 4099 </sect2>
belaran@999 4100 <sect2>
belaran@999 4101 <title>Mercurial suit les fichiers, pas les répertoires</title>
belaran@999 4102
belaran@999 4103 <para id="x_1ab">Mercurial ne suit pas les informations sur les
belaran@999 4104 répertoires. En contrepartie, il suit le chemin vers un fichier. Avant
belaran@999 4105 de créer un fichier, il crée au préalable les répertoires manquants
belaran@999 4106 dans le chemin. Après avoir supprimé un fichier, il supprime chaque
belaran@999 4107 répertoire vide qui apparaît dans le chemin du fichier. Ceci apparaît
belaran@999 4108 comme une distinction triviale, cependant, cela a une conséquence
belaran@999 4109 pratique mineure : il n'est pas possible de représenter un répertoire
belaran@999 4110 totalement vide dans Mercurial.</para>
belaran@999 4111
belaran@999 4112 <para id="x_1ac">Les répertoires vides sont rarement utiles. Il existe
belaran@999 4113 cependant des solutions alternatives et non intrusives que vous
belaran@999 4114 pouvez utiliser pour obtenir l'effet approprié. Les développeurs de
belaran@999 4115 Mercurial ont ainsi pensé que la complexité requise pour gérer les
belaran@999 4116 répertoires n'était pas aussi importante que le bénéfice que cette
belaran@999 4117 fonctionnalité apporterait.</para>
belaran@999 4118
belaran@999 4119 <para id="x_1ad">Si vous avez besoin d'un répertoire vide dans votre
belaran@999 4120 dépôt, il existe quelques façons d'y arriver. L'une d'elles est de
belaran@999 4121 créer un répertoire et ensuite, de faire un <command role="hg-cmd" moreinfo="none">hg
belaran@999 4122 add</command> sur un fichier <quote>caché</quote> dans ce
belaran@999 4123 répertoire. Sur les systèmes de type Unix, tout fichier dont le nom
belaran@999 4124 commence avec un point (<quote><literal moreinfo="none">.</literal></quote>) est
belaran@999 4125 considéré comme caché par la plupart des commandes et outils
belaran@999 4126 graphiques. Cette approche est illustrée ci-après.</para>
belaran@999 4127
belaran@999 4128 <!-- BEGIN daily.files.hidden -->
belaran@999 4129 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hidden-example</userinput>
belaran@999 4130 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hidden-example</userinput>
belaran@999 4131 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir empty</userinput>
belaran@999 4132 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">touch empty/.hidden</userinput>
belaran@999 4133 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add empty/.hidden</userinput>
belaran@999 4134 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Manage an empty-looking directory'</userinput>
belaran@999 4135 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls empty</userinput>
belaran@999 4136 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 4137 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hidden-example tmp</userinput>
belaran@999 4138 updating working directory
belaran@999 4139 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4140 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp</userinput>
belaran@999 4141 empty
belaran@999 4142 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp/empty</userinput>
belaran@999 4143 </screen>
belaran@999 4144 <!-- END daily.files.hidden -->
belaran@999 4145
belaran@999 4146
belaran@999 4147 <para id="x_1ae">Une autre façon de s'attaquer au besoin d'un
belaran@999 4148 répertoire vide est de simplement d'en créer un dans vos scripts
belaran@999 4149 de construction avant qu'ils n'en aient le besoin.</para>
belaran@999 4150 </sect2>
belaran@999 4151 </sect1>
belaran@999 4152
belaran@999 4153 <sect1>
belaran@999 4154 <title>Comment arrêter de suivre un fichier</title>
belaran@999 4155
belaran@999 4156 <para id="x_1af">Une fois que vous décidez qu'un fichier n'appartient
belaran@999 4157 plus à votre dépôt, utilisez la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4158 remove</command>. Ceci supprime le fichier et informe Mercurial
belaran@999 4159 d'arrêter de le suivre (ce qui prendra effet lors du prochain commit).
belaran@999 4160 Un fichier supprimé est représenté dans la sortie de la commande
belaran@999 4161 <command role="hg-cmd" moreinfo="none">hg status</command> par un
belaran@999 4162 <quote><literal moreinfo="none">R</literal></quote>.</para>
belaran@999 4163
belaran@999 4164 <!-- BEGIN daily.files.remove -->
belaran@999 4165 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init remove-example</userinput>
belaran@999 4166 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd remove-example</userinput>
belaran@999 4167 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 4168 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
belaran@999 4169 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/b</userinput>
belaran@999 4170 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a b</userinput>
belaran@999 4171 adding b/b
belaran@999 4172 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Small example for file removal'</userinput>
belaran@999 4173 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove a</userinput>
belaran@999 4174 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4175 R a
belaran@999 4176 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove b</userinput>
belaran@999 4177 removing b/b
belaran@999 4178 </screen>
belaran@999 4179 <!-- END daily.files.remove -->
belaran@999 4180
belaran@999 4181
belaran@999 4182 <para id="x_1b0">Après avoir fait un <command role="hg-cmd" moreinfo="none">hg
belaran@999 4183 remove</command> sur un fichier, Mercurial ne suivra plus aucun
belaran@999 4184 changement sur ce fichier, même si vous recréez un fichier avec le même
belaran@999 4185 nom dans votre répertoire de travail. Si vous recréez un fichier avec le
belaran@999 4186 même nom et que vous désirez que Mercurial suive ce dernier, faite
belaran@999 4187 simplement un <command role="hg-cmd" moreinfo="none">hg add</command> sur celui-ci.
belaran@999 4188 Mercurial saura alors que le nouveau fichier ne fait pas référence à
belaran@999 4189 l'ancien fichier qui portait le même nom.</para>
belaran@999 4190
belaran@999 4191 <sect2>
belaran@999 4192 <title>Supprimer un fichier n'affecte pas son historique</title>
belaran@999 4193
belaran@999 4194 <para id="x_1b1">Il est important de comprendre que supprimer un fichier
belaran@999 4195 n'a que deux effets.</para>
belaran@999 4196
belaran@999 4197 <itemizedlist>
belaran@999 4198 <listitem><para id="x_1b2">Il supprime la version actuelle de ce
belaran@999 4199 fichier du répertoire de travail.</para>
belaran@999 4200 </listitem>
belaran@999 4201 <listitem><para id="x_1b3">Il arrête, à partir du prochain commit, le
belaran@999 4202 suivi de Mercurial sur les changements qui ont lieu sur ce
belaran@999 4203 fichier.</para>
belaran@999 4204 </listitem></itemizedlist>
belaran@999 4205
belaran@999 4206 <para id="x_1b4">Supprimer un fichier <emphasis>n'</emphasis>affecte en
belaran@999 4207 <emphasis>aucun</emphasis> cas l'<emphasis>historique</emphasis> du
belaran@999 4208 fichier.</para>
belaran@999 4209
belaran@999 4210 <para id="x_1b5">Si vous mettez à jour le répertoire de travail à un
belaran@999 4211 changeset qui a été committé alors que le fichier que vous venez de
belaran@999 4212 supprimer était encore suivi, ce fichier réapparaîtra dans le
belaran@999 4213 répertoire de travail, avec le contenu qu'il avait lorsque vous aviez
belaran@999 4214 committé ce changeset. Si vous mettez à jour (update) le répertoire de
belaran@999 4215 travail à un changeset ultérieur dans lequel le fichier a été
belaran@999 4216 supprimé, Mercurial supprimera une nouvelle fois le fichier du
belaran@999 4217 répertoire de travail.</para>
belaran@999 4218 </sect2>
belaran@999 4219
belaran@999 4220 <sect2>
belaran@999 4221 <title>Fichiers manquants</title>
belaran@999 4222
belaran@999 4223 <para id="x_1b6">Mercurial considère qu'un fichier que vous avez
belaran@999 4224 supprimé sans utiliser<command role="hg-cmd" moreinfo="none">hg remove</command>
belaran@999 4225 comme étant <emphasis>manquant</emphasis>. Un fichier manquant est
belaran@999 4226 représenté avec un <quote><literal moreinfo="none">!</literal></quote> en sortie de
belaran@999 4227 <command role="hg-cmd" moreinfo="none">hg status</command>.
belaran@999 4228 Les commandes Mercurial ne feront rien avec les fichiers
belaran@999 4229 manquants.</para>
belaran@999 4230
belaran@999 4231 <!-- BEGIN daily.files.missing -->
belaran@999 4232 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init missing-example</userinput>
belaran@999 4233 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd missing-example</userinput>
belaran@999 4234 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 4235 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
belaran@999 4236 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'File about to be missing'</userinput>
belaran@999 4237 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm a</userinput>
belaran@999 4238 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4239 ! a
belaran@999 4240 </screen>
belaran@999 4241 <!-- END daily.files.missing -->
belaran@999 4242
belaran@999 4243
belaran@999 4244 <para id="x_1b7">Si votre dépôt contient un fichier que <command role="hg-cmd" moreinfo="none">hg status</command> reporte comme manquant, et que
belaran@999 4245 vous voulez que ce fichier reste supprimé, vous pouvez exécuter
belaran@999 4246 <command role="hg-cmd" moreinfo="none">hg remove <option role="hg-opt-remove">--after</option></command> à tout moment
belaran@999 4247 pour dire à Mercurial que vous aviez bien voulu supprimer ce
belaran@999 4248 fichier.</para>
belaran@999 4249
belaran@999 4250 <!-- BEGIN daily.files.remove-after -->
belaran@999 4251 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove --after a</userinput>
belaran@999 4252 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4253 R a
belaran@999 4254 </screen>
belaran@999 4255 <!-- END daily.files.remove-after -->
belaran@999 4256
belaran@999 4257
belaran@999 4258 <para id="x_1b8">D'un autre coté, si vous avez supprimé le fichier
belaran@999 4259 manquant par accident, donnez à la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4260 revert</command> le nom du fichier à retrouver. Il réapparaitra dans
belaran@999 4261 sa forme non modifiée.</para>
belaran@999 4262
belaran@999 4263 <!-- BEGIN daily.files.recover-missing -->
belaran@999 4264 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert a</userinput>
belaran@999 4265 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat a</userinput>
belaran@999 4266 a
belaran@999 4267 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4268 </screen>
belaran@999 4269 <!-- END daily.files.recover-missing -->
belaran@999 4270
belaran@999 4271
belaran@999 4272 </sect2>
belaran@999 4273
belaran@999 4274 <sect2>
belaran@999 4275 <title>Entre nous : Pourquoi dire explicitement à Mercurial de supprimer un
belaran@999 4276 fichier ?</title>
belaran@999 4277
belaran@999 4278 <para id="x_1b9">Vous pourriez vous demander pourquoi il est nécessaire
belaran@999 4279 de dire explicitement à Mercurial que vous souhaitez supprimer un
belaran@999 4280 fichier. Au début du développement de Mercurial, celui ci vous
belaran@999 4281 laissait pourtant supprimer un fichier sans soucis ; Mercurial vous
belaran@999 4282 aurait automatiquement informé de l'absence du fichier lorsque vous
belaran@999 4283 auriez lancé un <command role="hg-cmd" moreinfo="none">hg commit</command> et arrêté
belaran@999 4284 de le suivre. En pratique, ceci a montré qu'il était trop facile de
belaran@999 4285 supprimer accidentellement un fichier sans le remarquer.</para>
belaran@999 4286 </sect2>
belaran@999 4287
belaran@999 4288 <sect2>
belaran@999 4289 <title>Raccourci utile—ajouter et supprimer des fichiers en une
belaran@999 4290 seule étape.</title>
belaran@999 4291
belaran@999 4292 <para id="x_1ba">Mercurial offre une commande combinée, <command role="hg-cmd" moreinfo="none">hg addremove</command>, qui ajoute les fichiers non
belaran@999 4293 suivis et marque les fichiers manquants comme supprimés.</para>
belaran@999 4294
belaran@999 4295 <!-- BEGIN daily.files.addremove -->
belaran@999 4296 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init addremove-example</userinput>
belaran@999 4297 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd addremove-example</userinput>
belaran@999 4298 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 4299 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
belaran@999 4300 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg addremove</userinput>
belaran@999 4301 adding a
belaran@999 4302 adding b
belaran@999 4303 </screen>
belaran@999 4304 <!-- END daily.files.addremove -->
belaran@999 4305
belaran@999 4306
belaran@999 4307 <para id="x_1bb">La commande <command role="hg-cmd" moreinfo="none">hg commit</command>
belaran@999 4308 fournit aussi une option <option role="hg-opt-commit">-A</option> qui
belaran@999 4309 exécute le même ajouter-et-supprimer, immédiatement suivi d'un
belaran@999 4310 commit.</para>
belaran@999 4311
belaran@999 4312 <!-- BEGIN daily.files.commit-addremove -->
belaran@999 4313 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c &gt; c</userinput>
belaran@999 4314 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Commit with addremove'</userinput>
belaran@999 4315 adding c
belaran@999 4316 </screen>
belaran@999 4317 <!-- END daily.files.commit-addremove -->
belaran@999 4318
belaran@999 4319
belaran@999 4320 </sect2>
belaran@999 4321 </sect1>
belaran@999 4322
belaran@999 4323 <sect1 id="chap:daily.copy">
belaran@999 4324 <title>Copier des fichiers</title>
belaran@999 4325
belaran@999 4326 <para id="x_1bc">Mercurial fournit une commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4327 copy</command> qui vous permet de faire une nouvelle copie d'un
belaran@999 4328 fichier. Lorsque vous copiez un fichier en utilisant cette commande,
belaran@999 4329 Mercurial crée un enregistrement du fait que ce nouveau fichier est une
belaran@999 4330 copie du fichier originel. Il traite ces fichiers copiés spécialement
belaran@999 4331 lorsque vous fusionnez (merge) votre travail avec quelqu'un
belaran@999 4332 d'autre.</para>
belaran@999 4333
belaran@999 4334 <sect2>
belaran@999 4335 <title>Les résultats d'une copie durant une fusion (merge)</title>
belaran@999 4336
belaran@999 4337 <para id="x_1bd">Ce qu'il se passe durant une fusion (merge) est que
belaran@999 4338 les changements <quote>suivent</quote> une copie. Pour illustrer ce
belaran@999 4339 que cela veut dire de la meilleure façon, créons un exemple. Nous
belaran@999 4340 allons commencer avec le mini dépôt usuel qui contient un simple
belaran@999 4341 fichier.</para>
belaran@999 4342
belaran@999 4343 <!-- BEGIN daily.copy.init -->
belaran@999 4344 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init my-copy</userinput>
belaran@999 4345 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput>
belaran@999 4346 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo line &gt; file</userinput>
belaran@999 4347 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file</userinput>
belaran@999 4348 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added a file'</userinput>
belaran@999 4349 </screen>
belaran@999 4350 <!-- END daily.copy.init -->
belaran@999 4351
belaran@999 4352
belaran@999 4353 <para id="x_1be">Nous devons faire du travail en parallèle, ainsi,
belaran@999 4354 nous aurons quelque chose à fusionner (merge). Donc clonons notre
belaran@999 4355 dépôt.</para>
belaran@999 4356
belaran@999 4357 <!-- BEGIN daily.copy.clone -->
belaran@999 4358 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 4359 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone my-copy your-copy</userinput>
belaran@999 4360 updating working directory
belaran@999 4361 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4362 </screen>
belaran@999 4363 <!-- END daily.copy.clone -->
belaran@999 4364
belaran@999 4365
belaran@999 4366 <para id="x_1bf">De retour dans notre dépôt initial, utilisons la
belaran@999 4367 commande <command role="hg-cmd" moreinfo="none">hg copy</command> pour faire une
belaran@999 4368 copie du premier fichier que nous avons créé.</para>
belaran@999 4369
belaran@999 4370 <!-- BEGIN daily.copy.copy -->
belaran@999 4371 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput>
belaran@999 4372 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput>
belaran@999 4373 </screen>
belaran@999 4374 <!-- END daily.copy.copy -->
belaran@999 4375
belaran@999 4376
belaran@999 4377 <para id="x_1c0">Si nous regardons ensuite à la sortie de la commande
belaran@999 4378 <command role="hg-cmd" moreinfo="none">hg status</command>, les fichiers copiés
belaran@999 4379 ont l'air de fichiers normalement ajoutés.</para>
belaran@999 4380
belaran@999 4381 <!-- BEGIN daily.copy.status -->
belaran@999 4382 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4383 A new-file
belaran@999 4384 </screen>
belaran@999 4385 <!-- END daily.copy.status -->
belaran@999 4386
belaran@999 4387
belaran@999 4388 <para id="x_1c1">Mais si nous passons l'option <option role="hg-opt-status">-C</option> à <command role="hg-cmd" moreinfo="none">hg
belaran@999 4389 status</command>, il affiche une autre ligne de sortie : il s'agit
belaran@999 4390 du fichier <emphasis>source</emphasis> pour notre copie.</para>
belaran@999 4391
belaran@999 4392 <!-- BEGIN daily.copy.status-copy -->
belaran@999 4393 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput>
belaran@999 4394 A new-file
belaran@999 4395 file
belaran@999 4396 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Copied file'</userinput>
belaran@999 4397 </screen>
belaran@999 4398 <!-- END daily.copy.status-copy -->
belaran@999 4399
belaran@999 4400
belaran@999 4401 <para id="x_1c2">Maintenant, de retour dans le dépôt que nous avons
belaran@999 4402 cloné, créons un changement en parallèle. Nous allons ajouter une
belaran@999 4403 ligne de contenu au fichier original qui a été créé.</para>
belaran@999 4404
belaran@999 4405 <!-- BEGIN daily.copy.other -->
belaran@999 4406 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../your-copy</userinput>
belaran@999 4407 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'new contents' &gt;&gt; file</userinput>
belaran@999 4408 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Changed file'</userinput>
belaran@999 4409 </screen>
belaran@999 4410 <!-- END daily.copy.other -->
belaran@999 4411
belaran@999 4412
belaran@999 4413 <para id="x_1c3">Nous avons alors un fichier <filename moreinfo="none">file</filename>
belaran@999 4414 modifié dans ce dépôt. Lorsque nous récupérons (pull) les changements
belaran@999 4415 depuis le premier répertoire et fusionnons (merge) les deux "heads",
belaran@999 4416 Mercurial propagera les changements que nous avons faits localement
belaran@999 4417 au fichier <filename moreinfo="none">file</filename> dans sa copie
belaran@999 4418 <filename moreinfo="none">new-file</filename>.</para>
belaran@999 4419
belaran@999 4420 <!-- BEGIN daily.copy.merge -->
belaran@999 4421 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-copy</userinput>
belaran@999 4422 pulling from ../my-copy
belaran@999 4423 searching for changes
belaran@999 4424 adding changesets
belaran@999 4425 adding manifests
belaran@999 4426 adding file changes
belaran@999 4427 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 4428 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 4429 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 4430 merging file and new-file to new-file
belaran@999 4431 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
belaran@999 4432 (branch merge, don't forget to commit)
belaran@999 4433 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat new-file</userinput>
belaran@999 4434 line
belaran@999 4435 new contents
belaran@999 4436 </screen>
belaran@999 4437 <!-- END daily.copy.merge -->
belaran@999 4438
belaran@999 4439
belaran@999 4440 </sect2>
belaran@999 4441 <sect2 id="sec:daily:why-copy">
belaran@999 4442 <title>Pourquoi est-ce que les changements devraient suivre les copies
belaran@999 4443 ?</title>
belaran@999 4444
belaran@999 4445 <para id="x_1c4">Ce comportement—des changements d'un fichiers
belaran@999 4446 qui se propagent aux copies de ce fichier—peut sembler
belaran@999 4447 ésotérique, mais, dans la plupart des cas, c'est hautement
belaran@999 4448 désirable.</para>
belaran@999 4449
belaran@999 4450 <para id="x_1c5">Pour commencer, souvenez vous que cette propagation
belaran@999 4451 a lieue <emphasis>seulement</emphasis> lors des fusions (merge).
belaran@999 4452 Donc, si vous faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur
belaran@999 4453 un fichier, et par la suite modifiez le fichier original durant le
belaran@999 4454 cours normal de votre travail, rien n'a lieu.</para>
belaran@999 4455
belaran@999 4456 <para id="x_1c6">La deuxième chose à savoir c'est que les modifications
belaran@999 4457 ne se propageront à travers une copie que si le changeset à partir
belaran@999 4458 duquel vous faites une fusion (merge) <emphasis>n'a pas encore
belaran@999 4459 vu</emphasis> la copie.</para>
belaran@999 4460
belaran@999 4461 <para id="x_1c7">La raison pour laquelle Mercurial fait ainsi est une
belaran@999 4462 règle. Imaginons que je corrige un important bug dans un fichier source
belaran@999 4463 et que je commit mes changements. Pendant ce temps, vous avez décidé de
belaran@999 4464 faire un <command role="hg-cmd" moreinfo="none">hg copy</command> du fichier dans
belaran@999 4465 votre dépôt, sans rien savoir au sujet du bug ou à propos de la
belaran@999 4466 correction. Vous avez alors commencé à "hacker" sur votre copie du
belaran@999 4467 fichier.</para>
belaran@999 4468
belaran@999 4469 <para id="x_1c8">Si vous aviez récupéré (pull) et fusionné (merge) mes
belaran@999 4470 changements, et que Mercurial <emphasis>n'avait pas</emphasis>
belaran@999 4471 propagé les changements à travers les copies, votre nouveau fichier
belaran@999 4472 source contiendrait maintenant le bug, et à moins que vous ne sachiez
belaran@999 4473 qu'il faille propager la correction du bug à la main, le bug aurait
belaran@999 4474 <emphasis>subsisté</emphasis> dans votre copie du fichier.</para>
belaran@999 4475
belaran@999 4476 <para id="x_1c9">En propageant automatiquement les changements qui
belaran@999 4477 fixent les bugs à partir du fichier original vers les copies,
belaran@999 4478 Mercurial prévient ce type de problèmes. A ma connaissance, Mercurial
belaran@999 4479 est le <emphasis>seul</emphasis> système de gestion de révisions qui
belaran@999 4480 propage les changements à travers les copies comme ceci.</para>
belaran@999 4481
belaran@999 4482 <para id="x_1ca">Une fois que votre historique des changements a un
belaran@999 4483 enregistrement concernant une copie et qu'une fusion postérieure a
belaran@999 4484 eu lieue, il n'y a d'habitude pas d'autre besoin de propager les
belaran@999 4485 changements du fichier originel vers le fichier copié. C'est pourquoi
belaran@999 4486 Mercurial ne propage les changements à travers les copies qu'à la
belaran@999 4487 première fusion, et pas d'avantage.</para>
belaran@999 4488 </sect2>
belaran@999 4489
belaran@999 4490 <sect2>
belaran@999 4491 <title>Comment faire des changements qui <emphasis>ne</emphasis>
belaran@999 4492 suivent <emphasis>pas</emphasis> une copie</title>
belaran@999 4493
belaran@999 4494 <para id="x_1cb">Si pour une raison ou une autre, vous décidez que
belaran@999 4495 cette fonctionnalité de propager automatiquement les changements à
belaran@999 4496 travers les copies n'est pas pour vous, utilisez simplement la
belaran@999 4497 commande normale de copie de votre système (sur les systèmes de type
belaran@999 4498 Unix, il s'agit de <command moreinfo="none">cp</command>) pour faire une copie d'un
belaran@999 4499 fichier. Utilisez ensuite <command role="hg-cmd" moreinfo="none">hg add</command>
belaran@999 4500 pour ajouter les nouveaux fichiers à la main. Cependant, avant d'en
belaran@999 4501 faire ainsi, relisez <xref linkend="sec:daily:why-copy"/>, et faites
belaran@999 4502 un choix en connaissance de cause comme quoi cette fonctionnalité
belaran@999 4503 n'est pas appropriée à votre cas spécifique.</para>
belaran@999 4504
belaran@999 4505 </sect2>
belaran@999 4506 <sect2>
belaran@999 4507 <title>Comportement de la commande <command role="hg-cmd" moreinfo="none">hg copy</command></title>
belaran@999 4508
belaran@999 4509 <para id="x_1cc">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg copy</command>, Mercurial crée une copie de chaque
belaran@999 4510 fichier source tel qu'il est actuellement dans le répertoire de
belaran@999 4511 travail. Cela signifie que si vous effectuez des modifications sur un
belaran@999 4512 fichier, puis faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur
belaran@999 4513 celui-ci sans avoir au préalable committé ces changements, la nouvelle
belaran@999 4514 copie contiendra aussi les modifications que vous avez fait jusqu'à
belaran@999 4515 ce point. (Je trouve ce comportement quelque peu contre intuitif,
belaran@999 4516 c'est pourquoi j'en fais mention ici.)</para>
belaran@999 4517 <!-- Vérifier que je n'ai pas fait de contre sens en relisant la
belaran@999 4518 version anglaise, ce que je comprend ici me paraît un peu bizarre -->
belaran@999 4519
belaran@999 4520 <para id="x_1cd">La commande <command role="hg-cmd" moreinfo="none">hg copy</command>
belaran@999 4521 agit comme la commande Unix <command moreinfo="none">cp</command> (vous pouvez
belaran@999 4522 utilisez l'alias <command role="hg-cmd" moreinfo="none">hg cp</command> si vous
belaran@999 4523 préférez). Nous devons lui donner deux ou plus arguments où le
belaran@999 4524 dernier est considéré comme la <emphasis>destination</emphasis>, et
belaran@999 4525 les autres comme les <emphasis>sources</emphasis>.</para>
belaran@999 4526
belaran@999 4527 <para id="x_685">Si vous passez à <command role="hg-cmd" moreinfo="none">hg
belaran@999 4528 copy</command> un seul fichier source, et que la destination
belaran@999 4529 n'existe pas, ceci créera un nouveau fichier avec ce nom.</para>
belaran@999 4530
belaran@999 4531 <!-- BEGIN daily.copy.simple -->
belaran@999 4532 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir k</userinput>
belaran@999 4533 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a k</userinput>
belaran@999 4534 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls k</userinput>
belaran@999 4535 a
belaran@999 4536 </screen>
belaran@999 4537 <!-- END daily.copy.simple -->
belaran@999 4538
belaran@999 4539
belaran@999 4540 <para id="x_1ce">Si la destination est un répertoire, Mercurial copie
belaran@999 4541 les sources dans ce répertoire.</para>
belaran@999 4542
belaran@999 4543 <!-- BEGIN daily.copy.dir-dest -->
belaran@999 4544 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir d</userinput>
belaran@999 4545 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a b d</userinput>
belaran@999 4546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls d</userinput>
belaran@999 4547 a b
belaran@999 4548 </screen>
belaran@999 4549 <!-- END daily.copy.dir-dest -->
belaran@999 4550
belaran@999 4551
belaran@999 4552 <para id="x_1cf">La copie de répertoire est récursive et préserve la
belaran@999 4553 structure du répertoire source.</para>
belaran@999 4554
belaran@999 4555 <!-- BEGIN daily.copy.dir-src -->
belaran@999 4556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z e</userinput>
belaran@999 4557 copying z/a/c to e/a/c
belaran@999 4558 </screen>
belaran@999 4559 <!-- END daily.copy.dir-src -->
belaran@999 4560
belaran@999 4561
belaran@999 4562 <para id="x_1d0">Si la source et la destination sont tous deux des
belaran@999 4563 répertoires, l'arborescence de la source est recréée dans le
belaran@999 4564 répertoire destination.</para>
belaran@999 4565
belaran@999 4566 <!-- BEGIN daily.copy.dir-src-dest -->
belaran@999 4567 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z d</userinput>
belaran@999 4568 copying z/a/c to d/z/a/c
belaran@999 4569 </screen>
belaran@999 4570 <!-- END daily.copy.dir-src-dest -->
belaran@999 4571
belaran@999 4572
belaran@999 4573 <para id="x_1d1">Comme avec la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4574 remove</command>, si vous copiez un fichier manuellement et voulez
belaran@999 4575 que Mercurial sache qu'il s'agit d'une copie, utilisez simplement
belaran@999 4576 l'option <option role="hg-opt-copy">--after</option> avec <command role="hg-cmd" moreinfo="none">hg copy</command>.</para>
belaran@999 4577
belaran@999 4578 <!-- BEGIN daily.copy.after -->
belaran@999 4579 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp a n</userinput>
belaran@999 4580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy --after a n</userinput>
belaran@999 4581 </screen>
belaran@999 4582 <!-- END daily.copy.after -->
belaran@999 4583
belaran@999 4584 </sect2>
belaran@999 4585 </sect1>
belaran@999 4586
belaran@999 4587 <sect1>
belaran@999 4588 <title>Renommer les fichiers</title>
belaran@999 4589
belaran@999 4590 <para id="x_1d2">Il est plus commun d'avoir besoin de renommer un
belaran@999 4591 fichier que d'en faire une copie. La raison pour laquelle j'ai discuté
belaran@999 4592 de la commande <command role="hg-cmd" moreinfo="none">hg copy</command> avant de parler
belaran@999 4593 de renommage des fichiers est que Mercurial traite les renommages
belaran@999 4594 essentiellement comme une copie. Ainsi, savoir comment Mercurial traite
belaran@999 4595 les copies de fichiers vous informe sur ce que vous êtes en droit
belaran@999 4596 d'attendre lorsque vous renommez un fichier.</para>
belaran@999 4597
belaran@999 4598 <para id="x_1d3">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg rename</command>, Mercurial crée une copie de tous
belaran@999 4599 les fichiers sources, les supprime et marque ces fichiers comme étant
belaran@999 4600 supprimés.</para>
belaran@999 4601
belaran@999 4602 <!-- BEGIN daily.rename.rename -->
belaran@999 4603 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput>
belaran@999 4604 </screen>
belaran@999 4605 <!-- END daily.rename.rename -->
belaran@999 4606
belaran@999 4607
belaran@999 4608 <para id="x_1d4">La commande <command role="hg-cmd" moreinfo="none">hg status</command>
belaran@999 4609 montre les nouveaux fichiers comme ajoutés et les fichiers originaux
belaran@999 4610 comme supprimés.</para>
belaran@999 4611
belaran@999 4612 <!-- BEGIN daily.rename.status -->
belaran@999 4613 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 4614 A b
belaran@999 4615 R a
belaran@999 4616 </screen>
belaran@999 4617 <!-- END daily.rename.status -->
belaran@999 4618
belaran@999 4619
belaran@999 4620 <para id="x_1d5">A cause du <command role="hg-cmd" moreinfo="none">hg copy</command>,
belaran@999 4621 nous devons utiliser l'option <option role="hg-opt-status">-C</option>
belaran@999 4622 pour la commande <command role="hg-cmd" moreinfo="none">hg status</command> afin
belaran@999 4623 d'observer que le fichier ajouté est bien suivi par Mercurial comme
belaran@999 4624 étant une copie de l'original maintenant supprimé.</para>
belaran@999 4625
belaran@999 4626 <!-- BEGIN daily.rename.status-copy -->
belaran@999 4627 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput>
belaran@999 4628 A b
belaran@999 4629 a
belaran@999 4630 R a
belaran@999 4631 </screen>
belaran@999 4632 <!-- END daily.rename.status-copy -->
belaran@999 4633
belaran@999 4634
belaran@999 4635 <para id="x_1d6">Comme avec <command role="hg-cmd" moreinfo="none">hg remove</command> et
belaran@999 4636 <command role="hg-cmd" moreinfo="none">hg copy</command>, vous pouvez informer
belaran@999 4637 Mercurial au sujet d'un renommage après coup en utilisant l'option
belaran@999 4638 <option role="hg-opt-rename">--after</option>. Dans le plus grand
belaran@999 4639 respect, le comportement de la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4640 rename</command>, et les options qu'il accepte sont similaires à la
belaran@999 4641 commande <command role="hg-cmd" moreinfo="none">hg copy</command>.</para>
belaran@999 4642
belaran@999 4643 <para id="x_686">Si vous êtes familier avec la ligne de commande Unix,
belaran@999 4644 vous serez heureux d'apprendre que la commande <command role="hg-cmd" moreinfo="none">hg rename</command> peut être invoquée par <command role="hg-cmd" moreinfo="none">hg mv</command>.</para>
belaran@999 4645
belaran@999 4646 <sect2>
belaran@999 4647 <title>Renommer les fichiers et fusionner (merge) les changements</title>
belaran@999 4648
belaran@999 4649 <para id="x_1d7">Puise que le "rename" de Mercurial est implanté comme un
belaran@999 4650 "copy-and-remove", la même propagation des changements a lieue après
belaran@999 4651 un "rename" qu'après un "copy" lorsque vous fusionnez (merge).</para>
belaran@999 4652
belaran@999 4653 <para id="x_1d8">Si je modifie un fichier et que vous le renommez, si
belaran@999 4654 ensuite nous fusionnons nos changements respectifs, mes modifications
belaran@999 4655 sur le fichier sous son nom originel seront propagés vers le même
belaran@999 4656 fichier sous son nouveau nom. (C'est quelque chose que vous pourriez
belaran@999 4657 espérer voir <quote>fonctionner simplement</quote>, mais tous les
belaran@999 4658 systèmes de gestion de version ne le font pas.)</para>
belaran@999 4659
belaran@999 4660 <para id="x_1d9">Tandis qu'avoir des changements qui suivent une copie
belaran@999 4661 est une fonctionnalité où vous hocheriez sûrement la tête en disant
belaran@999 4662 <quote>oui, cela pourrait être utile</quote>, il est clair que les
belaran@999 4663 voir suivre un renommage est définitivement important. Sans cette
belaran@999 4664 aptitude, il serait vraiment trop facile d'avoir des changements
belaran@999 4665 qui deviennent orphelins lorsque des fichiers sont renommés.</para>
belaran@999 4666 </sect2>
belaran@999 4667
belaran@999 4668 <sect2>
belaran@999 4669 <title>Renommages divergeants et fusion (merge)</title>
belaran@999 4670
belaran@999 4671 <para id="x_1da">Le cas de noms divergeants a lieu lorsque deux
belaran@999 4672 développeurs commencent avec un fichier—appelons le
belaran@999 4673 <filename moreinfo="none">foo</filename>—dans leurs dépôts respectifs.</para>
belaran@999 4674
belaran@999 4675 <!-- BEGIN rename.divergent.clone -->
belaran@999 4676 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig anne</userinput>
belaran@999 4677 updating working directory
belaran@999 4678 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4679 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig bob</userinput>
belaran@999 4680 updating working directory
belaran@999 4681 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4682 </screen>
belaran@999 4683 <!-- END rename.divergent.clone -->
belaran@999 4684
belaran@999 4685
belaran@999 4686 <para id="x_1db">Anne renomme le fichier en
belaran@999 4687 <filename moreinfo="none">bar</filename>.</para>
belaran@999 4688
belaran@999 4689 <!-- BEGIN rename.divergent.rename.anne -->
belaran@999 4690 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd anne</userinput>
belaran@999 4691 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename foo bar</userinput>
belaran@999 4692 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to bar'</userinput>
belaran@999 4693 </screen>
belaran@999 4694 <!-- END rename.divergent.rename.anne -->
belaran@999 4695
belaran@999 4696
belaran@999 4697 <para id="x_1dc">Pendant ce temps, Bob le renomme en
belaran@999 4698 <filename moreinfo="none">quux</filename>. (Souvenez vous que <command role="hg-cmd" moreinfo="none">hg mv</command> est un alias pour <command role="hg-cmd" moreinfo="none">hg rename</command>.)</para>
belaran@999 4699
belaran@999 4700 <!-- BEGIN rename.divergent.rename.bob -->
belaran@999 4701 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../bob</userinput>
belaran@999 4702 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg mv foo quux</userinput>
belaran@999 4703 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to quux'</userinput>
belaran@999 4704 </screen>
belaran@999 4705 <!-- END rename.divergent.rename.bob -->
belaran@999 4706
belaran@999 4707
belaran@999 4708 <para id="x_1dd">J'aime à penser qu'il s'agit d'un conflit puisque
belaran@999 4709 chaque développeur a exprimé différentes intentions au sujet de ce
belaran@999 4710 que le nom de ce fichier aurait du être.</para>
belaran@999 4711
belaran@999 4712 <para id="x_1de">Que pensez vous qu'il devrait se produire lorsqu'ils
belaran@999 4713 fusionnent (merge) leurs travaux ? Le comportement actuel de
belaran@999 4714 Mercurial est qu'il préserve toujours les <emphasis>deux</emphasis>
belaran@999 4715 noms lorsqu'il fusionne (merge) des changesets qui contiennent des
belaran@999 4716 renommages divergeants.</para>
belaran@999 4717
belaran@999 4718 <!-- BEGIN rename.divergent.merge -->
belaran@999 4719 <screen format="linespecific"># See http://www.selenic.com/mercurial/bts/issue455
belaran@999 4720 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../orig</userinput>
belaran@999 4721 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../anne</userinput>
belaran@999 4722 pulling from ../anne
belaran@999 4723 searching for changes
belaran@999 4724 adding changesets
belaran@999 4725 adding manifests
belaran@999 4726 adding file changes
belaran@999 4727 added 1 changesets with 1 changes to 1 files
belaran@999 4728 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
belaran@999 4729 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../bob</userinput>
belaran@999 4730 pulling from ../bob
belaran@999 4731 searching for changes
belaran@999 4732 adding changesets
belaran@999 4733 adding manifests
belaran@999 4734 adding file changes
belaran@999 4735 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 4736 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 4737 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 4738 warning: detected divergent renames of foo to:
belaran@999 4739 bar
belaran@999 4740 quux
belaran@999 4741 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4742 (branch merge, don't forget to commit)
belaran@999 4743 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput>
belaran@999 4744 bar quux
belaran@999 4745 </screen>
belaran@999 4746 <!-- END rename.divergent.merge -->
belaran@999 4747
belaran@999 4748
belaran@999 4749 <para id="x_1df">Remarquez que bien que Mercurial vous avertisse au
belaran@999 4750 sujet de la divergeance des renommages, il vous laisse faire quelque
belaran@999 4751 chose au sujet de la divergeance après la fusion (merge).</para>
belaran@999 4752 </sect2>
belaran@999 4753
belaran@999 4754 <sect2>
belaran@999 4755 <title>Renommages et fusion convergeants</title>
belaran@999 4756
belaran@999 4757 <para id="x_1e0">Un autre type de conflit de renommage intervient
belaran@999 4758 lorsque deux personne choisissent de renommer différents fichiers
belaran@999 4759 <emphasis>source</emphasis> vers la même
belaran@999 4760 <emphasis>destination</emphasis>. Dans ce cas, Mercurial exécute la
belaran@999 4761 machinerie normale de fusion (merge) et vous guide vers une
belaran@999 4762 solution convenable.</para>
belaran@999 4763 </sect2>
belaran@999 4764
belaran@999 4765 <sect2>
belaran@999 4766 <title>Autres cas anguleux relatifs aux noms</title>
belaran@999 4767
belaran@999 4768 <para id="x_1e1">Mercurial possède un bug de longue date dans lequel il
belaran@999 4769 échoue à traiter une fusion (merge) où un coté a un fichier avec un
belaran@999 4770 nom donné, alors que l'autre coté possède un répertoire avec le même nom.
belaran@999 4771 Ceci est documenté dans l'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue
belaran@999 4772 29</ulink>.</para>
belaran@999 4773
belaran@999 4774 <!-- BEGIN issue29.go -->
belaran@999 4775 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init issue29</userinput>
belaran@999 4776 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd issue29</userinput>
belaran@999 4777 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 4778 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Ama</userinput>
belaran@999 4779 adding a
belaran@999 4780 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
belaran@999 4781 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amb</userinput>
belaran@999 4782 adding b
belaran@999 4783 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg up 0</userinput>
belaran@999 4784 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
belaran@999 4785 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
belaran@999 4786 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/b</userinput>
belaran@999 4787 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amc</userinput>
belaran@999 4788 adding b/b
belaran@999 4789 created new head
belaran@999 4790 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 4791 abort: Is a directory: /tmp/issue29vhrzWD/issue29/b
belaran@999 4792 </screen>
belaran@999 4793 <!-- END issue29.go -->
belaran@999 4794
belaran@999 4795
belaran@999 4796 </sect2>
belaran@999 4797 </sect1>
belaran@999 4798
belaran@999 4799 <sect1>
belaran@999 4800 <title>Récupération d'erreurs</title>
belaran@999 4801
belaran@999 4802 <para id="x_1e2">Mercurial possède certaines commandes utiles qui vont
belaran@999 4803 vous aider à récupérer de certaines erreurs communes.</para>
belaran@999 4804
belaran@999 4805 <para id="x_1e3">La commande <command role="hg-cmd" moreinfo="none">hg revert</command>
belaran@999 4806 vous permet d'annuler les changements que vous avez faits dans votre
belaran@999 4807 répertoire de travail. Par exemple, si vous faites un <command role="hg-cmd" moreinfo="none">hg add</command> sur un fichier par accident, exécutez
belaran@999 4808 juste <command role="hg-cmd" moreinfo="none">hg revert</command> avec le nom du fichier
belaran@999 4809 que vous avez ajouté et tandis que le fichier ne sera touché d'une
belaran@999 4810 quelconque manière, il ne sera plus suivi comme ajouté par Mercurial.
belaran@999 4811 Vous pouvez aussi utiliser la commande <command role="hg-cmd" moreinfo="none">hg
belaran@999 4812 revert</command> pour vous débarrasser de modifications erronés
belaran@999 4813 apportées à un fichier.</para>
belaran@999 4814
belaran@999 4815 <para id="x_1e4">Il est utile de se souvenir que la commande <command role="hg-cmd" moreinfo="none">hg revert</command> est utile pour les modifications
belaran@999 4816 qui n'ont pas encore été committées. Une fois que vous avez committé un
belaran@999 4817 changement, si vous décidez qu'il s'agissait d'une erreur, vous pouvez
belaran@999 4818 toujours faire quelque chose à ce sujet, bien que vos options soient
belaran@999 4819 un peu plus limitées.</para>
belaran@999 4820
belaran@999 4821 <para id="x_1e5">Pour plus d'informations au sujet de la commande
belaran@999 4822 <command role="hg-cmd" moreinfo="none">hg revert</command>, et des détails sur comment
belaran@999 4823 traiter les modifications que vous avez déjà committées, référez vous à
belaran@999 4824 <xref linkend="chap:undo"/>.</para>
belaran@999 4825 </sect1>
belaran@999 4826
belaran@999 4827 <sect1>
belaran@999 4828 <title>Traiter avec les fusions (merge) malicieuses</title>
belaran@999 4829
belaran@999 4830 <para id="x_687">Dans des projets compliqués ou conséquents, il n'est pas
belaran@999 4831 rare qu'une fusion (merge) de deux changesets finisse par une migraine.
belaran@999 4832 Supposez qu'il y ait un gros fichier source qui ait été largement édité de
belaran@999 4833 chaque coté de la fusion (merge) : ceci va inévitablement résulter en
belaran@999 4834 conflits, dont certains peuvent prendre plusieurs essais pour s'en
belaran@999 4835 sortir.</para>
belaran@999 4836
belaran@999 4837 <para id="x_688">Développons en un cas simple pour voir comment le gérer.
belaran@999 4838 Nous allons commencer avec un dépôt contenant un fichier, et le
belaran@999 4839 cloner deux fois.</para>
belaran@999 4840
belaran@999 4841 <!-- BEGIN ch04/resolve.init -->
belaran@999 4842 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init conflict</userinput>
belaran@999 4843 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd conflict</userinput>
belaran@999 4844 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first &gt; myfile.txt</userinput>
belaran@999 4845 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -A -m first</userinput>
belaran@999 4846 adding myfile.txt
belaran@999 4847 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 4848 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict left</userinput>
belaran@999 4849 updating working directory
belaran@999 4850 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4851 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict right</userinput>
belaran@999 4852 updating working directory
belaran@999 4853 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4854 </screen>
belaran@999 4855 <!-- END ch04/resolve.init -->
belaran@999 4856
belaran@999 4857
belaran@999 4858 <para id="x_689">Dans un des clones, nous allons modifier le fichier
belaran@999 4859 d'une façon.</para>
belaran@999 4860
belaran@999 4861 <!-- BEGIN ch04/resolve.left -->
belaran@999 4862 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd left</userinput>
belaran@999 4863 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo left &gt;&gt; myfile.txt</userinput>
belaran@999 4864 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m left</userinput>
belaran@999 4865 </screen>
belaran@999 4866 <!-- END ch04/resolve.left -->
belaran@999 4867
belaran@999 4868
belaran@999 4869 <para id="x_68a">Dans un autre, nous allons modifier le fichier
belaran@999 4870 différemment.</para>
belaran@999 4871
belaran@999 4872 <!-- BEGIN ch04/resolve.right -->
belaran@999 4873 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../right</userinput>
belaran@999 4874 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo right &gt;&gt; myfile.txt</userinput>
belaran@999 4875 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m right</userinput>
belaran@999 4876 </screen>
belaran@999 4877 <!-- END ch04/resolve.right -->
belaran@999 4878
belaran@999 4879
belaran@999 4880 <para id="x_68b">Ensuite, nous allons récupérer (pull) chaque ensemble de
belaran@999 4881 changement dans notre dépôt original.</para>
belaran@999 4882
belaran@999 4883 <!-- BEGIN ch04/resolve.pull -->
belaran@999 4884 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../conflict</userinput>
belaran@999 4885 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../left</userinput>
belaran@999 4886 pulling from ../left
belaran@999 4887 searching for changes
belaran@999 4888 adding changesets
belaran@999 4889 adding manifests
belaran@999 4890 adding file changes
belaran@999 4891 added 1 changesets with 1 changes to 1 files
belaran@999 4892 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 4893 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../right</userinput>
belaran@999 4894 pulling from ../right
belaran@999 4895 searching for changes
belaran@999 4896 adding changesets
belaran@999 4897 adding manifests
belaran@999 4898 adding file changes
belaran@999 4899 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 4900 not updating, since new heads added
belaran@999 4901 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 4902 </screen>
belaran@999 4903 <!-- END ch04/resolve.pull -->
belaran@999 4904
belaran@999 4905
belaran@999 4906 <para id="x_68c">Nous nous attendons à ce que notre dépôt contienne deux
belaran@999 4907 "heads".</para>
belaran@999 4908
belaran@999 4909 <!-- BEGIN ch04/resolve.heads -->
belaran@999 4910 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
belaran@999 4911 changeset: 2:85f1afc84c33
belaran@999 4912 tag: tip
belaran@999 4913 parent: 0:14a820f81f48
belaran@999 4914 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 4915 date: Sun Aug 16 14:04:51 2009 +0000
belaran@999 4916 summary: right
belaran@999 4917
belaran@999 4918 changeset: 1:085ebbf44348
belaran@999 4919 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 4920 date: Sun Aug 16 14:04:51 2009 +0000
belaran@999 4921 summary: left
belaran@999 4922
belaran@999 4923 </screen>
belaran@999 4924 <!-- END ch04/resolve.heads -->
belaran@999 4925
belaran@999 4926
belaran@999 4927 <para id="x_68d">Normalement, si nous lançons <command role="hg-cmd" moreinfo="none">hg
belaran@999 4928 merge</command> à ce point, il nous renverra vers une interface
belaran@999 4929 utilisateur qui nous permettra de résoudre manuellement les éditions
belaran@999 4930 conflictuelles sur le fichier <filename moreinfo="none">myfile.txt</filename>.
belaran@999 4931 Cependant, pour simplifier ici les choses dans la présentation, nous
belaran@999 4932 aimerions plutôt que la fusion (merge) échoue immédiatement. Voici une
belaran@999 4933 façon de le faire.</para>
belaran@999 4934
belaran@999 4935 <!-- BEGIN ch04/resolve.export -->
belaran@999 4936 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=false</userinput>
belaran@999 4937 </screen>
belaran@999 4938 <!-- END ch04/resolve.export -->
belaran@999 4939
belaran@999 4940
belaran@999 4941 <para id="x_68e">Nous avons dit au processus de fusion de Mercurial
belaran@999 4942 d'exécuter la commande <command moreinfo="none">false</command> (qui échoue
belaran@999 4943 immédiatement, à la demande) s'il détecte une fusion (merge) qu'il ne
belaran@999 4944 peut pas arranger automatiquement.</para>
belaran@999 4945
belaran@999 4946 <para id="x_68f">Si nous appelons maintenant <command role="hg-cmd" moreinfo="none">hg
belaran@999 4947 merge</command>, il devrait échouer et reporter une erreur.</para>
belaran@999 4948
belaran@999 4949 <!-- BEGIN ch04/resolve.merge -->
belaran@999 4950 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 4951 merging myfile.txt
belaran@999 4952 merging myfile.txt failed!
belaran@999 4953 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
belaran@999 4954 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
belaran@999 4955 </screen>
belaran@999 4956 <!-- END ch04/resolve.merge -->
belaran@999 4957
belaran@999 4958
belaran@999 4959 <para id="x_690">Même si nous ne remarquons pas qu'une fusion (merge) a
belaran@999 4960 échoué, Mercurial nous empêchera de committer le résultat d'une fusion
belaran@999 4961 ratée.</para>
belaran@999 4962
belaran@999 4963 <!-- BEGIN ch04/resolve.cifail -->
belaran@999 4964 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Attempt to commit a failed merge'</userinput>
belaran@999 4965 abort: unresolved merge conflicts (see hg resolve)
belaran@999 4966 </screen>
belaran@999 4967 <!-- END ch04/resolve.cifail -->
belaran@999 4968
belaran@999 4969
belaran@999 4970 <para id="x_691">Lorsque <command role="hg-cmd" moreinfo="none">hg commit</command>
belaran@999 4971 échoue dans ce cas, il suggère que nous utilisons la commande peu
belaran@999 4972 connue <command role="hg-cmd" moreinfo="none">hg resolve</command>. Comme d'habitude,
belaran@999 4973 <command role="hg-cmd" moreinfo="none">hg help resolve</command> affichera une aide
belaran@999 4974 sommaire.</para>
belaran@999 4975
belaran@999 4976 <sect2>
belaran@999 4977 <title>États de résolution des fichiers</title>
belaran@999 4978 <!-- TODO Vérifier traduction : File resolution states -->
belaran@999 4979
belaran@999 4980 <para id="x_692">Lorsqu'une fusion intervient, la plupart des fichiers
belaran@999 4981 vont, la plupart du temps, rester sans modification. Pour chaque
belaran@999 4982 fichier sur lequel Mercurial doit faire quelque chose, il suit l'état
belaran@999 4983 de celui-ci.</para>
belaran@999 4984
belaran@999 4985 <itemizedlist>
belaran@999 4986 <listitem><para id="x_693">Un fichier
belaran@999 4987 <quote><emphasis>resolved</emphasis></quote> a été fusionné
belaran@999 4988 (merge) avec succès, que ce soit automatiquement par Mercurial ou
belaran@999 4989 manuellement par une intervention humaine.</para></listitem>
belaran@999 4990 <listitem><para id="x_694">Un fichier
belaran@999 4991 <quote><emphasis>unresolved</emphasis></quote> n'a pas été
belaran@999 4992 fusionné (merge) correctement et a besoin de plus
belaran@999 4993 d'attention.</para>
belaran@999 4994 </listitem>
belaran@999 4995 </itemizedlist>
belaran@999 4996
belaran@999 4997 <para id="x_695">Si Mercurial voit un fichier
belaran@999 4998 <emphasis>quelconque</emphasis> dans un état
belaran@999 4999 <quote>unresolved</quote> après une fusion (merge), il considère que
belaran@999 5000 la fusion (merge) a échoué. Heureusement, nous n'avons pas à
belaran@999 5001 recommencer la procédure à partir du début.</para>
belaran@999 5002
belaran@999 5003 <para id="x_696">L'option <option role="hg-opt-resolve">--list</option>
belaran@999 5004 ou <option role="hg-opt-resolve">-l</option> passée à <command role="hg-cmd" moreinfo="none">hg resolve</command> liste l'état de chaque fichier
belaran@999 5005 fusionné (merge).</para>
belaran@999 5006
belaran@999 5007 <!-- BEGIN ch04/resolve.list -->
belaran@999 5008 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -l</userinput>
belaran@999 5009 U myfile.txt
belaran@999 5010 </screen>
belaran@999 5011 <!-- END ch04/resolve.list -->
belaran@999 5012
belaran@999 5013
belaran@999 5014 <para id="x_697">En sortie de <command role="hg-cmd" moreinfo="none">hg
belaran@999 5015 resolve</command>, un fichier "resolved" est marqué avec un
belaran@999 5016 <literal moreinfo="none">R</literal>, alors qu'un fichier "unresolved" est marqué
belaran@999 5017 d'un <literal moreinfo="none">U</literal>. S'il existe un fichier listé avec un
belaran@999 5018 <literal moreinfo="none">U</literal>, nous savons qu'essayer de committer le résultat
belaran@999 5019 de la fusion (merge) échouera.</para>
belaran@999 5020 </sect2>
belaran@999 5021
belaran@999 5022 <sect2>
belaran@999 5023 <title>Résoudre une fusion de fichier</title>
belaran@999 5024
belaran@999 5025 <para id="x_698">Nous avons plusieurs options pour changer l'état d'un
belaran@999 5026 fichier de "unresolved" à "resolved". Le plus commun est de relancer
belaran@999 5027 <command role="hg-cmd" moreinfo="none">hg resolve</command>. Si nous passons les noms
belaran@999 5028 des fichiers individuels ou des répertoires, ceci retentera la fusion
belaran@999 5029 de tous les fichiers présents à cet endroit. Nous pouvons aussi
belaran@999 5030 passer l'option <option role="hg-opt-resolve">--all</option> ou
belaran@999 5031 <option role="hg-opt-resolve">-a</option> qui tentera de fusionner
belaran@999 5032 <emphasis>tous</emphasis> les fichiers "unresolved".</para>
belaran@999 5033
belaran@999 5034 <para id="x_699">Mercurial nous laisse aussi modifier la résolution
belaran@999 5035 d'un fichier directement. Nous pouvons marquer un fichier "resolved"
belaran@999 5036 en utilisant l'option <option role="hg-opt-resolve">--mark</option>,
belaran@999 5037 ou "unresolved" en utilisant l'option <option role="hg-opt-resolve">--unmark</option>. Ceci nous autorise à
belaran@999 5038 nettoyer une fusion particulièrement compliquée à la main, et de
belaran@999 5039 garder un suivi de nos progrès avec chaque fichier pendant que nous
belaran@999 5040 procédons.</para>
belaran@999 5041 </sect2>
belaran@999 5042 </sect1>
belaran@999 5043
belaran@999 5044 <sect1>
belaran@999 5045 <title>Des "diffs" plus utiles</title>
belaran@999 5046
belaran@999 5047 <para id="x_6c7">La sortie par défaut de la commande <command role="hg-cmd" moreinfo="none">hg diff</command> est compatible rétrospectivement avec
belaran@999 5048 la commande régulière <command moreinfo="none">diff</command>, mais ceci a quelques
belaran@999 5049 inconvénients.</para>
belaran@999 5050
belaran@999 5051 <para id="x_6c8">Considérez le cas où nous utilisons <command role="hg-cmd" moreinfo="none">hg
belaran@999 5052 rename</command> pour renommer un fichier.</para>
belaran@999 5053
belaran@999 5054 <!-- BEGIN ch04/diff.rename.basic -->
belaran@999 5055 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput>
belaran@999 5056 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 5057 diff -r f5deb7868663 a
belaran@999 5058 --- a/a Sun Aug 16 14:04:49 2009 +0000
belaran@999 5059 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
belaran@999 5060 @@ -1,1 +0,0 @@
belaran@999 5061 -a
belaran@999 5062 diff -r f5deb7868663 b
belaran@999 5063 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
belaran@999 5064 +++ b/b Sun Aug 16 14:04:49 2009 +0000
belaran@999 5065 @@ -0,0 +1,1 @@
belaran@999 5066 +a
belaran@999 5067 </screen>
belaran@999 5068 <!-- END ch04/diff.rename.basic -->
belaran@999 5069
belaran@999 5070
belaran@999 5071 <para id="x_6c9">La sortie de <command role="hg-cmd" moreinfo="none">hg diff</command>
belaran@999 5072 ci-dessus cache le fait que nous avons simplement renommé un fichier.
belaran@999 5073 La commande <command role="hg-cmd" moreinfo="none">hg diff</command> accepte l'option
belaran@999 5074 <option>--git</option> ou <option>-g</option> pour utiliser un nouveau
belaran@999 5075 format de diff qui montre ces informations sous une forme plus
belaran@999 5076 expressive.</para>
belaran@999 5077
belaran@999 5078 <!-- BEGIN ch04/diff.rename.git -->
belaran@999 5079 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput>
belaran@999 5080 diff --git a/a b/b
belaran@999 5081 rename from a
belaran@999 5082 rename to b
belaran@999 5083 </screen>
belaran@999 5084 <!-- END ch04/diff.rename.git -->
belaran@999 5085
belaran@999 5086
belaran@999 5087 <para id="x_6ca">Cette option peut aussi aider avec le cas autrement
belaran@999 5088 confus : un fichier qui apparaît comme étant modifié en accord avec
belaran@999 5089 <command role="hg-cmd" moreinfo="none">hg status</command>, mais où <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien. Cette situation peut
belaran@999 5090 survenir si nous changeons les permissions d'exécution du
belaran@999 5091 fichier.</para>
belaran@999 5092
belaran@999 5093 <!-- BEGIN ch04/diff.chmod -->
belaran@999 5094 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x a</userinput>
belaran@999 5095 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg st</userinput>
belaran@999 5096 M a
belaran@999 5097 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 5098 </screen>
belaran@999 5099 <!-- END ch04/diff.chmod -->
belaran@999 5100
belaran@999 5101
belaran@999 5102 <para id="x_6cb">La commande normale <command moreinfo="none">diff</command> ne fait pas
belaran@999 5103 attention aux permissions des fichiers, ce qui explique pourquoi
belaran@999 5104 <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien du tout par
belaran@999 5105 défaut. Si nous lui passons l'option <option>-g</option>, ceci nous
belaran@999 5106 informe de ce qu'il s'est vraiment passé.</para>
belaran@999 5107
belaran@999 5108 <!-- BEGIN ch04/diff.chmod.git -->
belaran@999 5109 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput>
belaran@999 5110 diff --git a/a b/a
belaran@999 5111 old mode 100644
belaran@999 5112 new mode 100755
belaran@999 5113 </screen>
belaran@999 5114 <!-- END ch04/diff.chmod.git -->
belaran@999 5115
belaran@999 5116 </sect1>
belaran@999 5117
belaran@999 5118 <sect1>
belaran@999 5119 <title>Quels fichiers suivre et lesquels éviter</title>
belaran@999 5120
belaran@999 5121 <para id="x_6cc">Les systèmes de gestion de révisions sont en général
belaran@999 5122 meilleurs pour gérer les fichiers textes qui sont écrits par les
belaran@999 5123 humains, comme le code source, où les fichiers ne changent pas
belaran@999 5124 énormément d'une révision à l'autre. Certains systèmes de gestion de
belaran@999 5125 révisions centralisés peuvent aussi traiter très convenablement les
belaran@999 5126 fichiers binaires, tels que les images bitmap.</para>
belaran@999 5127
belaran@999 5128 <para id="x_6cd">Par exemple, une équipe de développement de jeux va
belaran@999 5129 probablement gérer les deux types : ses codes source et tous ses binaires
belaran@999 5130 (ex. données géométriques, textures, schémas de cartes) dans un système
belaran@999 5131 de contrôle de révisions.</para>
belaran@999 5132 <!-- Vérifier la traduction de map layouts que j'ai traduit par schémas
belaran@999 5133 de cartes -->
belaran@999 5134
belaran@999 5135 <para id="x_6ce">Puisqu'il est d'habitude impossible de fusionner (merge)
belaran@999 5136 deux modifications conflictuelles sur un fichier binaire, les systèmes
belaran@999 5137 de version centralisés offrent souvent un mécanisme de verrou (lock) qui
belaran@999 5138 permet à un utilisateur de dire <quote>Je suis la seule personne qui
belaran@999 5139 peut éditer ce fichier</quote>.</para>
belaran@999 5140
belaran@999 5141 <para id="x_6cf">En comparaison avec un système centralisé, un système
belaran@999 5142 décentralisé de gestion de révision change certains facteurs qui
belaran@999 5143 guident les décisions sur quels fichiers gérer et comment.</para>
belaran@999 5144
belaran@999 5145 <para id="x_6d0">Par exemple, un système distribué de gestion de révisions
belaran@999 5146 ne peut pas, par sa nature, offrir un système de véroux (lock) sur les
belaran@999 5147 fichiers. Il n'y a donc pas de mécanisme inclus pour empêcher deux
belaran@999 5148 personnes de faire des modifications conflictuelles sur un fichier
belaran@999 5149 binaire. Si vous avez une équipe où plusieurs personnes peuvent souvent
belaran@999 5150 éditer un fichier binaire, cela ne serait pas une très bonne idée
belaran@999 5151 d'utiliser Mercurial —ou tout autre système distribué de gestion
belaran@999 5152 de révisions—pour gérer ces fichiers.</para>
belaran@999 5153
belaran@999 5154 <para id="x_6d1">Lorsque vous sauvegardez les modifications sur un
belaran@999 5155 fichier, Mercurial ne sauvegarde d'habitude que les différences entre
belaran@999 5156 la version précédente et la version actuelle d'un fichier. Pour la
belaran@999 5157 plupart des fichiers texte, ceci est très efficace. Cependant, certains
belaran@999 5158 fichiers (en particulier les fichiers binaires) sont construits d'une
belaran@999 5159 façon que même un petit changement sur un contenu logique résulte sur
belaran@999 5160 un changement de la plupart des octets du fichier. Par exemple, les
belaran@999 5161 fichiers compressés sont particulièrement sujets à ce comportement. Si
belaran@999 5162 les différences entre deux versions successives d'un fichier sont
belaran@999 5163 toujours très grandes, Mercurial ne sera pas capable de sauvegarder
belaran@999 5164 l'historique des révisions sur le fichier très efficacement. Ceci peut
belaran@999 5165 affecter aussi bien les besoins pour la sauvegarde locale que le temps
belaran@999 5166 nécessaire à cloner le dépôt.</para>
belaran@999 5167
belaran@999 5168 <para id="x_6d2">Pour avoir une idée de comment ceci pourrait vous
belaran@999 5169 affecter en pratique, supposez que nous voulions que Mercurial gère des
belaran@999 5170 documents OpenOffice. OpenOffice sauvegarde les documents sur le disque
belaran@999 5171 comme des fichiers compressés zip. Même le fait d'éditer ces fichiers
belaran@999 5172 d'une seule lettre, changera les bits de la quasi totalité du fichier
belaran@999 5173 lorsque vous le sauvegarderez. Maintenant, supposez que ce fichier
belaran@999 5174 fasse une taille de 2Mo. Puisque la plupart du fichier change à chaque
belaran@999 5175 fois que vous sauvegardez, Mercurial aura à sauvegarder tous les 2Mo du
belaran@999 5176 fichier à chaque commit, alors que de votre point de vue, il n'y a
belaran@999 5177 que peu de mots qui changent à chaque fois. Un seul fichier
belaran@999 5178 souvent édité qui n'est pas bien traité par les hypothèses que Mercurial
belaran@999 5179 fait sur les sauvegardes peut facilement avoir un effet colossal sur la
belaran@999 5180 taille du dépôt.</para>
belaran@999 5181
belaran@999 5182 <para id="x_6d3">Même pire, si vous et quelqu'un d'autre éditez le même
belaran@999 5183 document OpenOffice sur lequel vous travaillez, il n'y a pas de façon
belaran@999 5184 utile pour fusionner votre travail. En fait, il n'y a pas de moyen
belaran@999 5185 utile de montrer que les différences sont faites à partir de votre
belaran@999 5186 vision des modifications.</para>
belaran@999 5187
belaran@999 5188 <para id="x_6d4">Il y a ainsi quelques recommandations claires sur les
belaran@999 5189 types de fichiers spécifiques avec lesquels faire très
belaran@999 5190 attention.</para>
belaran@999 5191
belaran@999 5192 <itemizedlist>
belaran@999 5193 <listitem><para id="x_6d5">Les fichier qui sont très gros et
belaran@999 5194 incompressibles, comme les images ISO de CD-ROM, sont, par
belaran@999 5195 construction très gros et les cloner à travers un réseau sera très
belaran@999 5196 long.</para></listitem>
belaran@999 5197 <!-- TODO : Trouver une meilleure traduction pour : ISO CD-ROM images, will by
belaran@999 5198 virtue of sheer size make clones over a network very slow. -->
belaran@999 5199 <listitem><para id="x_6d6">Les fichiers qui changent beaucoup d'une
belaran@999 5200 révision à l'autre peuvent être très chers à sauvegarder si vous
belaran@999 5201 les éditez fréquemment, de même que les conflits entre deux éditions
belaran@999 5202 concurrentes peuvent être difficiles à résoudre.</para>
belaran@999 5203 </listitem>
belaran@999 5204 </itemizedlist>
belaran@999 5205 </sect1>
belaran@999 5206
belaran@999 5207 <sect1>
belaran@999 5208 <title>Sauvegardes et miroirs</title>
belaran@999 5209
belaran@999 5210 <para id="x_6d7">Puisque Mercurial maintient une copie complète de
belaran@999 5211 l'historique de chaque clone, toute personne qui utilise Mercurial pour
belaran@999 5212 collaborer à un projet peut potentiellement agir comme une source de
belaran@999 5213 sauvegarde si une catastrophe survenait. Si un dépôt central devient
belaran@999 5214 indisponible, vous pouvez construire un remplaçant en clonant une copie
belaran@999 5215 du dépôt à partir d'un des contributeurs en récupérant (pull) tous les
belaran@999 5216 changements qui n'auraient pas été vus par les autres.</para>
belaran@999 5217
belaran@999 5218 <para id="x_6d8">Il est simple d'utiliser Mercurial pour construire des
belaran@999 5219 serveurs hors site de sauvegarde et des miroirs distants. Initiez une
belaran@999 5220 tâche périodique (ex. via la commande <command moreinfo="none">cron</command>) sur un
belaran@999 5221 serveur distant pour récupérer (pull) les changements de votre dépôt
belaran@999 5222 distant chaque heure. Ceci sera difficile seulement dans le cas
belaran@999 5223 improbable où le nombre des dépôts maîtres que vous maintenez change
belaran@999 5224 souvent, auquel cas vous aurez besoin de faire un peu de scripting pour
belaran@999 5225 rafraichir la liste des dépôt à sauvegarder.</para>
belaran@999 5226
belaran@999 5227 <para id="x_6d9">Si vous exécutez des sauvegardes traditionnelles de
belaran@999 5228 votre dépôt maître sur bande ou disque, et que vous voulez sauvegarder
belaran@999 5229 un dépôt nommé <filename moreinfo="none">myrepo</filename>, utilisez la commande
belaran@999 5230 <command moreinfo="none">hg clone -U myrepo myrepo.bak</command> pour créer un clone de
belaran@999 5231 <filename moreinfo="none">myrepo</filename> avant de commencer vos backups.
belaran@999 5232 L'option <option>-U</option> ne crée pas de répertoire de travail après
belaran@999 5233 que le clone soit accompli, puisque ceci serait superflu et ferait que
belaran@999 5234 la sauvegarde prenne plus de temps.</para>
belaran@999 5235
belaran@999 5236 <para id="x_6da">Si vous voulez ensuite sauvegarder
belaran@999 5237 <filename moreinfo="none">myrepo.bak</filename> au lieu de <filename moreinfo="none">myrepo</filename>,
belaran@999 5238 vous aurez la garantie d'avoir une image (snapshot) consistante de
belaran@999 5239 votre dépôt sur lequel un développeur insomniaque n'enverra (push) pas de
belaran@999 5240 changements en milieu de sauvegarde.</para>
belaran@999 5241 </sect1>
belaran@999 5242 </chapter>
belaran@999 5243
belaran@999 5244 <!--
belaran@999 5245 local variables:
belaran@999 5246 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 5247 end:
belaran@999 5248 -->
belaran@999 5249
belaran@999 5250 <!-- BEGIN ch06 -->
belaran@999 5251 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 5252
belaran@999 5253 <chapter id="cha:collab">
belaran@999 5254 <?dbhtml filename="collaborating-with-other-people.html"?>
belaran@999 5255 <title>Collaborating with other people</title>
belaran@999 5256
belaran@999 5257 <para id="x_44a">As a completely decentralised tool, Mercurial doesn't impose
belaran@999 5258 any policy on how people ought to work with each other. However,
belaran@999 5259 if you're new to distributed revision control, it helps to have
belaran@999 5260 some tools and examples in mind when you're thinking about
belaran@999 5261 possible workflow models.</para>
belaran@999 5262
belaran@999 5263 <sect1>
belaran@999 5264 <title>Mercurial's web interface</title>
belaran@999 5265
belaran@999 5266 <para id="x_44b">Mercurial has a powerful web interface that provides several
belaran@999 5267 useful capabilities.</para>
belaran@999 5268
belaran@999 5269 <para id="x_44c">For interactive use, the web interface lets you browse a
belaran@999 5270 single repository or a collection of repositories. You can view
belaran@999 5271 the history of a repository, examine each change (comments and
belaran@999 5272 diffs), and view the contents of each directory and file. You
belaran@999 5273 can even get a view of history that gives a graphical view of
belaran@999 5274 the relationships between individual changes and merges.</para>
belaran@999 5275
belaran@999 5276 <para id="x_44d">Also for human consumption, the web interface provides
belaran@999 5277 Atom and RSS feeds of the changes in a repository. This lets you
belaran@999 5278 <quote>subscribe</quote> to a repository using your favorite
belaran@999 5279 feed reader, and be automatically notified of activity in that
belaran@999 5280 repository as soon as it happens. I find this capability much
belaran@999 5281 more convenient than the model of subscribing to a mailing list
belaran@999 5282 to which notifications are sent, as it requires no additional
belaran@999 5283 configuration on the part of whoever is serving the
belaran@999 5284 repository.</para>
belaran@999 5285
belaran@999 5286 <para id="x_44e">The web interface also lets remote users clone a repository,
belaran@999 5287 pull changes from it, and (when the server is configured to
belaran@999 5288 permit it) push changes back to it. Mercurial's HTTP tunneling
belaran@999 5289 protocol aggressively compresses data, so that it works
belaran@999 5290 efficiently even over low-bandwidth network connections.</para>
belaran@999 5291
belaran@999 5292 <para id="x_44f">The easiest way to get started with the web interface is to
belaran@999 5293 use your web browser to visit an existing repository, such as
belaran@999 5294 the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para>
belaran@999 5295
belaran@999 5296 <para id="x_450">If you're interested in providing a web interface
belaran@999 5297 to your own repositories, there are several good ways to do
belaran@999 5298 this.</para>
belaran@999 5299
belaran@999 5300 <para id="x_69d">The easiest and fastest way to get started in an informal
belaran@999 5301 environment is to use the <command role="hg-cmd" moreinfo="none">hg
belaran@999 5302 serve</command> command, which is best suited to short-term
belaran@999 5303 <quote>lightweight</quote> serving. See <xref linkend="sec:collab:serve"/> below for details of how to use
belaran@999 5304 this command.</para>
belaran@999 5305
belaran@999 5306 <para id="x_69e">For longer-lived repositories that you'd like to
belaran@999 5307 have permanently available, there are several public hosting
belaran@999 5308 services available. Some are free to open source projects,
belaran@999 5309 while others offer paid commercial hosting. An up-to-date list
belaran@999 5310 is available at <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</ulink>.</para>
belaran@999 5311
belaran@999 5312 <para id="x_6a0">If you would prefer to host your own repositories, Mercurial
belaran@999 5313 has built-in support for several popular hosting technologies,
belaran@999 5314 most notably CGI (Common Gateway Interface), and WSGI (Web
belaran@999 5315 Services Gateway Interface). See <xref linkend="sec:collab:cgi"/> for details of CGI and WSGI
belaran@999 5316 configuration.</para>
belaran@999 5317 </sect1>
belaran@999 5318
belaran@999 5319 <sect1>
belaran@999 5320 <title>Collaboration models</title>
belaran@999 5321
belaran@999 5322 <para id="x_451">With a suitably flexible tool, making decisions about
belaran@999 5323 workflow is much more of a social engineering challenge than a
belaran@999 5324 technical one. Mercurial imposes few limitations on how you can
belaran@999 5325 structure the flow of work in a project, so it's up to you and
belaran@999 5326 your group to set up and live with a model that matches your own
belaran@999 5327 particular needs.</para>
belaran@999 5328
belaran@999 5329 <sect2>
belaran@999 5330 <title>Factors to keep in mind</title>
belaran@999 5331
belaran@999 5332 <para id="x_452">The most important aspect of any model that you must keep
belaran@999 5333 in mind is how well it matches the needs and capabilities of
belaran@999 5334 the people who will be using it. This might seem
belaran@999 5335 self-evident; even so, you still can't afford to forget it for
belaran@999 5336 a moment.</para>
belaran@999 5337
belaran@999 5338 <para id="x_453">I once put together a workflow model that seemed to make
belaran@999 5339 perfect sense to me, but that caused a considerable amount of
belaran@999 5340 consternation and strife within my development team. In spite
belaran@999 5341 of my attempts to explain why we needed a complex set of
belaran@999 5342 branches, and how changes ought to flow between them, a few
belaran@999 5343 team members revolted. Even though they were smart people,
belaran@999 5344 they didn't want to pay attention to the constraints we were
belaran@999 5345 operating under, or face the consequences of those constraints
belaran@999 5346 in the details of the model that I was advocating.</para>
belaran@999 5347
belaran@999 5348 <para id="x_454">Don't sweep foreseeable social or technical problems under
belaran@999 5349 the rug. Whatever scheme you put into effect, you should plan
belaran@999 5350 for mistakes and problem scenarios. Consider adding automated
belaran@999 5351 machinery to prevent, or quickly recover from, trouble that
belaran@999 5352 you can anticipate. As an example, if you intend to have a
belaran@999 5353 branch with not-for-release changes in it, you'd do well to
belaran@999 5354 think early about the possibility that someone might
belaran@999 5355 accidentally merge those changes into a release branch. You
belaran@999 5356 could avoid this particular problem by writing a hook that
belaran@999 5357 prevents changes from being merged from an inappropriate
belaran@999 5358 branch.</para>
belaran@999 5359 </sect2>
belaran@999 5360
belaran@999 5361 <sect2>
belaran@999 5362 <title>Informal anarchy</title>
belaran@999 5363
belaran@999 5364 <para id="x_455">I wouldn't suggest an <quote>anything goes</quote>
belaran@999 5365 approach as something sustainable, but it's a model that's
belaran@999 5366 easy to grasp, and it works perfectly well in a few unusual
belaran@999 5367 situations.</para>
belaran@999 5368
belaran@999 5369 <para id="x_456">As one example, many projects have a loose-knit group of
belaran@999 5370 collaborators who rarely physically meet each other. Some
belaran@999 5371 groups like to overcome the isolation of working at a distance
belaran@999 5372 by organizing occasional <quote>sprints</quote>. In a sprint,
belaran@999 5373 a number of people get together in a single location (a
belaran@999 5374 company's conference room, a hotel meeting room, that kind of
belaran@999 5375 place) and spend several days more or less locked in there,
belaran@999 5376 hacking intensely on a handful of projects.</para>
belaran@999 5377
belaran@999 5378 <para id="x_457">A sprint or a hacking session in a coffee shop are the perfect places to use the
belaran@999 5379 <command role="hg-cmd" moreinfo="none">hg serve</command> command, since
belaran@999 5380 <command role="hg-cmd" moreinfo="none">hg serve</command> does not require any
belaran@999 5381 fancy server infrastructure. You can get started with
belaran@999 5382 <command role="hg-cmd" moreinfo="none">hg serve</command> in moments, by
belaran@999 5383 reading <xref linkend="sec:collab:serve"/> below. Then simply
belaran@999 5384 tell the person next to you that you're running a server, send
belaran@999 5385 the URL to them in an instant message, and you immediately
belaran@999 5386 have a quick-turnaround way to work together. They can type
belaran@999 5387 your URL into their web browser and quickly review your
belaran@999 5388 changes; or they can pull a bugfix from you and verify it; or
belaran@999 5389 they can clone a branch containing a new feature and try it
belaran@999 5390 out.</para>
belaran@999 5391
belaran@999 5392 <para id="x_458">The charm, and the problem, with doing things
belaran@999 5393 in an ad hoc fashion like this is that only people who know
belaran@999 5394 about your changes, and where they are, can see them. Such an
belaran@999 5395 informal approach simply doesn't scale beyond a handful
belaran@999 5396 people, because each individual needs to know about
belaran@999 5397 <emphasis>n</emphasis> different repositories to pull
belaran@999 5398 from.</para>
belaran@999 5399 </sect2>
belaran@999 5400
belaran@999 5401 <sect2>
belaran@999 5402 <title>A single central repository</title>
belaran@999 5403
belaran@999 5404 <para id="x_459">For smaller projects migrating from a centralised revision
belaran@999 5405 control tool, perhaps the easiest way to get started is to
belaran@999 5406 have changes flow through a single shared central repository.
belaran@999 5407 This is also the most common <quote>building block</quote> for
belaran@999 5408 more ambitious workflow schemes.</para>
belaran@999 5409
belaran@999 5410 <para id="x_45a">Contributors start by cloning a copy of this repository.
belaran@999 5411 They can pull changes from it whenever they need to, and some
belaran@999 5412 (perhaps all) developers have permission to push a change back
belaran@999 5413 when they're ready for other people to see it.</para>
belaran@999 5414
belaran@999 5415 <para id="x_45b">Under this model, it can still often make sense for people
belaran@999 5416 to pull changes directly from each other, without going
belaran@999 5417 through the central repository. Consider a case in which I
belaran@999 5418 have a tentative bug fix, but I am worried that if I were to
belaran@999 5419 publish it to the central repository, it might subsequently
belaran@999 5420 break everyone else's trees as they pull it. To reduce the
belaran@999 5421 potential for damage, I can ask you to clone my repository
belaran@999 5422 into a temporary repository of your own and test it. This
belaran@999 5423 lets us put off publishing the potentially unsafe change until
belaran@999 5424 it has had a little testing.</para>
belaran@999 5425
belaran@999 5426 <para id="x_45c">If a team is hosting its own repository in this
belaran@999 5427 kind of scenario, people will usually use the
belaran@999 5428 <command moreinfo="none">ssh</command> protocol to securely push changes to
belaran@999 5429 the central repository, as documented in <xref linkend="sec:collab:ssh"/>. It's also usual to publish a
belaran@999 5430 read-only copy of the repository over HTTP, as in
belaran@999 5431 <xref linkend="sec:collab:cgi"/>. Publishing over HTTP
belaran@999 5432 satisfies the needs of people who don't have push access, and
belaran@999 5433 those who want to use web browsers to browse the repository's
belaran@999 5434 history.</para>
belaran@999 5435 </sect2>
belaran@999 5436
belaran@999 5437 <sect2>
belaran@999 5438 <title>A hosted central repository</title>
belaran@999 5439
belaran@999 5440 <para id="x_6a1">A wonderful thing about public hosting services like
belaran@999 5441 <ulink url="http://bitbucket.org/">Bitbucket</ulink> is that
belaran@999 5442 not only do they handle the fiddly server configuration
belaran@999 5443 details, such as user accounts, authentication, and secure
belaran@999 5444 wire protocols, they provide additional infrastructure to make
belaran@999 5445 this model work well.</para>
belaran@999 5446
belaran@999 5447 <para id="x_6a2">For instance, a well-engineered hosting service will let
belaran@999 5448 people clone their own copies of a repository with a single
belaran@999 5449 click. This lets people work in separate spaces and share
belaran@999 5450 their changes when they're ready.</para>
belaran@999 5451
belaran@999 5452 <para id="x_6a3">In addition, a good hosting service will let people
belaran@999 5453 communicate with each other, for instance to say <quote>there
belaran@999 5454 are changes ready for you to review in this
belaran@999 5455 tree</quote>.</para>
belaran@999 5456 </sect2>
belaran@999 5457
belaran@999 5458 <sect2>
belaran@999 5459 <title>Working with multiple branches</title>
belaran@999 5460
belaran@999 5461 <para id="x_45d">Projects of any significant size naturally tend to make
belaran@999 5462 progress on several fronts simultaneously. In the case of
belaran@999 5463 software, it's common for a project to go through periodic
belaran@999 5464 official releases. A release might then go into
belaran@999 5465 <quote>maintenance mode</quote> for a while after its first
belaran@999 5466 publication; maintenance releases tend to contain only bug
belaran@999 5467 fixes, not new features. In parallel with these maintenance
belaran@999 5468 releases, one or more future releases may be under
belaran@999 5469 development. People normally use the word
belaran@999 5470 <quote>branch</quote> to refer to one of these many slightly
belaran@999 5471 different directions in which development is
belaran@999 5472 proceeding.</para>
belaran@999 5473
belaran@999 5474 <para id="x_45e">Mercurial is particularly well suited to managing a number
belaran@999 5475 of simultaneous, but not identical, branches. Each
belaran@999 5476 <quote>development direction</quote> can live in its own
belaran@999 5477 central repository, and you can merge changes from one to
belaran@999 5478 another as the need arises. Because repositories are
belaran@999 5479 independent of each other, unstable changes in a development
belaran@999 5480 branch will never affect a stable branch unless someone
belaran@999 5481 explicitly merges those changes into the stable branch.</para>
belaran@999 5482
belaran@999 5483 <para id="x_45f">Here's an example of how this can work in practice. Let's
belaran@999 5484 say you have one <quote>main branch</quote> on a central
belaran@999 5485 server.</para>
belaran@999 5486
belaran@999 5487 <!-- BEGIN branching.init -->
belaran@999 5488 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init main</userinput>
belaran@999 5489 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main</userinput>
belaran@999 5490 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a boring feature.' &gt; myfile</userinput>
belaran@999 5491 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'We have reached an important milestone!'</userinput>
belaran@999 5492 adding myfile
belaran@999 5493 </screen>
belaran@999 5494 <!-- END branching.init -->
belaran@999 5495
belaran@999 5496
belaran@999 5497 <para id="x_460">People clone it, make changes locally, test them, and push
belaran@999 5498 them back.</para>
belaran@999 5499
belaran@999 5500 <para id="x_461">Once the main branch reaches a release milestone, you can
belaran@999 5501 use the <command role="hg-cmd" moreinfo="none">hg tag</command> command to
belaran@999 5502 give a permanent name to the milestone revision.</para>
belaran@999 5503
belaran@999 5504 <!-- BEGIN branching.tag -->
belaran@999 5505 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
belaran@999 5506 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 5507 changeset: 1:5e447fdaf941
belaran@999 5508 tag: tip
belaran@999 5509 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 5510 date: Sun Aug 16 14:04:47 2009 +0000
belaran@999 5511 summary: Added tag v1.0 for changeset 6412b791fd06
belaran@999 5512
belaran@999 5513 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
belaran@999 5514 tip 1:5e447fdaf941
belaran@999 5515 v1.0 0:6412b791fd06
belaran@999 5516 </screen>
belaran@999 5517 <!-- END branching.tag -->
belaran@999 5518
belaran@999 5519
belaran@999 5520 <para id="x_462">Let's say some ongoing
belaran@999 5521 development occurs on the main branch.</para>
belaran@999 5522
belaran@999 5523 <!-- BEGIN branching.main -->
belaran@999 5524 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput>
belaran@999 5525 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is exciting and new!' &gt;&gt; myfile</userinput>
belaran@999 5526 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add a new feature'</userinput>
belaran@999 5527 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 5528 This is a boring feature.
belaran@999 5529 This is exciting and new!
belaran@999 5530 </screen>
belaran@999 5531 <!-- END branching.main -->
belaran@999 5532
belaran@999 5533
belaran@999 5534 <para id="x_463">Using the tag that was recorded at the milestone, people
belaran@999 5535 who clone that repository at any time in the future can use
belaran@999 5536 <command role="hg-cmd" moreinfo="none">hg update</command> to get a copy of
belaran@999 5537 the working directory exactly as it was when that tagged
belaran@999 5538 revision was committed.</para>
belaran@999 5539
belaran@999 5540 <!-- BEGIN branching.update -->
belaran@999 5541 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 5542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -U main main-old</userinput>
belaran@999 5543 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main-old</userinput>
belaran@999 5544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update v1.0</userinput>
belaran@999 5545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 5546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 5547 This is a boring feature.
belaran@999 5548 </screen>
belaran@999 5549 <!-- END branching.update -->
belaran@999 5550
belaran@999 5551
belaran@999 5552 <para id="x_464">In addition, immediately after the main branch is tagged,
belaran@999 5553 we can then clone the main branch on the server to a new
belaran@999 5554 <quote>stable</quote> branch, also on the server.</para>
belaran@999 5555
belaran@999 5556 <!-- BEGIN branching.clone -->
belaran@999 5557 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 5558 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -rv1.0 main stable</userinput>
belaran@999 5559 requesting all changes
belaran@999 5560 adding changesets
belaran@999 5561 adding manifests
belaran@999 5562 adding file changes
belaran@999 5563 added 1 changesets with 1 changes to 1 files
belaran@999 5564 updating working directory
belaran@999 5565 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 5566 </screen>
belaran@999 5567 <!-- END branching.clone -->
belaran@999 5568
belaran@999 5569
belaran@999 5570 <para id="x_465">If we need to make a change to the stable
belaran@999 5571 branch, we can then clone <emphasis>that</emphasis>
belaran@999 5572 repository, make our changes, commit, and push our changes
belaran@999 5573 back there.</para>
belaran@999 5574
belaran@999 5575 <!-- BEGIN branching.stable -->
belaran@999 5576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone stable stable-fix</userinput>
belaran@999 5577 updating working directory
belaran@999 5578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 5579 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd stable-fix</userinput>
belaran@999 5580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a fix to a boring feature.' &gt; myfile</userinput>
belaran@999 5581 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Fix a bug'</userinput>
belaran@999 5582 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
belaran@999 5583 pushing to /tmp/branchingPsTziR/stable
belaran@999 5584 searching for changes
belaran@999 5585 adding changesets
belaran@999 5586 adding manifests
belaran@999 5587 adding file changes
belaran@999 5588 added 1 changesets with 1 changes to 1 files
belaran@999 5589 </screen>
belaran@999 5590 <!-- END branching.stable -->
belaran@999 5591
belaran@999 5592
belaran@999 5593 <para id="x_466">Because Mercurial repositories are independent, and
belaran@999 5594 Mercurial doesn't move changes around automatically, the
belaran@999 5595 stable and main branches are <emphasis>isolated</emphasis>
belaran@999 5596 from each other. The changes that we made on the main branch
belaran@999 5597 don't <quote>leak</quote> to the stable branch, and vice
belaran@999 5598 versa.</para>
belaran@999 5599
belaran@999 5600 <para id="x_467">We'll often want all of our bugfixes on the stable
belaran@999 5601 branch to show up on the main branch, too. Rather than
belaran@999 5602 rewrite a bugfix on the main branch, we can simply pull and
belaran@999 5603 merge changes from the stable to the main branch, and
belaran@999 5604 Mercurial will bring those bugfixes in for us.</para>
belaran@999 5605
belaran@999 5606 <!-- BEGIN branching.merge -->
belaran@999 5607 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput>
belaran@999 5608 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../stable</userinput>
belaran@999 5609 pulling from ../stable
belaran@999 5610 searching for changes
belaran@999 5611 adding changesets
belaran@999 5612 adding manifests
belaran@999 5613 adding file changes
belaran@999 5614 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 5615 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 5616 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 5617 merging myfile
belaran@999 5618 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
belaran@999 5619 (branch merge, don't forget to commit)
belaran@999 5620 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Bring in bugfix from stable branch'</userinput>
belaran@999 5621 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 5622 This is a fix to a boring feature.
belaran@999 5623 This is exciting and new!
belaran@999 5624 </screen>
belaran@999 5625 <!-- END branching.merge -->
belaran@999 5626
belaran@999 5627
belaran@999 5628 <para id="x_468">The main branch will still contain changes that
belaran@999 5629 are not on the stable branch, but it will also contain all of
belaran@999 5630 the bugfixes from the stable branch. The stable branch
belaran@999 5631 remains unaffected by these changes, since changes are only
belaran@999 5632 flowing from the stable to the main branch, and not the other
belaran@999 5633 way.</para>
belaran@999 5634 </sect2>
belaran@999 5635
belaran@999 5636 <sect2>
belaran@999 5637 <title>Feature branches</title>
belaran@999 5638
belaran@999 5639 <para id="x_469">For larger projects, an effective way to manage change is
belaran@999 5640 to break up a team into smaller groups. Each group has a
belaran@999 5641 shared branch of its own, cloned from a single
belaran@999 5642 <quote>master</quote> branch used by the entire project.
belaran@999 5643 People working on an individual branch are typically quite
belaran@999 5644 isolated from developments on other branches.</para>
belaran@999 5645
belaran@999 5646 <figure id="fig:collab:feature-branches" float="0">
belaran@999 5647 <title>Feature branches</title>
belaran@999 5648 <mediaobject>
belaran@999 5649 <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject>
belaran@999 5650 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 5651 </mediaobject>
belaran@999 5652 </figure>
belaran@999 5653
belaran@999 5654 <para id="x_46b">When a particular feature is deemed to be in suitable
belaran@999 5655 shape, someone on that feature team pulls and merges from the
belaran@999 5656 master branch into the feature branch, then pushes back up to
belaran@999 5657 the master branch.</para>
belaran@999 5658 </sect2>
belaran@999 5659
belaran@999 5660 <sect2>
belaran@999 5661 <title>The release train</title>
belaran@999 5662
belaran@999 5663 <para id="x_46c">Some projects are organized on a <quote>train</quote>
belaran@999 5664 basis: a release is scheduled to happen every few months, and
belaran@999 5665 whatever features are ready when the <quote>train</quote> is
belaran@999 5666 ready to leave are allowed in.</para>
belaran@999 5667
belaran@999 5668 <para id="x_46d">This model resembles working with feature branches. The
belaran@999 5669 difference is that when a feature branch misses a train,
belaran@999 5670 someone on the feature team pulls and merges the changes that
belaran@999 5671 went out on that train release into the feature branch, and
belaran@999 5672 the team continues its work on top of that release so that
belaran@999 5673 their feature can make the next release.</para>
belaran@999 5674 </sect2>
belaran@999 5675
belaran@999 5676 <sect2>
belaran@999 5677 <title>The Linux kernel model</title>
belaran@999 5678
belaran@999 5679 <para id="x_46e">The development of the Linux kernel has a shallow
belaran@999 5680 hierarchical structure, surrounded by a cloud of apparent
belaran@999 5681 chaos. Because most Linux developers use
belaran@999 5682 <command moreinfo="none">git</command>, a distributed revision control tool
belaran@999 5683 with capabilities similar to Mercurial, it's useful to
belaran@999 5684 describe the way work flows in that environment; if you like
belaran@999 5685 the ideas, the approach translates well across tools.</para>
belaran@999 5686
belaran@999 5687 <para id="x_46f">At the center of the community sits Linus Torvalds, the
belaran@999 5688 creator of Linux. He publishes a single source repository
belaran@999 5689 that is considered the <quote>authoritative</quote> current
belaran@999 5690 tree by the entire developer community. Anyone can clone
belaran@999 5691 Linus's tree, but he is very choosy about whose trees he pulls
belaran@999 5692 from.</para>
belaran@999 5693
belaran@999 5694 <para id="x_470">Linus has a number of <quote>trusted lieutenants</quote>.
belaran@999 5695 As a general rule, he pulls whatever changes they publish, in
belaran@999 5696 most cases without even reviewing those changes. Some of
belaran@999 5697 those lieutenants are generally agreed to be
belaran@999 5698 <quote>maintainers</quote>, responsible for specific
belaran@999 5699 subsystems within the kernel. If a random kernel hacker wants
belaran@999 5700 to make a change to a subsystem that they want to end up in
belaran@999 5701 Linus's tree, they must find out who the subsystem's
belaran@999 5702 maintainer is, and ask that maintainer to take their change.
belaran@999 5703 If the maintainer reviews their changes and agrees to take
belaran@999 5704 them, they'll pass them along to Linus in due course.</para>
belaran@999 5705
belaran@999 5706 <para id="x_471">Individual lieutenants have their own approaches to
belaran@999 5707 reviewing, accepting, and publishing changes; and for deciding
belaran@999 5708 when to feed them to Linus. In addition, there are several
belaran@999 5709 well known branches that people use for different purposes.
belaran@999 5710 For example, a few people maintain <quote>stable</quote>
belaran@999 5711 repositories of older versions of the kernel, to which they
belaran@999 5712 apply critical fixes as needed. Some maintainers publish
belaran@999 5713 multiple trees: one for experimental changes; one for changes
belaran@999 5714 that they are about to feed upstream; and so on. Others just
belaran@999 5715 publish a single tree.</para>
belaran@999 5716
belaran@999 5717 <para id="x_472">This model has two notable features. The first is that
belaran@999 5718 it's <quote>pull only</quote>. You have to ask, convince, or
belaran@999 5719 beg another developer to take a change from you, because there
belaran@999 5720 are almost no trees to which more than one person can push,
belaran@999 5721 and there's no way to push changes into a tree that someone
belaran@999 5722 else controls.</para>
belaran@999 5723
belaran@999 5724 <para id="x_473">The second is that it's based on reputation and acclaim.
belaran@999 5725 If you're an unknown, Linus will probably ignore changes from
belaran@999 5726 you without even responding. But a subsystem maintainer will
belaran@999 5727 probably review them, and will likely take them if they pass
belaran@999 5728 their criteria for suitability. The more <quote>good</quote>
belaran@999 5729 changes you contribute to a maintainer, the more likely they
belaran@999 5730 are to trust your judgment and accept your changes. If you're
belaran@999 5731 well-known and maintain a long-lived branch for something
belaran@999 5732 Linus hasn't yet accepted, people with similar interests may
belaran@999 5733 pull your changes regularly to keep up with your work.</para>
belaran@999 5734
belaran@999 5735 <para id="x_474">Reputation and acclaim don't necessarily cross subsystem
belaran@999 5736 or <quote>people</quote> boundaries. If you're a respected
belaran@999 5737 but specialised storage hacker, and you try to fix a
belaran@999 5738 networking bug, that change will receive a level of scrutiny
belaran@999 5739 from a network maintainer comparable to a change from a
belaran@999 5740 complete stranger.</para>
belaran@999 5741
belaran@999 5742 <para id="x_475">To people who come from more orderly project backgrounds,
belaran@999 5743 the comparatively chaotic Linux kernel development process
belaran@999 5744 often seems completely insane. It's subject to the whims of
belaran@999 5745 individuals; people make sweeping changes whenever they deem
belaran@999 5746 it appropriate; and the pace of development is astounding.
belaran@999 5747 And yet Linux is a highly successful, well-regarded piece of
belaran@999 5748 software.</para>
belaran@999 5749 </sect2>
belaran@999 5750
belaran@999 5751 <sect2>
belaran@999 5752 <title>Pull-only versus shared-push collaboration</title>
belaran@999 5753
belaran@999 5754 <para id="x_476">A perpetual source of heat in the open source community is
belaran@999 5755 whether a development model in which people only ever pull
belaran@999 5756 changes from others is <quote>better than</quote> one in which
belaran@999 5757 multiple people can push changes to a shared
belaran@999 5758 repository.</para>
belaran@999 5759
belaran@999 5760 <para id="x_477">Typically, the backers of the shared-push model use tools
belaran@999 5761 that actively enforce this approach. If you're using a
belaran@999 5762 centralised revision control tool such as Subversion, there's
belaran@999 5763 no way to make a choice over which model you'll use: the tool
belaran@999 5764 gives you shared-push, and if you want to do anything else,
belaran@999 5765 you'll have to roll your own approach on top (such as applying
belaran@999 5766 a patch by hand).</para>
belaran@999 5767
belaran@999 5768 <para id="x_478">A good distributed revision control tool will
belaran@999 5769 support both models. You and your collaborators can then
belaran@999 5770 structure how you work together based on your own needs and
belaran@999 5771 preferences, not on what contortions your tools force you
belaran@999 5772 into.</para>
belaran@999 5773 </sect2>
belaran@999 5774 <sect2>
belaran@999 5775 <title>Where collaboration meets branch management</title>
belaran@999 5776
belaran@999 5777 <para id="x_479">Once you and your team set up some shared
belaran@999 5778 repositories and start propagating changes back and forth
belaran@999 5779 between local and shared repos, you begin to face a related,
belaran@999 5780 but slightly different challenge: that of managing the
belaran@999 5781 multiple directions in which your team may be moving at once.
belaran@999 5782 Even though this subject is intimately related to how your
belaran@999 5783 team collaborates, it's dense enough to merit treatment of its
belaran@999 5784 own, in <xref linkend="chap:branch"/>.</para>
belaran@999 5785 </sect2>
belaran@999 5786 </sect1>
belaran@999 5787
belaran@999 5788 <sect1>
belaran@999 5789 <title>The technical side of sharing</title>
belaran@999 5790
belaran@999 5791 <para id="x_47a">The remainder of this chapter is devoted to the question of
belaran@999 5792 sharing changes with your collaborators.</para>
belaran@999 5793 </sect1>
belaran@999 5794
belaran@999 5795 <sect1 id="sec:collab:serve">
belaran@999 5796 <title>Informal sharing with <command role="hg-cmd" moreinfo="none">hg
belaran@999 5797 serve</command></title>
belaran@999 5798
belaran@999 5799 <para id="x_47b">Mercurial's <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5800 command is wonderfully suited to small, tight-knit, and
belaran@999 5801 fast-paced group environments. It also provides a great way to
belaran@999 5802 get a feel for using Mercurial commands over a network.</para>
belaran@999 5803
belaran@999 5804 <para id="x_47c">Run <command role="hg-cmd" moreinfo="none">hg serve</command> inside a
belaran@999 5805 repository, and in under a second it will bring up a specialised
belaran@999 5806 HTTP server; this will accept connections from any client, and
belaran@999 5807 serve up data for that repository until you terminate it.
belaran@999 5808 Anyone who knows the URL of the server you just started, and can
belaran@999 5809 talk to your computer over the network, can then use a web
belaran@999 5810 browser or Mercurial to read data from that repository. A URL
belaran@999 5811 for a <command role="hg-cmd" moreinfo="none">hg serve</command> instance running
belaran@999 5812 on a laptop is likely to look something like
belaran@999 5813 <literal moreinfo="none">http://my-laptop.local:8000/</literal>.</para>
belaran@999 5814
belaran@999 5815 <para id="x_47d">The <command role="hg-cmd" moreinfo="none">hg serve</command> command is
belaran@999 5816 <emphasis>not</emphasis> a general-purpose web server. It can do
belaran@999 5817 only two things:</para>
belaran@999 5818 <itemizedlist>
belaran@999 5819 <listitem><para id="x_47e">Allow people to browse the history of the
belaran@999 5820 repository it's serving, from their normal web
belaran@999 5821 browsers.</para>
belaran@999 5822 </listitem>
belaran@999 5823 <listitem><para id="x_47f">Speak Mercurial's wire protocol, so that people
belaran@999 5824 can <command role="hg-cmd" moreinfo="none">hg clone</command> or <command role="hg-cmd" moreinfo="none">hg pull</command> changes from that
belaran@999 5825 repository.</para>
belaran@999 5826 </listitem></itemizedlist>
belaran@999 5827 <para id="x_480">In particular, <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5828 won't allow remote users to <emphasis>modify</emphasis> your
belaran@999 5829 repository. It's intended for read-only use.</para>
belaran@999 5830
belaran@999 5831 <para id="x_481">If you're getting started with Mercurial, there's nothing to
belaran@999 5832 prevent you from using <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5833 to serve up a repository on your own computer, then use commands
belaran@999 5834 like <command role="hg-cmd" moreinfo="none">hg clone</command>, <command role="hg-cmd" moreinfo="none">hg incoming</command>, and so on to talk to that
belaran@999 5835 server as if the repository was hosted remotely. This can help
belaran@999 5836 you to quickly get acquainted with using commands on
belaran@999 5837 network-hosted repositories.</para>
belaran@999 5838
belaran@999 5839 <sect2>
belaran@999 5840 <title>A few things to keep in mind</title>
belaran@999 5841
belaran@999 5842 <para id="x_482">Because it provides unauthenticated read access to all
belaran@999 5843 clients, you should only use <command role="hg-cmd" moreinfo="none">hg
belaran@999 5844 serve</command> in an environment where you either don't
belaran@999 5845 care, or have complete control over, who can access your
belaran@999 5846 network and pull data from your repository.</para>
belaran@999 5847
belaran@999 5848 <para id="x_483">The <command role="hg-cmd" moreinfo="none">hg serve</command> command
belaran@999 5849 knows nothing about any firewall software you might have
belaran@999 5850 installed on your system or network. It cannot detect or
belaran@999 5851 control your firewall software. If other people are unable to
belaran@999 5852 talk to a running <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5853 instance, the second thing you should do
belaran@999 5854 (<emphasis>after</emphasis> you make sure that they're using
belaran@999 5855 the correct URL) is check your firewall configuration.</para>
belaran@999 5856
belaran@999 5857 <para id="x_484">By default, <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5858 listens for incoming connections on port 8000. If another
belaran@999 5859 process is already listening on the port you want to use, you
belaran@999 5860 can specify a different port to listen on using the <option role="hg-opt-serve">-p</option> option.</para>
belaran@999 5861
belaran@999 5862 <para id="x_485">Normally, when <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 5863 starts, it prints no output, which can be a bit unnerving. If
belaran@999 5864 you'd like to confirm that it is indeed running correctly, and
belaran@999 5865 find out what URL you should send to your collaborators, start
belaran@999 5866 it with the <option role="hg-opt-global">-v</option>
belaran@999 5867 option.</para>
belaran@999 5868 </sect2>
belaran@999 5869 </sect1>
belaran@999 5870
belaran@999 5871 <sect1 id="sec:collab:ssh">
belaran@999 5872 <title>Using the Secure Shell (ssh) protocol</title>
belaran@999 5873
belaran@999 5874 <para id="x_486">You can pull and push changes securely over a network
belaran@999 5875 connection using the Secure Shell (<literal moreinfo="none">ssh</literal>)
belaran@999 5876 protocol. To use this successfully, you may have to do a little
belaran@999 5877 bit of configuration on the client or server sides.</para>
belaran@999 5878
belaran@999 5879 <para id="x_487">If you're not familiar with ssh, it's the name of
belaran@999 5880 both a command and a network protocol that let you securely
belaran@999 5881 communicate with another computer. To use it with Mercurial,
belaran@999 5882 you'll be setting up one or more user accounts on a server so
belaran@999 5883 that remote users can log in and execute commands.</para>
belaran@999 5884
belaran@999 5885 <para id="x_488">(If you <emphasis>are</emphasis> familiar with ssh, you'll
belaran@999 5886 probably find some of the material that follows to be elementary
belaran@999 5887 in nature.)</para>
belaran@999 5888
belaran@999 5889 <sect2>
belaran@999 5890 <title>How to read and write ssh URLs</title>
belaran@999 5891
belaran@999 5892 <para id="x_489">An ssh URL tends to look like this:</para>
belaran@999 5893 <programlisting format="linespecific">ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting>
belaran@999 5894 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 5895 <listitem><para id="x_48a">The <quote><literal moreinfo="none">ssh://</literal></quote>
belaran@999 5896 part tells Mercurial to use the ssh protocol.</para>
belaran@999 5897 </listitem>
belaran@999 5898 <listitem><para id="x_48b">The <quote><literal moreinfo="none">bos@</literal></quote>
belaran@999 5899 component indicates what username to log into the server
belaran@999 5900 as. You can leave this out if the remote username is the
belaran@999 5901 same as your local username.</para>
belaran@999 5902 </listitem>
belaran@999 5903 <listitem><para id="x_48c">The
belaran@999 5904 <quote><literal moreinfo="none">hg.serpentine.com</literal></quote> gives
belaran@999 5905 the hostname of the server to log into.</para>
belaran@999 5906 </listitem>
belaran@999 5907 <listitem><para id="x_48d">The <quote>:22</quote> identifies the port
belaran@999 5908 number to connect to the server on. The default port is
belaran@999 5909 22, so you only need to specify a colon and port number if
belaran@999 5910 you're <emphasis>not</emphasis> using port 22.</para>
belaran@999 5911 </listitem>
belaran@999 5912 <listitem><para id="x_48e">The remainder of the URL is the local path to
belaran@999 5913 the repository on the server.</para>
belaran@999 5914 </listitem></orderedlist>
belaran@999 5915
belaran@999 5916 <para id="x_48f">There's plenty of scope for confusion with the path
belaran@999 5917 component of ssh URLs, as there is no standard way for tools
belaran@999 5918 to interpret it. Some programs behave differently than others
belaran@999 5919 when dealing with these paths. This isn't an ideal situation,
belaran@999 5920 but it's unlikely to change. Please read the following
belaran@999 5921 paragraphs carefully.</para>
belaran@999 5922
belaran@999 5923 <para id="x_490">Mercurial treats the path to a repository on the server as
belaran@999 5924 relative to the remote user's home directory. For example, if
belaran@999 5925 user <literal moreinfo="none">foo</literal> on the server has a home directory
belaran@999 5926 of <filename class="directory" moreinfo="none">/home/foo</filename>, then an
belaran@999 5927 ssh URL that contains a path component of <filename class="directory" moreinfo="none">bar</filename> <emphasis>really</emphasis>
belaran@999 5928 refers to the directory <filename class="directory" moreinfo="none">/home/foo/bar</filename>.</para>
belaran@999 5929
belaran@999 5930 <para id="x_491">If you want to specify a path relative to another user's
belaran@999 5931 home directory, you can use a path that starts with a tilde
belaran@999 5932 character followed by the user's name (let's call them
belaran@999 5933 <literal moreinfo="none">otheruser</literal>), like this.</para>
belaran@999 5934 <programlisting format="linespecific">ssh://server/~otheruser/hg/repo</programlisting>
belaran@999 5935
belaran@999 5936 <para id="x_492">And if you really want to specify an
belaran@999 5937 <emphasis>absolute</emphasis> path on the server, begin the
belaran@999 5938 path component with two slashes, as in this example.</para>
belaran@999 5939 <programlisting format="linespecific">ssh://server//absolute/path</programlisting>
belaran@999 5940 </sect2>
belaran@999 5941
belaran@999 5942 <sect2>
belaran@999 5943 <title>Finding an ssh client for your system</title>
belaran@999 5944
belaran@999 5945 <para id="x_493">Almost every Unix-like system comes with OpenSSH
belaran@999 5946 preinstalled. If you're using such a system, run
belaran@999 5947 <literal moreinfo="none">which ssh</literal> to find out if the
belaran@999 5948 <command moreinfo="none">ssh</command> command is installed (it's usually in
belaran@999 5949 <filename class="directory" moreinfo="none">/usr/bin</filename>). In the
belaran@999 5950 unlikely event that it isn't present, take a look at your
belaran@999 5951 system documentation to figure out how to install it.</para>
belaran@999 5952
belaran@999 5953 <para id="x_494">On Windows, the TortoiseHg package is bundled
belaran@999 5954 with a version of Simon Tatham's excellent
belaran@999 5955 <command moreinfo="none">plink</command> command, and you should not need to
belaran@999 5956 do any further configuration.</para>
belaran@999 5957 </sect2>
belaran@999 5958
belaran@999 5959 <sect2>
belaran@999 5960 <title>Generating a key pair</title>
belaran@999 5961
belaran@999 5962 <para id="x_499">To avoid the need to repetitively type a
belaran@999 5963 password every time you need to use your ssh client, I
belaran@999 5964 recommend generating a key pair.</para>
belaran@999 5965
belaran@999 5966 <tip>
belaran@999 5967 <title>Key pairs are not mandatory</title>
belaran@999 5968
belaran@999 5969 <para id="x_6a4">Mercurial knows nothing about ssh authentication or key
belaran@999 5970 pairs. You can, if you like, safely ignore this section and
belaran@999 5971 the one that follows until you grow tired of repeatedly
belaran@999 5972 typing ssh passwords.</para>
belaran@999 5973 </tip>
belaran@999 5974
belaran@999 5975 <itemizedlist>
belaran@999 5976 <listitem>
belaran@999 5977 <para id="x_6a5">On a Unix-like system, the
belaran@999 5978 <command moreinfo="none">ssh-keygen</command> command will do the
belaran@999 5979 trick.</para>
belaran@999 5980 <para id="x_6a6">On Windows, if you're using TortoiseHg, you may need
belaran@999 5981 to download a command named <command moreinfo="none">puttygen</command>
belaran@999 5982 from <ulink url="http://www.chiark.greenend.org.uk/~sgtatham/putty">the
belaran@999 5983 PuTTY web site</ulink> to generate a key pair. See
belaran@999 5984 <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">the
belaran@999 5985 <command moreinfo="none">puttygen</command> documentation</ulink> for
belaran@999 5986 details of how use the command.</para>
belaran@999 5987 </listitem>
belaran@999 5988 </itemizedlist>
belaran@999 5989
belaran@999 5990 <para id="x_49a">When you generate a key pair, it's usually
belaran@999 5991 <emphasis>highly</emphasis> advisable to protect it with a
belaran@999 5992 passphrase. (The only time that you might not want to do this
belaran@999 5993 is when you're using the ssh protocol for automated tasks on a
belaran@999 5994 secure network.)</para>
belaran@999 5995
belaran@999 5996 <para id="x_49b">Simply generating a key pair isn't enough, however.
belaran@999 5997 You'll need to add the public key to the set of authorised
belaran@999 5998 keys for whatever user you're logging in remotely as. For
belaran@999 5999 servers using OpenSSH (the vast majority), this will mean
belaran@999 6000 adding the public key to a list in a file called <filename role="special" moreinfo="none">authorized_keys</filename> in their <filename role="special" class="directory" moreinfo="none">.ssh</filename>
belaran@999 6001 directory.</para>
belaran@999 6002
belaran@999 6003 <para id="x_49c">On a Unix-like system, your public key will have a
belaran@999 6004 <filename moreinfo="none">.pub</filename> extension. If you're using
belaran@999 6005 <command moreinfo="none">puttygen</command> on Windows, you can save the
belaran@999 6006 public key to a file of your choosing, or paste it from the
belaran@999 6007 window it's displayed in straight into the <filename role="special" moreinfo="none">authorized_keys</filename> file.</para>
belaran@999 6008 </sect2>
belaran@999 6009 <sect2>
belaran@999 6010 <title>Using an authentication agent</title>
belaran@999 6011
belaran@999 6012 <para id="x_49d">An authentication agent is a daemon that stores
belaran@999 6013 passphrases in memory (so it will forget passphrases if you
belaran@999 6014 log out and log back in again). An ssh client will notice if
belaran@999 6015 it's running, and query it for a passphrase. If there's no
belaran@999 6016 authentication agent running, or the agent doesn't store the
belaran@999 6017 necessary passphrase, you'll have to type your passphrase
belaran@999 6018 every time Mercurial tries to communicate with a server on
belaran@999 6019 your behalf (e.g. whenever you pull or push changes).</para>
belaran@999 6020
belaran@999 6021 <para id="x_49e">The downside of storing passphrases in an agent is that
belaran@999 6022 it's possible for a well-prepared attacker to recover the
belaran@999 6023 plain text of your passphrases, in some cases even if your
belaran@999 6024 system has been power-cycled. You should make your own
belaran@999 6025 judgment as to whether this is an acceptable risk. It
belaran@999 6026 certainly saves a lot of repeated typing.</para>
belaran@999 6027
belaran@999 6028 <itemizedlist>
belaran@999 6029 <listitem>
belaran@999 6030 <para id="x_49f">On Unix-like systems, the agent is called
belaran@999 6031 <command moreinfo="none">ssh-agent</command>, and it's often run
belaran@999 6032 automatically for you when you log in. You'll need to use
belaran@999 6033 the <command moreinfo="none">ssh-add</command> command to add passphrases
belaran@999 6034 to the agent's store.</para>
belaran@999 6035 </listitem>
belaran@999 6036 <listitem>
belaran@999 6037 <para id="x_6a7">On Windows, if you're using TortoiseHg, the
belaran@999 6038 <command moreinfo="none">pageant</command> command acts as the agent. As
belaran@999 6039 with <command moreinfo="none">puttygen</command>, you'll need to <ulink url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">download
belaran@999 6040 <command moreinfo="none">pageant</command></ulink> from the PuTTY web
belaran@999 6041 site and read <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">its
belaran@999 6042 documentation</ulink>. The <command moreinfo="none">pageant</command>
belaran@999 6043 command adds an icon to your system tray that will let you
belaran@999 6044 manage stored passphrases.</para>
belaran@999 6045 </listitem>
belaran@999 6046 </itemizedlist>
belaran@999 6047 </sect2>
belaran@999 6048
belaran@999 6049 <sect2>
belaran@999 6050 <title>Configuring the server side properly</title>
belaran@999 6051
belaran@999 6052 <para id="x_4a0">Because ssh can be fiddly to set up if you're new to it,
belaran@999 6053 a variety of things can go wrong. Add Mercurial
belaran@999 6054 on top, and there's plenty more scope for head-scratching.
belaran@999 6055 Most of these potential problems occur on the server side, not
belaran@999 6056 the client side. The good news is that once you've gotten a
belaran@999 6057 configuration working, it will usually continue to work
belaran@999 6058 indefinitely.</para>
belaran@999 6059
belaran@999 6060 <para id="x_4a1">Before you try using Mercurial to talk to an ssh server,
belaran@999 6061 it's best to make sure that you can use the normal
belaran@999 6062 <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> command to
belaran@999 6063 talk to the server first. If you run into problems with using
belaran@999 6064 these commands directly, Mercurial surely won't work. Worse,
belaran@999 6065 it will obscure the underlying problem. Any time you want to
belaran@999 6066 debug ssh-related Mercurial problems, you should drop back to
belaran@999 6067 making sure that plain ssh client commands work first,
belaran@999 6068 <emphasis>before</emphasis> you worry about whether there's a
belaran@999 6069 problem with Mercurial.</para>
belaran@999 6070
belaran@999 6071 <para id="x_4a2">The first thing to be sure of on the server side is that
belaran@999 6072 you can actually log in from another machine at all. If you
belaran@999 6073 can't use <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command>
belaran@999 6074 to log in, the error message you get may give you a few hints
belaran@999 6075 as to what's wrong. The most common problems are as
belaran@999 6076 follows.</para>
belaran@999 6077 <itemizedlist>
belaran@999 6078 <listitem><para id="x_4a3">If you get a <quote>connection refused</quote>
belaran@999 6079 error, either there isn't an SSH daemon running on the
belaran@999 6080 server at all, or it's inaccessible due to firewall
belaran@999 6081 configuration.</para>
belaran@999 6082 </listitem>
belaran@999 6083 <listitem><para id="x_4a4">If you get a <quote>no route to host</quote>
belaran@999 6084 error, you either have an incorrect address for the server
belaran@999 6085 or a seriously locked down firewall that won't admit its
belaran@999 6086 existence at all.</para>
belaran@999 6087 </listitem>
belaran@999 6088 <listitem><para id="x_4a5">If you get a <quote>permission denied</quote>
belaran@999 6089 error, you may have mistyped the username on the server,
belaran@999 6090 or you could have mistyped your key's passphrase or the
belaran@999 6091 remote user's password.</para>
belaran@999 6092 </listitem></itemizedlist>
belaran@999 6093 <para id="x_4a6">In summary, if you're having trouble talking to the
belaran@999 6094 server's ssh daemon, first make sure that one is running at
belaran@999 6095 all. On many systems it will be installed, but disabled, by
belaran@999 6096 default. Once you're done with this step, you should then
belaran@999 6097 check that the server's firewall is configured to allow
belaran@999 6098 incoming connections on the port the ssh daemon is listening
belaran@999 6099 on (usually 22). Don't worry about more exotic possibilities
belaran@999 6100 for misconfiguration until you've checked these two
belaran@999 6101 first.</para>
belaran@999 6102
belaran@999 6103 <para id="x_4a7">If you're using an authentication agent on the client side
belaran@999 6104 to store passphrases for your keys, you ought to be able to
belaran@999 6105 log into the server without being prompted for a passphrase or
belaran@999 6106 a password. If you're prompted for a passphrase, there are a
belaran@999 6107 few possible culprits.</para>
belaran@999 6108 <itemizedlist>
belaran@999 6109 <listitem><para id="x_4a8">You might have forgotten to use
belaran@999 6110 <command moreinfo="none">ssh-add</command> or <command moreinfo="none">pageant</command>
belaran@999 6111 to store the passphrase.</para>
belaran@999 6112 </listitem>
belaran@999 6113 <listitem><para id="x_4a9">You might have stored the passphrase for the
belaran@999 6114 wrong key.</para>
belaran@999 6115 </listitem></itemizedlist>
belaran@999 6116 <para id="x_4aa">If you're being prompted for the remote user's password,
belaran@999 6117 there are another few possible problems to check.</para>
belaran@999 6118 <itemizedlist>
belaran@999 6119 <listitem><para id="x_4ab">Either the user's home directory or their
belaran@999 6120 <filename role="special" class="directory" moreinfo="none">.ssh</filename>
belaran@999 6121 directory might have excessively liberal permissions. As
belaran@999 6122 a result, the ssh daemon will not trust or read their
belaran@999 6123 <filename role="special" moreinfo="none">authorized_keys</filename> file.
belaran@999 6124 For example, a group-writable home or <filename role="special" class="directory" moreinfo="none">.ssh</filename>
belaran@999 6125 directory will often cause this symptom.</para>
belaran@999 6126 </listitem>
belaran@999 6127 <listitem><para id="x_4ac">The user's <filename role="special" moreinfo="none">authorized_keys</filename> file may have
belaran@999 6128 a problem. If anyone other than the user owns or can write
belaran@999 6129 to that file, the ssh daemon will not trust or read
belaran@999 6130 it.</para>
belaran@999 6131 </listitem></itemizedlist>
belaran@999 6132
belaran@999 6133 <para id="x_4ad">In the ideal world, you should be able to run the
belaran@999 6134 following command successfully, and it should print exactly
belaran@999 6135 one line of output, the current date and time.</para>
belaran@999 6136 <programlisting format="linespecific">ssh myserver date</programlisting>
belaran@999 6137
belaran@999 6138 <para id="x_4ae">If, on your server, you have login scripts that print
belaran@999 6139 banners or other junk even when running non-interactive
belaran@999 6140 commands like this, you should fix them before you continue,
belaran@999 6141 so that they only print output if they're run interactively.
belaran@999 6142 Otherwise these banners will at least clutter up Mercurial's
belaran@999 6143 output. Worse, they could potentially cause problems with
belaran@999 6144 running Mercurial commands remotely. Mercurial tries to
belaran@999 6145 detect and ignore banners in non-interactive
belaran@999 6146 <command moreinfo="none">ssh</command> sessions, but it is not foolproof. (If
belaran@999 6147 you're editing your login scripts on your server, the usual
belaran@999 6148 way to see if a login script is running in an interactive
belaran@999 6149 shell is to check the return code from the command
belaran@999 6150 <literal moreinfo="none">tty -s</literal>.)</para>
belaran@999 6151
belaran@999 6152 <para id="x_4af">Once you've verified that plain old ssh is working with
belaran@999 6153 your server, the next step is to ensure that Mercurial runs on
belaran@999 6154 the server. The following command should run
belaran@999 6155 successfully:</para>
belaran@999 6156
belaran@999 6157 <programlisting format="linespecific">ssh myserver hg version</programlisting>
belaran@999 6158
belaran@999 6159 <para id="x_4b0">If you see an error message instead of normal <command role="hg-cmd" moreinfo="none">hg version</command> output, this is usually
belaran@999 6160 because you haven't installed Mercurial to <filename class="directory" moreinfo="none">/usr/bin</filename>. Don't worry if this
belaran@999 6161 is the case; you don't need to do that. But you should check
belaran@999 6162 for a few possible problems.</para>
belaran@999 6163 <itemizedlist>
belaran@999 6164 <listitem><para id="x_4b1">Is Mercurial really installed on the server at
belaran@999 6165 all? I know this sounds trivial, but it's worth
belaran@999 6166 checking!</para>
belaran@999 6167 </listitem>
belaran@999 6168 <listitem><para id="x_4b2">Maybe your shell's search path (usually set
belaran@999 6169 via the <envar>PATH</envar> environment variable) is
belaran@999 6170 simply misconfigured.</para>
belaran@999 6171 </listitem>
belaran@999 6172 <listitem><para id="x_4b3">Perhaps your <envar>PATH</envar> environment
belaran@999 6173 variable is only being set to point to the location of the
belaran@999 6174 <command moreinfo="none">hg</command> executable if the login session is
belaran@999 6175 interactive. This can happen if you're setting the path
belaran@999 6176 in the wrong shell login script. See your shell's
belaran@999 6177 documentation for details.</para>
belaran@999 6178 </listitem>
belaran@999 6179 <listitem><para id="x_4b4">The <envar>PYTHONPATH</envar> environment
belaran@999 6180 variable may need to contain the path to the Mercurial
belaran@999 6181 Python modules. It might not be set at all; it could be
belaran@999 6182 incorrect; or it may be set only if the login is
belaran@999 6183 interactive.</para>
belaran@999 6184 </listitem></itemizedlist>
belaran@999 6185
belaran@999 6186 <para id="x_4b5">If you can run <command role="hg-cmd" moreinfo="none">hg version</command>
belaran@999 6187 over an ssh connection, well done! You've got the server and
belaran@999 6188 client sorted out. You should now be able to use Mercurial to
belaran@999 6189 access repositories hosted by that username on that server.
belaran@999 6190 If you run into problems with Mercurial and ssh at this point,
belaran@999 6191 try using the <option role="hg-opt-global">--debug</option>
belaran@999 6192 option to get a clearer picture of what's going on.</para>
belaran@999 6193 </sect2>
belaran@999 6194 <sect2>
belaran@999 6195 <title>Using compression with ssh</title>
belaran@999 6196
belaran@999 6197 <para id="x_4b6">Mercurial does not compress data when it uses the ssh
belaran@999 6198 protocol, because the ssh protocol can transparently compress
belaran@999 6199 data. However, the default behavior of ssh clients is
belaran@999 6200 <emphasis>not</emphasis> to request compression.</para>
belaran@999 6201
belaran@999 6202 <para id="x_4b7">Over any network other than a fast LAN (even a wireless
belaran@999 6203 network), using compression is likely to significantly speed
belaran@999 6204 up Mercurial's network operations. For example, over a WAN,
belaran@999 6205 someone measured compression as reducing the amount of time
belaran@999 6206 required to clone a particularly large repository from 51
belaran@999 6207 minutes to 17 minutes.</para>
belaran@999 6208
belaran@999 6209 <para id="x_4b8">Both <command moreinfo="none">ssh</command> and <command moreinfo="none">plink</command>
belaran@999 6210 accept a <option role="cmd-opt-ssh">-C</option> option which
belaran@999 6211 turns on compression. You can easily edit your <filename role="special" moreinfo="none">~/.hgrc</filename> to enable compression for
belaran@999 6212 all of Mercurial's uses of the ssh protocol. Here is how to
belaran@999 6213 do so for regular <command moreinfo="none">ssh</command> on Unix-like systems,
belaran@999 6214 for example.</para>
belaran@999 6215 <programlisting format="linespecific">[ui]
belaran@999 6216 ssh = ssh -C</programlisting>
belaran@999 6217
belaran@999 6218 <para id="x_4b9">If you use <command moreinfo="none">ssh</command> on a
belaran@999 6219 Unix-like system, you can configure it to always use
belaran@999 6220 compression when talking to your server. To do this, edit
belaran@999 6221 your <filename role="special" moreinfo="none">.ssh/config</filename> file
belaran@999 6222 (which may not yet exist), as follows.</para>
belaran@999 6223
belaran@999 6224 <programlisting format="linespecific">Host hg
belaran@999 6225 Compression yes
belaran@999 6226 HostName hg.example.com</programlisting>
belaran@999 6227
belaran@999 6228 <para id="x_4ba">This defines a hostname alias,
belaran@999 6229 <literal moreinfo="none">hg</literal>. When you use that hostname on the
belaran@999 6230 <command moreinfo="none">ssh</command> command line or in a Mercurial
belaran@999 6231 <literal moreinfo="none">ssh</literal>-protocol URL, it will cause
belaran@999 6232 <command moreinfo="none">ssh</command> to connect to
belaran@999 6233 <literal moreinfo="none">hg.example.com</literal> and use compression. This
belaran@999 6234 gives you both a shorter name to type and compression, each of
belaran@999 6235 which is a good thing in its own right.</para>
belaran@999 6236 </sect2>
belaran@999 6237 </sect1>
belaran@999 6238
belaran@999 6239 <sect1 id="sec:collab:cgi">
belaran@999 6240 <title>Serving over HTTP using CGI</title>
belaran@999 6241
belaran@999 6242 <para id="x_6a8">The simplest way to host one or more repositories in a
belaran@999 6243 permanent way is to use a web server and Mercurial's CGI
belaran@999 6244 support.</para>
belaran@999 6245
belaran@999 6246 <para id="x_4bb">Depending on how ambitious you are, configuring Mercurial's
belaran@999 6247 CGI interface can take anything from a few moments to several
belaran@999 6248 hours.</para>
belaran@999 6249
belaran@999 6250 <para id="x_4bc">We'll begin with the simplest of examples, and work our way
belaran@999 6251 towards a more complex configuration. Even for the most basic
belaran@999 6252 case, you're almost certainly going to need to read and modify
belaran@999 6253 your web server's configuration.</para>
belaran@999 6254
belaran@999 6255 <note>
belaran@999 6256 <title>High pain tolerance required</title>
belaran@999 6257
belaran@999 6258 <para id="x_4bd">Configuring a web server is a complex, fiddly,
belaran@999 6259 and highly system-dependent activity. I can't possibly give
belaran@999 6260 you instructions that will cover anything like all of the
belaran@999 6261 cases you will encounter. Please use your discretion and
belaran@999 6262 judgment in following the sections below. Be prepared to make
belaran@999 6263 plenty of mistakes, and to spend a lot of time reading your
belaran@999 6264 server's error logs.</para>
belaran@999 6265
belaran@999 6266 <para id="x_6a9">If you don't have a strong stomach for tweaking
belaran@999 6267 configurations over and over, or a compelling need to host
belaran@999 6268 your own services, you might want to try one of the public
belaran@999 6269 hosting services that I mentioned earlier.</para>
belaran@999 6270 </note>
belaran@999 6271
belaran@999 6272 <sect2>
belaran@999 6273 <title>Web server configuration checklist</title>
belaran@999 6274
belaran@999 6275 <para id="x_4be">Before you continue, do take a few moments to check a few
belaran@999 6276 aspects of your system's setup.</para>
belaran@999 6277
belaran@999 6278 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 6279 <listitem><para id="x_4bf">Do you have a web server installed
belaran@999 6280 at all? Mac OS X and some Linux distributions ship with
belaran@999 6281 Apache, but many other systems may not have a web server
belaran@999 6282 installed.</para>
belaran@999 6283 </listitem>
belaran@999 6284 <listitem><para id="x_4c0">If you have a web server installed, is it
belaran@999 6285 actually running? On most systems, even if one is
belaran@999 6286 present, it will be disabled by default.</para>
belaran@999 6287 </listitem>
belaran@999 6288 <listitem><para id="x_4c1">Is your server configured to allow you to run
belaran@999 6289 CGI programs in the directory where you plan to do so?
belaran@999 6290 Most servers default to explicitly disabling the ability
belaran@999 6291 to run CGI programs.</para>
belaran@999 6292 </listitem></orderedlist>
belaran@999 6293
belaran@999 6294 <para id="x_4c2">If you don't have a web server installed, and don't have
belaran@999 6295 substantial experience configuring Apache, you should consider
belaran@999 6296 using the <literal moreinfo="none">lighttpd</literal> web server instead of
belaran@999 6297 Apache. Apache has a well-deserved reputation for baroque and
belaran@999 6298 confusing configuration. While <literal moreinfo="none">lighttpd</literal> is
belaran@999 6299 less capable in some ways than Apache, most of these
belaran@999 6300 capabilities are not relevant to serving Mercurial
belaran@999 6301 repositories. And <literal moreinfo="none">lighttpd</literal> is undeniably
belaran@999 6302 <emphasis>much</emphasis> easier to get started with than
belaran@999 6303 Apache.</para>
belaran@999 6304 </sect2>
belaran@999 6305
belaran@999 6306 <sect2>
belaran@999 6307 <title>Basic CGI configuration</title>
belaran@999 6308
belaran@999 6309 <para id="x_4c3">On Unix-like systems, it's common for users to have a
belaran@999 6310 subdirectory named something like <filename class="directory" moreinfo="none">public_html</filename> in their home
belaran@999 6311 directory, from which they can serve up web pages. A file
belaran@999 6312 named <filename moreinfo="none">foo</filename> in this directory will be
belaran@999 6313 accessible at a URL of the form
belaran@999 6314 <literal moreinfo="none">http://www.example.com/username/foo</literal>.</para>
belaran@999 6315
belaran@999 6316 <para id="x_4c4">To get started, find the <filename role="special" moreinfo="none">hgweb.cgi</filename> script that should be
belaran@999 6317 present in your Mercurial installation. If you can't quickly
belaran@999 6318 find a local copy on your system, simply download one from the
belaran@999 6319 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>.</para>
belaran@999 6320
belaran@999 6321 <para id="x_4c5">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and
belaran@999 6322 ensure that it's executable.</para>
belaran@999 6323 <programlisting format="linespecific">cp .../hgweb.cgi ~/public_html
belaran@999 6324 chmod 755 ~/public_html/hgweb.cgi</programlisting>
belaran@999 6325 <para id="x_4c6">The <literal moreinfo="none">755</literal> argument to
belaran@999 6326 <command moreinfo="none">chmod</command> is a little more general than just
belaran@999 6327 making the script executable: it ensures that the script is
belaran@999 6328 executable by anyone, and that <quote>group</quote> and
belaran@999 6329 <quote>other</quote> write permissions are
belaran@999 6330 <emphasis>not</emphasis> set. If you were to leave those
belaran@999 6331 write permissions enabled, Apache's <literal moreinfo="none">suexec</literal>
belaran@999 6332 subsystem would likely refuse to execute the script. In fact,
belaran@999 6333 <literal moreinfo="none">suexec</literal> also insists that the
belaran@999 6334 <emphasis>directory</emphasis> in which the script resides
belaran@999 6335 must not be writable by others.</para>
belaran@999 6336 <programlisting format="linespecific">chmod 755 ~/public_html</programlisting>
belaran@999 6337
belaran@999 6338 <sect3 id="sec:collab:wtf">
belaran@999 6339 <title>What could <emphasis>possibly</emphasis> go
belaran@999 6340 wrong?</title>
belaran@999 6341
belaran@999 6342 <para id="x_4c7">Once you've copied the CGI script into place,
belaran@999 6343 go into a web browser, and try to open the URL
belaran@999 6344 <literal moreinfo="none">http://myhostname/~myuser/hgweb.cgi</literal>,
belaran@999 6345 <emphasis>but</emphasis> brace yourself for instant failure.
belaran@999 6346 There's a high probability that trying to visit this URL
belaran@999 6347 will fail, and there are many possible reasons for this. In
belaran@999 6348 fact, you're likely to stumble over almost every one of the
belaran@999 6349 possible errors below, so please read carefully. The
belaran@999 6350 following are all of the problems I ran into on a system
belaran@999 6351 running Fedora 7, with a fresh installation of Apache, and a
belaran@999 6352 user account that I created specially to perform this
belaran@999 6353 exercise.</para>
belaran@999 6354
belaran@999 6355 <para id="x_4c8">Your web server may have per-user directories disabled.
belaran@999 6356 If you're using Apache, search your config file for a
belaran@999 6357 <literal moreinfo="none">UserDir</literal> directive. If there's none
belaran@999 6358 present, per-user directories will be disabled. If one
belaran@999 6359 exists, but its value is <literal moreinfo="none">disabled</literal>, then
belaran@999 6360 per-user directories will be disabled. Otherwise, the
belaran@999 6361 string after <literal moreinfo="none">UserDir</literal> gives the name of
belaran@999 6362 the subdirectory that Apache will look in under your home
belaran@999 6363 directory, for example <filename class="directory" moreinfo="none">public_html</filename>.</para>
belaran@999 6364
belaran@999 6365 <para id="x_4c9">Your file access permissions may be too restrictive.
belaran@999 6366 The web server must be able to traverse your home directory
belaran@999 6367 and directories under your <filename class="directory" moreinfo="none">public_html</filename> directory, and
belaran@999 6368 read files under the latter too. Here's a quick recipe to
belaran@999 6369 help you to make your permissions more appropriate.</para>
belaran@999 6370 <programlisting format="linespecific">chmod 755 ~
belaran@999 6371 find ~/public_html -type d -print0 | xargs -0r chmod 755
belaran@999 6372 find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting>
belaran@999 6373
belaran@999 6374 <para id="x_4ca">The other possibility with permissions is that you might
belaran@999 6375 get a completely empty window when you try to load the
belaran@999 6376 script. In this case, it's likely that your access
belaran@999 6377 permissions are <emphasis>too permissive</emphasis>. Apache's
belaran@999 6378 <literal moreinfo="none">suexec</literal> subsystem won't execute a script
belaran@999 6379 that's group- or world-writable, for example.</para>
belaran@999 6380
belaran@999 6381 <para id="x_4cb">Your web server may be configured to disallow execution
belaran@999 6382 of CGI programs in your per-user web directory. Here's
belaran@999 6383 Apache's default per-user configuration from my Fedora
belaran@999 6384 system.</para>
belaran@999 6385
belaran@999 6386 <!-- BEGIN ch06/apache-config.lst -->
belaran@999 6387 <programlisting format="linespecific">&lt;Directory /home/*/public_html&gt;
belaran@999 6388 AllowOverride FileInfo AuthConfig Limit
belaran@999 6389 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
belaran@999 6390 &lt;Limit GET POST OPTIONS&gt;
belaran@999 6391 Order allow,deny
belaran@999 6392 Allow from all
belaran@999 6393 &lt;/Limit&gt;
belaran@999 6394 &lt;LimitExcept GET POST OPTIONS&gt;
belaran@999 6395 Order deny,allow Deny from all
belaran@999 6396 &lt;/LimitExcept&gt;
belaran@999 6397 &lt;/Directory&gt;</programlisting>
belaran@999 6398 <!-- END ch06/apache-config.lst -->
belaran@999 6399
belaran@999 6400
belaran@999 6401 <para id="x_4cc">If you find a similar-looking
belaran@999 6402 <literal moreinfo="none">Directory</literal> group in your Apache
belaran@999 6403 configuration, the directive to look at inside it is
belaran@999 6404 <literal moreinfo="none">Options</literal>. Add <literal moreinfo="none">ExecCGI</literal>
belaran@999 6405 to the end of this list if it's missing, and restart the web
belaran@999 6406 server.</para>
belaran@999 6407
belaran@999 6408 <para id="x_4cd">If you find that Apache serves you the text of the CGI
belaran@999 6409 script instead of executing it, you may need to either
belaran@999 6410 uncomment (if already present) or add a directive like
belaran@999 6411 this.</para>
belaran@999 6412 <programlisting format="linespecific">AddHandler cgi-script .cgi</programlisting>
belaran@999 6413
belaran@999 6414 <para id="x_4ce">The next possibility is that you might be served with a
belaran@999 6415 colourful Python backtrace claiming that it can't import a
belaran@999 6416 <literal moreinfo="none">mercurial</literal>-related module. This is
belaran@999 6417 actually progress! The server is now capable of executing
belaran@999 6418 your CGI script. This error is only likely to occur if
belaran@999 6419 you're running a private installation of Mercurial, instead
belaran@999 6420 of a system-wide version. Remember that the web server runs
belaran@999 6421 the CGI program without any of the environment variables
belaran@999 6422 that you take for granted in an interactive session. If
belaran@999 6423 this error happens to you, edit your copy of <filename role="special" moreinfo="none">hgweb.cgi</filename> and follow the
belaran@999 6424 directions inside it to correctly set your
belaran@999 6425 <envar>PYTHONPATH</envar> environment variable.</para>
belaran@999 6426
belaran@999 6427 <para id="x_4cf">Finally, you are <emphasis>certain</emphasis> to be
belaran@999 6428 served with another colourful Python backtrace: this one
belaran@999 6429 will complain that it can't find <filename class="directory" moreinfo="none">/path/to/repository</filename>. Edit
belaran@999 6430 your <filename role="special" moreinfo="none">hgweb.cgi</filename> script
belaran@999 6431 and replace the <filename class="directory" moreinfo="none">/path/to/repository</filename> string
belaran@999 6432 with the complete path to the repository you want to serve
belaran@999 6433 up.</para>
belaran@999 6434
belaran@999 6435 <para id="x_4d0">At this point, when you try to reload the page, you
belaran@999 6436 should be presented with a nice HTML view of your
belaran@999 6437 repository's history. Whew!</para>
belaran@999 6438 </sect3>
belaran@999 6439
belaran@999 6440 <sect3>
belaran@999 6441 <title>Configuring lighttpd</title>
belaran@999 6442
belaran@999 6443 <para id="x_4d1">To be exhaustive in my experiments, I tried configuring
belaran@999 6444 the increasingly popular <literal moreinfo="none">lighttpd</literal> web
belaran@999 6445 server to serve the same repository as I described with
belaran@999 6446 Apache above. I had already overcome all of the problems I
belaran@999 6447 outlined with Apache, many of which are not server-specific.
belaran@999 6448 As a result, I was fairly sure that my file and directory
belaran@999 6449 permissions were good, and that my <filename role="special" moreinfo="none">hgweb.cgi</filename> script was properly
belaran@999 6450 edited.</para>
belaran@999 6451
belaran@999 6452 <para id="x_4d2">Once I had Apache running, getting
belaran@999 6453 <literal moreinfo="none">lighttpd</literal> to serve the repository was a
belaran@999 6454 snap (in other words, even if you're trying to use
belaran@999 6455 <literal moreinfo="none">lighttpd</literal>, you should read the Apache
belaran@999 6456 section). I first had to edit the
belaran@999 6457 <literal moreinfo="none">mod_access</literal> section of its config file to
belaran@999 6458 enable <literal moreinfo="none">mod_cgi</literal> and
belaran@999 6459 <literal moreinfo="none">mod_userdir</literal>, both of which were disabled
belaran@999 6460 by default on my system. I then added a few lines to the
belaran@999 6461 end of the config file, to configure these modules.</para>
belaran@999 6462 <programlisting format="linespecific">userdir.path = "public_html"
belaran@999 6463 cgi.assign = (".cgi" =&gt; "" )</programlisting>
belaran@999 6464 <para id="x_4d3">With this done, <literal moreinfo="none">lighttpd</literal> ran
belaran@999 6465 immediately for me. If I had configured
belaran@999 6466 <literal moreinfo="none">lighttpd</literal> before Apache, I'd almost
belaran@999 6467 certainly have run into many of the same system-level
belaran@999 6468 configuration problems as I did with Apache. However, I
belaran@999 6469 found <literal moreinfo="none">lighttpd</literal> to be noticeably easier to
belaran@999 6470 configure than Apache, even though I've used Apache for over
belaran@999 6471 a decade, and this was my first exposure to
belaran@999 6472 <literal moreinfo="none">lighttpd</literal>.</para>
belaran@999 6473 </sect3>
belaran@999 6474 </sect2>
belaran@999 6475
belaran@999 6476 <sect2>
belaran@999 6477 <title>Sharing multiple repositories with one CGI script</title>
belaran@999 6478
belaran@999 6479 <para id="x_4d4">The <filename role="special" moreinfo="none">hgweb.cgi</filename> script
belaran@999 6480 only lets you publish a single repository, which is an
belaran@999 6481 annoying restriction. If you want to publish more than one
belaran@999 6482 without wracking yourself with multiple copies of the same
belaran@999 6483 script, each with different names, a better choice is to use
belaran@999 6484 the <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
belaran@999 6485 script.</para>
belaran@999 6486
belaran@999 6487 <para id="x_4d5">The procedure to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is only a little more
belaran@999 6488 involved than for <filename role="special" moreinfo="none">hgweb.cgi</filename>. First, you must obtain
belaran@999 6489 a copy of the script. If you don't have one handy, you can
belaran@999 6490 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>.</para>
belaran@999 6491
belaran@999 6492 <para id="x_4d6">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and
belaran@999 6493 ensure that it's executable.</para>
belaran@999 6494
belaran@999 6495 <programlisting format="linespecific">cp .../hgwebdir.cgi ~/public_html
belaran@999 6496 chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting>
belaran@999 6497
belaran@999 6498 <para id="x_4d7">With basic configuration out of the way, try to
belaran@999 6499 visit <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>
belaran@999 6500 in your browser. It should
belaran@999 6501 display an empty list of repositories. If you get a blank
belaran@999 6502 window or error message, try walking through the list of
belaran@999 6503 potential problems in <xref linkend="sec:collab:wtf"/>.</para>
belaran@999 6504
belaran@999 6505 <para id="x_4d8">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
belaran@999 6506 script relies on an external configuration file. By default,
belaran@999 6507 it searches for a file named <filename role="special" moreinfo="none">hgweb.config</filename> in the same directory
belaran@999 6508 as itself. You'll need to create this file, and make it
belaran@999 6509 world-readable. The format of the file is similar to a
belaran@999 6510 Windows <quote>ini</quote> file, as understood by Python's
belaran@999 6511 <literal moreinfo="none">ConfigParser</literal>
belaran@999 6512 <citation>web:configparser</citation> module.</para>
belaran@999 6513
belaran@999 6514 <para id="x_4d9">The easiest way to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is with a section
belaran@999 6515 named <literal moreinfo="none">collections</literal>. This will automatically
belaran@999 6516 publish <emphasis>every</emphasis> repository under the
belaran@999 6517 directories you name. The section should look like
belaran@999 6518 this:</para>
belaran@999 6519 <programlisting format="linespecific">[collections]
belaran@999 6520 /my/root = /my/root</programlisting>
belaran@999 6521 <para id="x_4da">Mercurial interprets this by looking at the directory name
belaran@999 6522 on the <emphasis>right</emphasis> hand side of the
belaran@999 6523 <quote><literal moreinfo="none">=</literal></quote> sign; finding repositories
belaran@999 6524 in that directory hierarchy; and using the text on the
belaran@999 6525 <emphasis>left</emphasis> to strip off matching text from the
belaran@999 6526 names it will actually list in the web interface. The
belaran@999 6527 remaining component of a path after this stripping has
belaran@999 6528 occurred is called a <quote>virtual path</quote>.</para>
belaran@999 6529
belaran@999 6530 <para id="x_4db">Given the example above, if we have a
belaran@999 6531 repository whose local path is <filename class="directory" moreinfo="none">/my/root/this/repo</filename>, the CGI
belaran@999 6532 script will strip the leading <filename class="directory" moreinfo="none">/my/root</filename> from the name, and
belaran@999 6533 publish the repository with a virtual path of <filename class="directory" moreinfo="none">this/repo</filename>. If the base URL for
belaran@999 6534 our CGI script is
belaran@999 6535 <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>, the
belaran@999 6536 complete URL for that repository will be
belaran@999 6537 <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para>
belaran@999 6538
belaran@999 6539 <para id="x_4dc">If we replace <filename class="directory" moreinfo="none">/my/root</filename> on the left hand side
belaran@999 6540 of this example with <filename class="directory" moreinfo="none">/my</filename>, then <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will only strip off
belaran@999 6541 <filename class="directory" moreinfo="none">/my</filename> from the repository
belaran@999 6542 name, and will give us a virtual path of <filename class="directory" moreinfo="none">root/this/repo</filename> instead of
belaran@999 6543 <filename class="directory" moreinfo="none">this/repo</filename>.</para>
belaran@999 6544
belaran@999 6545 <para id="x_4dd">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
belaran@999 6546 script will recursively search each directory listed in the
belaran@999 6547 <literal moreinfo="none">collections</literal> section of its configuration
belaran@999 6548 file, but it will <literal moreinfo="none">not</literal> recurse into the
belaran@999 6549 repositories it finds.</para>
belaran@999 6550
belaran@999 6551 <para id="x_4de">The <literal moreinfo="none">collections</literal> mechanism makes it easy
belaran@999 6552 to publish many repositories in a <quote>fire and
belaran@999 6553 forget</quote> manner. You only need to set up the CGI
belaran@999 6554 script and configuration file one time. Afterwards, you can
belaran@999 6555 publish or unpublish a repository at any time by simply moving
belaran@999 6556 it into, or out of, the directory hierarchy in which you've
belaran@999 6557 configured <filename role="special" moreinfo="none">hgwebdir.cgi</filename> to
belaran@999 6558 look.</para>
belaran@999 6559
belaran@999 6560 <sect3>
belaran@999 6561 <title>Explicitly specifying which repositories to
belaran@999 6562 publish</title>
belaran@999 6563
belaran@999 6564 <para id="x_4df">In addition to the <literal moreinfo="none">collections</literal>
belaran@999 6565 mechanism, the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> script allows you
belaran@999 6566 to publish a specific list of repositories. To do so,
belaran@999 6567 create a <literal moreinfo="none">paths</literal> section, with contents of
belaran@999 6568 the following form.</para>
belaran@999 6569 <programlisting format="linespecific">[paths]
belaran@999 6570 repo1 = /my/path/to/some/repo
belaran@999 6571 repo2 = /some/path/to/another</programlisting>
belaran@999 6572 <para id="x_4e0">In this case, the virtual path (the component that will
belaran@999 6573 appear in a URL) is on the left hand side of each
belaran@999 6574 definition, while the path to the repository is on the
belaran@999 6575 right. Notice that there does not need to be any
belaran@999 6576 relationship between the virtual path you choose and the
belaran@999 6577 location of a repository in your filesystem.</para>
belaran@999 6578
belaran@999 6579 <para id="x_4e1">If you wish, you can use both the
belaran@999 6580 <literal moreinfo="none">collections</literal> and <literal moreinfo="none">paths</literal>
belaran@999 6581 mechanisms simultaneously in a single configuration
belaran@999 6582 file.</para>
belaran@999 6583
belaran@999 6584 <note>
belaran@999 6585 <title>Beware duplicate virtual paths</title>
belaran@999 6586
belaran@999 6587 <para id="x_4e2"> If several repositories have the same
belaran@999 6588 virtual path, <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will not report
belaran@999 6589 an error. Instead, it will behave unpredictably.</para>
belaran@999 6590 </note>
belaran@999 6591 </sect3>
belaran@999 6592 </sect2>
belaran@999 6593
belaran@999 6594 <sect2>
belaran@999 6595 <title>Downloading source archives</title>
belaran@999 6596
belaran@999 6597 <para id="x_4e3">Mercurial's web interface lets users download an archive
belaran@999 6598 of any revision. This archive will contain a snapshot of the
belaran@999 6599 working directory as of that revision, but it will not contain
belaran@999 6600 a copy of the repository data.</para>
belaran@999 6601
belaran@999 6602 <para id="x_4e4">By default, this feature is not enabled. To enable it,
belaran@999 6603 you'll need to add an <envar role="rc-item-web">allow_archive</envar> item to the
belaran@999 6604 <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>; see below for details.</para>
belaran@999 6605 </sect2>
belaran@999 6606 <sect2>
belaran@999 6607 <title>Web configuration options</title>
belaran@999 6608
belaran@999 6609 <para id="x_4e5">Mercurial's web interfaces (the <command role="hg-cmd" moreinfo="none">hg
belaran@999 6610 serve</command> command, and the <filename role="special" moreinfo="none">hgweb.cgi</filename> and <filename role="special" moreinfo="none">hgwebdir.cgi</filename> scripts) have a
belaran@999 6611 number of configuration options that you can set. These
belaran@999 6612 belong in a section named <literal role="rc-web" moreinfo="none">web</literal>.</para>
belaran@999 6613 <itemizedlist>
belaran@999 6614 <listitem><para id="x_4e6"><envar role="rc-item-web">allow_archive</envar>: Determines
belaran@999 6615 which (if any) archive download mechanisms Mercurial
belaran@999 6616 supports. If you enable this feature, users of the web
belaran@999 6617 interface will be able to download an archive of whatever
belaran@999 6618 revision of a repository they are viewing. To enable the
belaran@999 6619 archive feature, this item must take the form of a
belaran@999 6620 sequence of words drawn from the list below.</para>
belaran@999 6621 <itemizedlist>
belaran@999 6622 <listitem><para id="x_4e7"><literal moreinfo="none">bz2</literal>: A
belaran@999 6623 <command moreinfo="none">tar</command> archive, compressed using
belaran@999 6624 <literal moreinfo="none">bzip2</literal> compression. This has the
belaran@999 6625 best compression ratio, but uses the most CPU time on
belaran@999 6626 the server.</para>
belaran@999 6627 </listitem>
belaran@999 6628 <listitem><para id="x_4e8"><literal moreinfo="none">gz</literal>: A
belaran@999 6629 <command moreinfo="none">tar</command> archive, compressed using
belaran@999 6630 <literal moreinfo="none">gzip</literal> compression.</para>
belaran@999 6631 </listitem>
belaran@999 6632 <listitem><para id="x_4e9"><literal moreinfo="none">zip</literal>: A
belaran@999 6633 <command moreinfo="none">zip</command> archive, compressed using LZW
belaran@999 6634 compression. This format has the worst compression
belaran@999 6635 ratio, but is widely used in the Windows world.</para>
belaran@999 6636 </listitem>
belaran@999 6637 </itemizedlist>
belaran@999 6638 <para id="x_4ea"> If you provide an empty list, or don't have an
belaran@999 6639 <envar role="rc-item-web">allow_archive</envar> entry at
belaran@999 6640 all, this feature will be disabled. Here is an example of
belaran@999 6641 how to enable all three supported formats.</para>
belaran@999 6642 <programlisting format="linespecific">[web]
belaran@999 6643 allow_archive = bz2 gz zip</programlisting>
belaran@999 6644 </listitem>
belaran@999 6645 <listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>:
belaran@999 6646 Boolean. Determines whether the web interface allows
belaran@999 6647 remote users to <command role="hg-cmd" moreinfo="none">hg pull</command>
belaran@999 6648 and <command role="hg-cmd" moreinfo="none">hg clone</command> this
belaran@999 6649 repository over HTTP. If set to <literal moreinfo="none">no</literal> or
belaran@999 6650 <literal moreinfo="none">false</literal>, only the
belaran@999 6651 <quote>human-oriented</quote> portion of the web interface
belaran@999 6652 is available.</para>
belaran@999 6653 </listitem>
belaran@999 6654 <listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>:
belaran@999 6655 String. A free-form (but preferably brief) string
belaran@999 6656 identifying the person or group in charge of the
belaran@999 6657 repository. This often contains the name and email
belaran@999 6658 address of a person or mailing list. It often makes sense
belaran@999 6659 to place this entry in a repository's own <filename role="special" moreinfo="none">.hg/hgrc</filename> file, but it can make
belaran@999 6660 sense to use in a global <filename role="special" moreinfo="none">~/.hgrc</filename> if every repository
belaran@999 6661 has a single maintainer.</para>
belaran@999 6662 </listitem>
belaran@999 6663 <listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>:
belaran@999 6664 Integer. The default maximum number of changesets to
belaran@999 6665 display in a single page of output.</para>
belaran@999 6666 </listitem>
belaran@999 6667 <listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>:
belaran@999 6668 Integer. The default maximum number of modified files to
belaran@999 6669 display in a single page of output.</para>
belaran@999 6670 </listitem>
belaran@999 6671 <listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>:
belaran@999 6672 Integer. If the web interface displays alternating
belaran@999 6673 <quote>stripes</quote> to make it easier to visually align
belaran@999 6674 rows when you are looking at a table, this number controls
belaran@999 6675 the number of rows in each stripe.</para>
belaran@999 6676 </listitem>
belaran@999 6677 <listitem><para id="x_4f0"><envar role="rc-item-web">style</envar>: Controls the template
belaran@999 6678 Mercurial uses to display the web interface. Mercurial
belaran@999 6679 ships with several web templates.</para>
belaran@999 6680 <itemizedlist>
belaran@999 6681 <listitem>
belaran@999 6682 <para id="x_6aa"><literal moreinfo="none">coal</literal> is monochromatic.</para>
belaran@999 6683 </listitem>
belaran@999 6684 <listitem>
belaran@999 6685 <para id="x_6ab"><literal moreinfo="none">gitweb</literal> emulates the visual
belaran@999 6686 style of git's web interface.</para>
belaran@999 6687 </listitem>
belaran@999 6688 <listitem>
belaran@999 6689 <para id="x_6ac"><literal moreinfo="none">monoblue</literal> uses solid blues and
belaran@999 6690 greys.</para>
belaran@999 6691 </listitem>
belaran@999 6692 <listitem>
belaran@999 6693 <para id="x_6ad"><literal moreinfo="none">paper</literal> is the default.</para>
belaran@999 6694 </listitem>
belaran@999 6695 <listitem>
belaran@999 6696 <para id="x_6ae"><literal moreinfo="none">spartan</literal> was the default for a
belaran@999 6697 long time.</para>
belaran@999 6698 </listitem>
belaran@999 6699 </itemizedlist>
belaran@999 6700 <para id="x_6af">You can
belaran@999 6701 also specify a custom template of your own; see
belaran@999 6702 <xref linkend="chap:template"/> for details. Here, you can
belaran@999 6703 see how to enable the <literal moreinfo="none">gitweb</literal>
belaran@999 6704 style.</para>
belaran@999 6705 <programlisting format="linespecific">[web]
belaran@999 6706 style = gitweb</programlisting>
belaran@999 6707 </listitem>
belaran@999 6708 <listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>:
belaran@999 6709 Path. The directory in which to search for template
belaran@999 6710 files. By default, Mercurial searches in the directory in
belaran@999 6711 which it was installed.</para>
belaran@999 6712 </listitem></itemizedlist>
belaran@999 6713 <para id="x_4f2">If you are using <filename role="special" moreinfo="none">hgwebdir.cgi</filename>, you can place a few
belaran@999 6714 configuration items in a <literal role="rc-web" moreinfo="none">web</literal>
belaran@999 6715 section of the <filename role="special" moreinfo="none">hgweb.config</filename> file instead of a
belaran@999 6716 <filename role="special" moreinfo="none">~/.hgrc</filename> file, for
belaran@999 6717 convenience. These items are <envar role="rc-item-web">motd</envar> and <envar role="rc-item-web">style</envar>.</para>
belaran@999 6718
belaran@999 6719 <sect3>
belaran@999 6720 <title>Options specific to an individual repository</title>
belaran@999 6721
belaran@999 6722 <para id="x_4f3">A few <literal role="rc-web" moreinfo="none">web</literal> configuration
belaran@999 6723 items ought to be placed in a repository's local <filename role="special" moreinfo="none">.hg/hgrc</filename>, rather than a user's
belaran@999 6724 or global <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
belaran@999 6725 <itemizedlist>
belaran@999 6726 <listitem><para id="x_4f4"><envar role="rc-item-web">description</envar>: String. A
belaran@999 6727 free-form (but preferably brief) string that describes
belaran@999 6728 the contents or purpose of the repository.</para>
belaran@999 6729 </listitem>
belaran@999 6730 <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>:
belaran@999 6731 String. The name to use for the repository in the web
belaran@999 6732 interface. This overrides the default name, which is
belaran@999 6733 the last component of the repository's path.</para>
belaran@999 6734 </listitem></itemizedlist>
belaran@999 6735 </sect3>
belaran@999 6736
belaran@999 6737 <sect3>
belaran@999 6738 <title>Options specific to the <command role="hg-cmd" moreinfo="none">hg
belaran@999 6739 serve</command> command</title>
belaran@999 6740
belaran@999 6741 <para id="x_4f6">Some of the items in the <literal role="rc-web" moreinfo="none">web</literal> section of a <filename role="special" moreinfo="none">~/.hgrc</filename> file are only for use
belaran@999 6742 with the <command role="hg-cmd" moreinfo="none">hg serve</command>
belaran@999 6743 command.</para>
belaran@999 6744 <itemizedlist>
belaran@999 6745 <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>:
belaran@999 6746 Path. The name of a file into which to write an access
belaran@999 6747 log. By default, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 6748 serve</command> command writes this information to
belaran@999 6749 standard output, not to a file. Log entries are written
belaran@999 6750 in the standard <quote>combined</quote> file format used
belaran@999 6751 by almost all web servers.</para>
belaran@999 6752 </listitem>
belaran@999 6753 <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>:
belaran@999 6754 String. The local address on which the server should
belaran@999 6755 listen for incoming connections. By default, the server
belaran@999 6756 listens on all addresses.</para>
belaran@999 6757 </listitem>
belaran@999 6758 <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>:
belaran@999 6759 Path. The name of a file into which to write an error
belaran@999 6760 log. By default, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 6761 serve</command> command writes this information to
belaran@999 6762 standard error, not to a file.</para>
belaran@999 6763 </listitem>
belaran@999 6764 <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>:
belaran@999 6765 Boolean. Whether to use the IPv6 protocol. By default,
belaran@999 6766 IPv6 is not used.</para>
belaran@999 6767 </listitem>
belaran@999 6768 <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>:
belaran@999 6769 Integer. The TCP port number on which the server should
belaran@999 6770 listen. The default port number used is 8000.</para>
belaran@999 6771 </listitem></itemizedlist>
belaran@999 6772 </sect3>
belaran@999 6773
belaran@999 6774 <sect3>
belaran@999 6775 <title>Choosing the right <filename role="special" moreinfo="none">~/.hgrc</filename> file to add <literal role="rc-web" moreinfo="none">web</literal> items to</title>
belaran@999 6776
belaran@999 6777 <para id="x_4fc">It is important to remember that a web server like
belaran@999 6778 Apache or <literal moreinfo="none">lighttpd</literal> will run under a user
belaran@999 6779 ID that is different to yours. CGI scripts run by your
belaran@999 6780 server, such as <filename role="special" moreinfo="none">hgweb.cgi</filename>, will usually also run
belaran@999 6781 under that user ID.</para>
belaran@999 6782
belaran@999 6783 <para id="x_4fd">If you add <literal role="rc-web" moreinfo="none">web</literal> items to
belaran@999 6784 your own personal <filename role="special" moreinfo="none">~/.hgrc</filename> file, CGI scripts won't read that
belaran@999 6785 <filename role="special" moreinfo="none">~/.hgrc</filename> file. Those
belaran@999 6786 settings will thus only affect the behavior of the <command role="hg-cmd" moreinfo="none">hg serve</command> command when you run it.
belaran@999 6787 To cause CGI scripts to see your settings, either create a
belaran@999 6788 <filename role="special" moreinfo="none">~/.hgrc</filename> file in the
belaran@999 6789 home directory of the user ID that runs your web server, or
belaran@999 6790 add those settings to a system-wide <filename role="special" moreinfo="none">hgrc</filename> file.</para>
belaran@999 6791 </sect3>
belaran@999 6792 </sect2>
belaran@999 6793 </sect1>
belaran@999 6794
belaran@999 6795 <sect1>
belaran@999 6796 <title>System-wide configuration</title>
belaran@999 6797
belaran@999 6798 <para id="x_6b0">On Unix-like systems shared by multiple users (such as a
belaran@999 6799 server to which people publish changes), it often makes sense to
belaran@999 6800 set up some global default behaviors, such as what theme to use
belaran@999 6801 in web interfaces.</para>
belaran@999 6802
belaran@999 6803 <para id="x_6b1">If a file named <filename moreinfo="none">/etc/mercurial/hgrc</filename>
belaran@999 6804 exists, Mercurial will read it at startup time and apply any
belaran@999 6805 configuration settings it finds in that file. It will also look
belaran@999 6806 for files ending in a <literal moreinfo="none">.rc</literal> extension in a
belaran@999 6807 directory named <filename moreinfo="none">/etc/mercurial/hgrc.d</filename>, and
belaran@999 6808 apply any configuration settings it finds in each of those
belaran@999 6809 files.</para>
belaran@999 6810
belaran@999 6811 <sect2>
belaran@999 6812 <title>Making Mercurial more trusting</title>
belaran@999 6813
belaran@999 6814 <para id="x_6b2">One situation in which a global <filename moreinfo="none">hgrc</filename>
belaran@999 6815 can be useful is if users are pulling changes owned by other
belaran@999 6816 users. By default, Mercurial will not trust most of the
belaran@999 6817 configuration items in a <filename moreinfo="none">.hg/hgrc</filename> file
belaran@999 6818 inside a repository that is owned by a different user. If we
belaran@999 6819 clone or pull changes from such a repository, Mercurial will
belaran@999 6820 print a warning stating that it does not trust their
belaran@999 6821 <filename moreinfo="none">.hg/hgrc</filename>.</para>
belaran@999 6822
belaran@999 6823 <para id="x_6b3">If everyone in a particular Unix group is on the same team
belaran@999 6824 and <emphasis>should</emphasis> trust each other's
belaran@999 6825 configuration settings, or we want to trust particular users,
belaran@999 6826 we can override Mercurial's skeptical defaults by creating a
belaran@999 6827 system-wide <filename moreinfo="none">hgrc</filename> file such as the
belaran@999 6828 following:</para>
belaran@999 6829
belaran@999 6830 <programlisting format="linespecific"># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc
belaran@999 6831 [trusted]
belaran@999 6832 # Trust all entries in any hgrc file owned by the "editors" or
belaran@999 6833 # "www-data" groups.
belaran@999 6834 groups = editors, www-data
belaran@999 6835
belaran@999 6836 # Trust entries in hgrc files owned by the following users.
belaran@999 6837 users = apache, bobo
belaran@999 6838 </programlisting>
belaran@999 6839 </sect2>
belaran@999 6840 </sect1>
belaran@999 6841 </chapter>
belaran@999 6842
belaran@999 6843 <!--
belaran@999 6844 local variables:
belaran@999 6845 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 6846 end:
belaran@999 6847 -->
belaran@999 6848
belaran@999 6849 <!-- BEGIN ch07 -->
belaran@999 6850 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 6851
belaran@999 6852 <chapter id="chap:names">
belaran@999 6853 <?dbhtml filename="file-names-and-pattern-matching.html"?>
belaran@999 6854 <title>File names and pattern matching</title>
belaran@999 6855
belaran@999 6856 <para id="x_543">Mercurial provides mechanisms that let you work with file
belaran@999 6857 names in a consistent and expressive way.</para>
belaran@999 6858
belaran@999 6859 <sect1>
belaran@999 6860 <title>Simple file naming</title>
belaran@999 6861
belaran@999 6862 <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the
belaran@999 6863 hood</quote> to handle file names. Every command behaves
belaran@999 6864 uniformly with respect to file names. The way in which commands
belaran@999 6865 work with file names is as follows.</para>
belaran@999 6866
belaran@999 6867 <para id="x_545">If you explicitly name real files on the command line,
belaran@999 6868 Mercurial works with exactly those files, as you would expect.
belaran@999 6869 <!-- BEGIN filenames.files -->
belaran@999 6870 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add COPYING README examples/simple.py</userinput>
belaran@999 6871 </screen>
belaran@999 6872 <!-- END filenames.files -->
belaran@999 6873 </para>
belaran@999 6874
belaran@999 6875 <para id="x_546">When you provide a directory name, Mercurial will interpret
belaran@999 6876 this as <quote>operate on every file in this directory and its
belaran@999 6877 subdirectories</quote>. Mercurial traverses the files and
belaran@999 6878 subdirectories in a directory in alphabetical order. When it
belaran@999 6879 encounters a subdirectory, it will traverse that subdirectory
belaran@999 6880 before continuing with the current directory.</para>
belaran@999 6881
belaran@999 6882 <!-- BEGIN filenames.dirs -->
belaran@999 6883 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status src</userinput>
belaran@999 6884 ? src/main.py
belaran@999 6885 ? src/watcher/_watcher.c
belaran@999 6886 ? src/watcher/watcher.py
belaran@999 6887 ? src/xyzzy.txt
belaran@999 6888 </screen>
belaran@999 6889 <!-- END filenames.dirs -->
belaran@999 6890
belaran@999 6891 </sect1>
belaran@999 6892
belaran@999 6893 <sect1>
belaran@999 6894 <title>Running commands without any file names</title>
belaran@999 6895
belaran@999 6896 <para id="x_547">Mercurial's commands that work with file names have useful
belaran@999 6897 default behaviors when you invoke them without providing any
belaran@999 6898 file names or patterns. What kind of behavior you should
belaran@999 6899 expect depends on what the command does. Here are a few rules
belaran@999 6900 of thumb you can use to predict what a command is likely to do
belaran@999 6901 if you don't give it any names to work with.</para>
belaran@999 6902 <itemizedlist>
belaran@999 6903 <listitem><para id="x_548">Most commands will operate on the entire working
belaran@999 6904 directory. This is what the <command role="hg-cmd" moreinfo="none">hg
belaran@999 6905 add</command> command does, for example.</para>
belaran@999 6906 </listitem>
belaran@999 6907 <listitem><para id="x_549">If the command has effects that are difficult or
belaran@999 6908 impossible to reverse, it will force you to explicitly
belaran@999 6909 provide at least one name or pattern (see below). This
belaran@999 6910 protects you from accidentally deleting files by running
belaran@999 6911 <command role="hg-cmd" moreinfo="none">hg remove</command> with no
belaran@999 6912 arguments, for example.</para>
belaran@999 6913 </listitem></itemizedlist>
belaran@999 6914
belaran@999 6915 <para id="x_54a">It's easy to work around these default behaviors if they
belaran@999 6916 don't suit you. If a command normally operates on the whole
belaran@999 6917 working directory, you can invoke it on just the current
belaran@999 6918 directory and its subdirectories by giving it the name
belaran@999 6919 <quote><filename class="directory" moreinfo="none">.</filename></quote>.</para>
belaran@999 6920
belaran@999 6921 <!-- BEGIN filenames.wdir-subdir -->
belaran@999 6922 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd src</userinput>
belaran@999 6923 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n</userinput>
belaran@999 6924 adding ../MANIFEST.in
belaran@999 6925 adding ../examples/performant.py
belaran@999 6926 adding ../setup.py
belaran@999 6927 adding main.py
belaran@999 6928 adding watcher/_watcher.c
belaran@999 6929 adding watcher/watcher.py
belaran@999 6930 adding xyzzy.txt
belaran@999 6931 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n .</userinput>
belaran@999 6932 adding main.py
belaran@999 6933 adding watcher/_watcher.c
belaran@999 6934 adding watcher/watcher.py
belaran@999 6935 adding xyzzy.txt
belaran@999 6936 </screen>
belaran@999 6937 <!-- END filenames.wdir-subdir -->
belaran@999 6938
belaran@999 6939
belaran@999 6940 <para id="x_54b">Along the same lines, some commands normally print file
belaran@999 6941 names relative to the root of the repository, even if you're
belaran@999 6942 invoking them from a subdirectory. Such a command will print
belaran@999 6943 file names relative to your subdirectory if you give it explicit
belaran@999 6944 names. Here, we're going to run <command role="hg-cmd" moreinfo="none">hg
belaran@999 6945 status</command> from a subdirectory, and get it to operate on
belaran@999 6946 the entire working directory while printing file names relative
belaran@999 6947 to our subdirectory, by passing it the output of the <command role="hg-cmd" moreinfo="none">hg root</command> command.</para>
belaran@999 6948
belaran@999 6949 <!-- BEGIN filenames.wdir-relname -->
belaran@999 6950 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 6951 A COPYING
belaran@999 6952 A README
belaran@999 6953 A examples/simple.py
belaran@999 6954 ? MANIFEST.in
belaran@999 6955 ? examples/performant.py
belaran@999 6956 ? setup.py
belaran@999 6957 ? src/main.py
belaran@999 6958 ? src/watcher/_watcher.c
belaran@999 6959 ? src/watcher/watcher.py
belaran@999 6960 ? src/xyzzy.txt
belaran@999 6961 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput>
belaran@999 6962 A ../COPYING
belaran@999 6963 A ../README
belaran@999 6964 A ../examples/simple.py
belaran@999 6965 ? ../MANIFEST.in
belaran@999 6966 ? ../examples/performant.py
belaran@999 6967 ? ../setup.py
belaran@999 6968 ? main.py
belaran@999 6969 ? watcher/_watcher.c
belaran@999 6970 ? watcher/watcher.py
belaran@999 6971 ? xyzzy.txt
belaran@999 6972 </screen>
belaran@999 6973 <!-- END filenames.wdir-relname -->
belaran@999 6974
belaran@999 6975 </sect1>
belaran@999 6976
belaran@999 6977 <sect1>
belaran@999 6978 <title>Telling you what's going on</title>
belaran@999 6979
belaran@999 6980 <para id="x_54c">The <command role="hg-cmd" moreinfo="none">hg add</command> example in the
belaran@999 6981 preceding section illustrates something else that's helpful
belaran@999 6982 about Mercurial commands. If a command operates on a file that
belaran@999 6983 you didn't name explicitly on the command line, it will usually
belaran@999 6984 print the name of the file, so that you will not be surprised
belaran@999 6985 what's going on.</para>
belaran@999 6986
belaran@999 6987 <para id="x_54d">The principle here is of <emphasis>least
belaran@999 6988 surprise</emphasis>. If you've exactly named a file on the
belaran@999 6989 command line, there's no point in repeating it back at you. If
belaran@999 6990 Mercurial is acting on a file <emphasis>implicitly</emphasis>, e.g.
belaran@999 6991 because you provided no names, or a directory, or a pattern (see
belaran@999 6992 below), it is safest to tell you what files it's operating on.</para>
belaran@999 6993
belaran@999 6994 <para id="x_54e">For commands that behave this way, you can silence them
belaran@999 6995 using the <option role="hg-opt-global">-q</option> option. You
belaran@999 6996 can also get them to print the name of every file, even those
belaran@999 6997 you've named explicitly, using the <option role="hg-opt-global">-v</option> option.</para>
belaran@999 6998 </sect1>
belaran@999 6999
belaran@999 7000 <sect1>
belaran@999 7001 <title>Using patterns to identify files</title>
belaran@999 7002
belaran@999 7003 <para id="x_54f">In addition to working with file and directory names,
belaran@999 7004 Mercurial lets you use <emphasis>patterns</emphasis> to identify
belaran@999 7005 files. Mercurial's pattern handling is expressive.</para>
belaran@999 7006
belaran@999 7007 <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of
belaran@999 7008 matching file names to patterns normally falls to the shell. On
belaran@999 7009 these systems, you must explicitly tell Mercurial that a name is
belaran@999 7010 a pattern. On Windows, the shell does not expand patterns, so
belaran@999 7011 Mercurial will automatically identify names that are patterns,
belaran@999 7012 and expand them for you.</para>
belaran@999 7013
belaran@999 7014 <para id="x_551">To provide a pattern in place of a regular name on the
belaran@999 7015 command line, the mechanism is simple:</para>
belaran@999 7016 <programlisting format="linespecific">syntax:patternbody</programlisting>
belaran@999 7017 <para id="x_552">That is, a pattern is identified by a short text string that
belaran@999 7018 says what kind of pattern this is, followed by a colon, followed
belaran@999 7019 by the actual pattern.</para>
belaran@999 7020
belaran@999 7021 <para id="x_553">Mercurial supports two kinds of pattern syntax. The most
belaran@999 7022 frequently used is called <literal moreinfo="none">glob</literal>; this is the
belaran@999 7023 same kind of pattern matching used by the Unix shell, and should
belaran@999 7024 be familiar to Windows command prompt users, too.</para>
belaran@999 7025
belaran@999 7026 <para id="x_554">When Mercurial does automatic pattern matching on Windows,
belaran@999 7027 it uses <literal moreinfo="none">glob</literal> syntax. You can thus omit the
belaran@999 7028 <quote><literal moreinfo="none">glob:</literal></quote> prefix on Windows, but
belaran@999 7029 it's safe to use it, too.</para>
belaran@999 7030
belaran@999 7031 <para id="x_555">The <literal moreinfo="none">re</literal> syntax is more powerful; it lets
belaran@999 7032 you specify patterns using regular expressions, also known as
belaran@999 7033 regexps.</para>
belaran@999 7034
belaran@999 7035 <para id="x_556">By the way, in the examples that follow, notice that I'm
belaran@999 7036 careful to wrap all of my patterns in quote characters, so that
belaran@999 7037 they won't get expanded by the shell before Mercurial sees
belaran@999 7038 them.</para>
belaran@999 7039
belaran@999 7040 <sect2>
belaran@999 7041 <title>Shell-style <literal moreinfo="none">glob</literal> patterns</title>
belaran@999 7042
belaran@999 7043 <para id="x_557">This is an overview of the kinds of patterns you can use
belaran@999 7044 when you're matching on glob patterns.</para>
belaran@999 7045
belaran@999 7046 <para id="x_558">The <quote><literal moreinfo="none">*</literal></quote> character matches
belaran@999 7047 any string, within a single directory.</para>
belaran@999 7048
belaran@999 7049 <!-- BEGIN filenames.glob.star -->
belaran@999 7050 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add 'glob:*.py'</userinput>
belaran@999 7051 adding main.py
belaran@999 7052 </screen>
belaran@999 7053 <!-- END filenames.glob.star -->
belaran@999 7054
belaran@999 7055
belaran@999 7056 <para id="x_559">The <quote><literal moreinfo="none">**</literal></quote> pattern matches
belaran@999 7057 any string, and crosses directory boundaries. It's not a
belaran@999 7058 standard Unix glob token, but it's accepted by several popular
belaran@999 7059 Unix shells, and is very useful.</para>
belaran@999 7060
belaran@999 7061 <!-- BEGIN filenames.glob.starstar -->
belaran@999 7062 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 7063 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput>
belaran@999 7064 A examples/simple.py
belaran@999 7065 A src/main.py
belaran@999 7066 ? examples/performant.py
belaran@999 7067 ? setup.py
belaran@999 7068 ? src/watcher/watcher.py
belaran@999 7069 </screen>
belaran@999 7070 <!-- END filenames.glob.starstar -->
belaran@999 7071
belaran@999 7072
belaran@999 7073 <para id="x_55a">The <quote><literal moreinfo="none">?</literal></quote> pattern matches
belaran@999 7074 any single character.</para>
belaran@999 7075
belaran@999 7076 <!-- BEGIN filenames.glob.question -->
belaran@999 7077 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.?'</userinput>
belaran@999 7078 ? src/watcher/_watcher.c
belaran@999 7079 </screen>
belaran@999 7080 <!-- END filenames.glob.question -->
belaran@999 7081
belaran@999 7082
belaran@999 7083 <para id="x_55b">The <quote><literal moreinfo="none">[</literal></quote> character begins a
belaran@999 7084 <emphasis>character class</emphasis>. This matches any single
belaran@999 7085 character within the class. The class ends with a
belaran@999 7086 <quote><literal moreinfo="none">]</literal></quote> character. A class may
belaran@999 7087 contain multiple <emphasis>range</emphasis>s of the form
belaran@999 7088 <quote><literal moreinfo="none">a-f</literal></quote>, which is shorthand for
belaran@999 7089 <quote><literal moreinfo="none">abcdef</literal></quote>.</para>
belaran@999 7090
belaran@999 7091 <!-- BEGIN filenames.glob.range -->
belaran@999 7092 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**[nr-t]'</userinput>
belaran@999 7093 ? MANIFEST.in
belaran@999 7094 ? src/xyzzy.txt
belaran@999 7095 </screen>
belaran@999 7096 <!-- END filenames.glob.range -->
belaran@999 7097
belaran@999 7098
belaran@999 7099 <para id="x_55c">If the first character after the
belaran@999 7100 <quote><literal moreinfo="none">[</literal></quote> in a character class is a
belaran@999 7101 <quote><literal moreinfo="none">!</literal></quote>, it
belaran@999 7102 <emphasis>negates</emphasis> the class, making it match any
belaran@999 7103 single character not in the class.</para>
belaran@999 7104
belaran@999 7105 <para id="x_55d">A <quote><literal moreinfo="none">{</literal></quote> begins a group of
belaran@999 7106 subpatterns, where the whole group matches if any subpattern
belaran@999 7107 in the group matches. The <quote><literal moreinfo="none">,</literal></quote>
belaran@999 7108 character separates subpatterns, and
belaran@999 7109 <quote><literal moreinfo="none">}</literal></quote> ends the group.</para>
belaran@999 7110
belaran@999 7111 <!-- BEGIN filenames.glob.group -->
belaran@999 7112 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.{in,py}'</userinput>
belaran@999 7113 ? MANIFEST.in
belaran@999 7114 ? setup.py
belaran@999 7115 </screen>
belaran@999 7116 <!-- END filenames.glob.group -->
belaran@999 7117
belaran@999 7118
belaran@999 7119 <sect3>
belaran@999 7120 <title>Watch out!</title>
belaran@999 7121
belaran@999 7122 <para id="x_55e">Don't forget that if you want to match a pattern in any
belaran@999 7123 directory, you should not be using the
belaran@999 7124 <quote><literal moreinfo="none">*</literal></quote> match-any token, as this
belaran@999 7125 will only match within one directory. Instead, use the
belaran@999 7126 <quote><literal moreinfo="none">**</literal></quote> token. This small
belaran@999 7127 example illustrates the difference between the two.</para>
belaran@999 7128
belaran@999 7129 <!-- BEGIN filenames.glob.star-starstar -->
belaran@999 7130 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.py'</userinput>
belaran@999 7131 ? setup.py
belaran@999 7132 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput>
belaran@999 7133 A examples/simple.py
belaran@999 7134 A src/main.py
belaran@999 7135 ? examples/performant.py
belaran@999 7136 ? setup.py
belaran@999 7137 ? src/watcher/watcher.py
belaran@999 7138 </screen>
belaran@999 7139 <!-- END filenames.glob.star-starstar -->
belaran@999 7140
belaran@999 7141 </sect3>
belaran@999 7142 </sect2>
belaran@999 7143
belaran@999 7144 <sect2>
belaran@999 7145 <title>Regular expression matching with <literal moreinfo="none">re</literal>
belaran@999 7146 patterns</title>
belaran@999 7147
belaran@999 7148 <para id="x_55f">Mercurial accepts the same regular expression syntax as
belaran@999 7149 the Python programming language (it uses Python's regexp
belaran@999 7150 engine internally). This is based on the Perl language's
belaran@999 7151 regexp syntax, which is the most popular dialect in use (it's
belaran@999 7152 also used in Java, for example).</para>
belaran@999 7153
belaran@999 7154 <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail
belaran@999 7155 here, as regexps are not often used. Perl-style regexps are
belaran@999 7156 in any case already exhaustively documented on a multitude of
belaran@999 7157 web sites, and in many books. Instead, I will focus here on a
belaran@999 7158 few things you should know if you find yourself needing to use
belaran@999 7159 regexps with Mercurial.</para>
belaran@999 7160
belaran@999 7161 <para id="x_561">A regexp is matched against an entire file name, relative
belaran@999 7162 to the root of the repository. In other words, even if you're
belaran@999 7163 already in subbdirectory <filename class="directory" moreinfo="none">foo</filename>, if you want to match files
belaran@999 7164 under this directory, your pattern must start with
belaran@999 7165 <quote><literal moreinfo="none">foo/</literal></quote>.</para>
belaran@999 7166
belaran@999 7167 <para id="x_562">One thing to note, if you're familiar with Perl-style
belaran@999 7168 regexps, is that Mercurial's are <emphasis>rooted</emphasis>.
belaran@999 7169 That is, a regexp starts matching against the beginning of a
belaran@999 7170 string; it doesn't look for a match anywhere within the
belaran@999 7171 string. To match anywhere in a string, start your pattern
belaran@999 7172 with <quote><literal moreinfo="none">.*</literal></quote>.</para>
belaran@999 7173 </sect2>
belaran@999 7174 </sect1>
belaran@999 7175
belaran@999 7176 <sect1>
belaran@999 7177 <title>Filtering files</title>
belaran@999 7178
belaran@999 7179 <para id="x_563">Not only does Mercurial give you a variety of ways to
belaran@999 7180 specify files; it lets you further winnow those files using
belaran@999 7181 <emphasis>filters</emphasis>. Commands that work with file
belaran@999 7182 names accept two filtering options.</para>
belaran@999 7183 <itemizedlist>
belaran@999 7184 <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or
belaran@999 7185 <option role="hg-opt-global">--include</option>, lets you
belaran@999 7186 specify a pattern that file names must match in order to be
belaran@999 7187 processed.</para>
belaran@999 7188 </listitem>
belaran@999 7189 <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or
belaran@999 7190 <option role="hg-opt-global">--exclude</option>, gives you a
belaran@999 7191 way to <emphasis>avoid</emphasis> processing files, if they
belaran@999 7192 match this pattern.</para>
belaran@999 7193 </listitem></itemizedlist>
belaran@999 7194 <para id="x_566">You can provide multiple <option role="hg-opt-global">-I</option> and <option role="hg-opt-global">-X</option> options on the command line,
belaran@999 7195 and intermix them as you please. Mercurial interprets the
belaran@999 7196 patterns you provide using glob syntax by default (but you can
belaran@999 7197 use regexps if you need to).</para>
belaran@999 7198
belaran@999 7199 <para id="x_567">You can read a <option role="hg-opt-global">-I</option>
belaran@999 7200 filter as <quote>process only the files that match this
belaran@999 7201 filter</quote>.</para>
belaran@999 7202
belaran@999 7203 <!-- BEGIN filenames.filter.include -->
belaran@999 7204 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -I '*.in'</userinput>
belaran@999 7205 ? MANIFEST.in
belaran@999 7206 </screen>
belaran@999 7207 <!-- END filenames.filter.include -->
belaran@999 7208
belaran@999 7209
belaran@999 7210 <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best
belaran@999 7211 read as <quote>process only the files that don't match this
belaran@999 7212 pattern</quote>.</para>
belaran@999 7213
belaran@999 7214 <!-- BEGIN filenames.filter.exclude -->
belaran@999 7215 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -X '**.py' src</userinput>
belaran@999 7216 ? src/watcher/_watcher.c
belaran@999 7217 ? src/xyzzy.txt
belaran@999 7218 </screen>
belaran@999 7219 <!-- END filenames.filter.exclude -->
belaran@999 7220
belaran@999 7221 </sect1>
belaran@999 7222
belaran@999 7223 <sect1>
belaran@999 7224 <title>Permanently ignoring unwanted files and directories</title>
belaran@999 7225
belaran@999 7226 <para id="x_569">When you create a new repository, the chances are
belaran@999 7227 that over time it will grow to contain files that ought to
belaran@999 7228 <emphasis>not</emphasis> be managed by Mercurial, but which you
belaran@999 7229 don't want to see listed every time you run <command moreinfo="none">hg
belaran@999 7230 status</command>. For instance, <quote>build products</quote>
belaran@999 7231 are files that are created as part of a build but which should
belaran@999 7232 not be managed by a revision control system. The most common
belaran@999 7233 build products are output files produced by software tools such
belaran@999 7234 as compilers. As another example, many text editors litter a
belaran@999 7235 directory with lock files, temporary working files, and backup
belaran@999 7236 files, which it also makes no sense to manage.</para>
belaran@999 7237
belaran@999 7238 <para id="x_6b4">To have Mercurial permanently ignore such files, create a
belaran@999 7239 file named <filename moreinfo="none">.hgignore</filename> in the root of your
belaran@999 7240 repository. You <emphasis>should</emphasis> <command moreinfo="none">hg
belaran@999 7241 add</command> this file so that it gets tracked with the rest of
belaran@999 7242 your repository contents, since your collaborators will probably
belaran@999 7243 find it useful too.</para>
belaran@999 7244
belaran@999 7245 <para id="x_6b5">By default, the <filename moreinfo="none">.hgignore</filename> file should
belaran@999 7246 contain a list of regular expressions, one per line. Empty
belaran@999 7247 lines are skipped. Most people prefer to describe the files they
belaran@999 7248 want to ignore using the <quote>glob</quote> syntax that we
belaran@999 7249 described above, so a typical <filename moreinfo="none">.hgignore</filename>
belaran@999 7250 file will start with this directive:</para>
belaran@999 7251
belaran@999 7252 <programlisting format="linespecific">syntax: glob</programlisting>
belaran@999 7253
belaran@999 7254 <para id="x_6b6">This tells Mercurial to interpret the lines that follow as
belaran@999 7255 glob patterns, not regular expressions.</para>
belaran@999 7256
belaran@999 7257 <para id="x_6b7">Here is a typical-looking <filename moreinfo="none">.hgignore</filename>
belaran@999 7258 file.</para>
belaran@999 7259
belaran@999 7260 <programlisting format="linespecific">syntax: glob
belaran@999 7261 # This line is a comment, and will be skipped.
belaran@999 7262 # Empty lines are skipped too.
belaran@999 7263
belaran@999 7264 # Backup files left behind by the Emacs editor.
belaran@999 7265 *~
belaran@999 7266
belaran@999 7267 # Lock files used by the Emacs editor.
belaran@999 7268 # Notice that the "#" character is quoted with a backslash.
belaran@999 7269 # This prevents it from being interpreted as starting a comment.
belaran@999 7270 .\#*
belaran@999 7271
belaran@999 7272 # Temporary files used by the vim editor.
belaran@999 7273 .*.swp
belaran@999 7274
belaran@999 7275 # A hidden file created by the Mac OS X Finder.
belaran@999 7276 .DS_Store
belaran@999 7277 </programlisting>
belaran@999 7278 </sect1>
belaran@999 7279
belaran@999 7280 <sect1 id="sec:names:case">
belaran@999 7281 <title>Case sensitivity</title>
belaran@999 7282
belaran@999 7283 <para id="x_56a">If you're working in a mixed development environment that
belaran@999 7284 contains both Linux (or other Unix) systems and Macs or Windows
belaran@999 7285 systems, you should keep in the back of your mind the knowledge
belaran@999 7286 that they treat the case (<quote>N</quote> versus
belaran@999 7287 <quote>n</quote>) of file names in incompatible ways. This is
belaran@999 7288 not very likely to affect you, and it's easy to deal with if it
belaran@999 7289 does, but it could surprise you if you don't know about
belaran@999 7290 it.</para>
belaran@999 7291
belaran@999 7292 <para id="x_56b">Operating systems and filesystems differ in the way they
belaran@999 7293 handle the <emphasis>case</emphasis> of characters in file and
belaran@999 7294 directory names. There are three common ways to handle case in
belaran@999 7295 names.</para>
belaran@999 7296 <itemizedlist>
belaran@999 7297 <listitem><para id="x_56c">Completely case insensitive. Uppercase and
belaran@999 7298 lowercase versions of a letter are treated as identical,
belaran@999 7299 both when creating a file and during subsequent accesses.
belaran@999 7300 This is common on older DOS-based systems.</para>
belaran@999 7301 </listitem>
belaran@999 7302 <listitem><para id="x_56d">Case preserving, but insensitive. When a file
belaran@999 7303 or directory is created, the case of its name is stored, and
belaran@999 7304 can be retrieved and displayed by the operating system.
belaran@999 7305 When an existing file is being looked up, its case is
belaran@999 7306 ignored. This is the standard arrangement on Windows and
belaran@999 7307 MacOS. The names <filename moreinfo="none">foo</filename> and
belaran@999 7308 <filename moreinfo="none">FoO</filename> identify the same file. This
belaran@999 7309 treatment of uppercase and lowercase letters as
belaran@999 7310 interchangeable is also referred to as <emphasis>case
belaran@999 7311 folding</emphasis>.</para>
belaran@999 7312 </listitem>
belaran@999 7313 <listitem><para id="x_56e">Case sensitive. The case of a name
belaran@999 7314 is significant at all times. The names
belaran@999 7315 <filename moreinfo="none">foo</filename> and <filename moreinfo="none">FoO</filename>
belaran@999 7316 identify different files. This is the way Linux and Unix
belaran@999 7317 systems normally work.</para>
belaran@999 7318 </listitem></itemizedlist>
belaran@999 7319
belaran@999 7320 <para id="x_56f">On Unix-like systems, it is possible to have any or all of
belaran@999 7321 the above ways of handling case in action at once. For example,
belaran@999 7322 if you use a USB thumb drive formatted with a FAT32 filesystem
belaran@999 7323 on a Linux system, Linux will handle names on that filesystem in
belaran@999 7324 a case preserving, but insensitive, way.</para>
belaran@999 7325
belaran@999 7326 <sect2>
belaran@999 7327 <title>Safe, portable repository storage</title>
belaran@999 7328
belaran@999 7329 <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case
belaran@999 7330 safe</emphasis>. It translates file names so that they can
belaran@999 7331 be safely stored on both case sensitive and case insensitive
belaran@999 7332 filesystems. This means that you can use normal file copying
belaran@999 7333 tools to transfer a Mercurial repository onto, for example, a
belaran@999 7334 USB thumb drive, and safely move that drive and repository
belaran@999 7335 back and forth between a Mac, a PC running Windows, and a
belaran@999 7336 Linux box.</para>
belaran@999 7337
belaran@999 7338 </sect2>
belaran@999 7339 <sect2>
belaran@999 7340 <title>Detecting case conflicts</title>
belaran@999 7341
belaran@999 7342 <para id="x_571">When operating in the working directory, Mercurial honours
belaran@999 7343 the naming policy of the filesystem where the working
belaran@999 7344 directory is located. If the filesystem is case preserving,
belaran@999 7345 but insensitive, Mercurial will treat names that differ only
belaran@999 7346 in case as the same.</para>
belaran@999 7347
belaran@999 7348 <para id="x_572">An important aspect of this approach is that it is
belaran@999 7349 possible to commit a changeset on a case sensitive (typically
belaran@999 7350 Linux or Unix) filesystem that will cause trouble for users on
belaran@999 7351 case insensitive (usually Windows and MacOS) users. If a
belaran@999 7352 Linux user commits changes to two files, one named
belaran@999 7353 <filename moreinfo="none">myfile.c</filename> and the other named
belaran@999 7354 <filename moreinfo="none">MyFile.C</filename>, they will be stored correctly
belaran@999 7355 in the repository. And in the working directories of other
belaran@999 7356 Linux users, they will be correctly represented as separate
belaran@999 7357 files.</para>
belaran@999 7358
belaran@999 7359 <para id="x_573">If a Windows or Mac user pulls this change, they will not
belaran@999 7360 initially have a problem, because Mercurial's repository
belaran@999 7361 storage mechanism is case safe. However, once they try to
belaran@999 7362 <command role="hg-cmd" moreinfo="none">hg update</command> the working
belaran@999 7363 directory to that changeset, or <command role="hg-cmd" moreinfo="none">hg
belaran@999 7364 merge</command> with that changeset, Mercurial will spot the
belaran@999 7365 conflict between the two file names that the filesystem would
belaran@999 7366 treat as the same, and forbid the update or merge from
belaran@999 7367 occurring.</para>
belaran@999 7368 </sect2>
belaran@999 7369
belaran@999 7370 <sect2>
belaran@999 7371 <title>Fixing a case conflict</title>
belaran@999 7372
belaran@999 7373 <para id="x_574">If you are using Windows or a Mac in a mixed environment
belaran@999 7374 where some of your collaborators are using Linux or Unix, and
belaran@999 7375 Mercurial reports a case folding conflict when you try to
belaran@999 7376 <command role="hg-cmd" moreinfo="none">hg update</command> or <command role="hg-cmd" moreinfo="none">hg merge</command>, the procedure to fix the
belaran@999 7377 problem is simple.</para>
belaran@999 7378
belaran@999 7379 <para id="x_575">Just find a nearby Linux or Unix box, clone the problem
belaran@999 7380 repository onto it, and use Mercurial's <command role="hg-cmd" moreinfo="none">hg rename</command> command to change the
belaran@999 7381 names of any offending files or directories so that they will
belaran@999 7382 no longer cause case folding conflicts. Commit this change,
belaran@999 7383 <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg push</command> it across to your Windows or
belaran@999 7384 MacOS system, and <command role="hg-cmd" moreinfo="none">hg update</command>
belaran@999 7385 to the revision with the non-conflicting names.</para>
belaran@999 7386
belaran@999 7387 <para id="x_576">The changeset with case-conflicting names will remain in
belaran@999 7388 your project's history, and you still won't be able to
belaran@999 7389 <command role="hg-cmd" moreinfo="none">hg update</command> your working
belaran@999 7390 directory to that changeset on a Windows or MacOS system, but
belaran@999 7391 you can continue development unimpeded.</para>
belaran@999 7392 </sect2>
belaran@999 7393 </sect1>
belaran@999 7394 </chapter>
belaran@999 7395
belaran@999 7396 <!--
belaran@999 7397 local variables:
belaran@999 7398 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 7399 end:
belaran@999 7400 -->
belaran@999 7401
belaran@999 7402 <!-- BEGIN ch08 -->
belaran@999 7403 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 7404
belaran@999 7405 <chapter id="chap:branch">
belaran@999 7406 <?dbhtml filename="managing-releases-and-branchy-development.html"?>
belaran@999 7407 <title>Managing releases and branchy development</title>
belaran@999 7408
belaran@999 7409 <para id="x_369">Mercurial provides several mechanisms for you to manage a
belaran@999 7410 project that is making progress on multiple fronts at once. To
belaran@999 7411 understand these mechanisms, let's first take a brief look at a
belaran@999 7412 fairly normal software project structure.</para>
belaran@999 7413
belaran@999 7414 <para id="x_36a">Many software projects issue periodic <quote>major</quote>
belaran@999 7415 releases that contain substantial new features. In parallel, they
belaran@999 7416 may issue <quote>minor</quote> releases. These are usually
belaran@999 7417 identical to the major releases off which they're based, but with
belaran@999 7418 a few bugs fixed.</para>
belaran@999 7419
belaran@999 7420 <para id="x_36b">In this chapter, we'll start by talking about how to keep
belaran@999 7421 records of project milestones such as releases. We'll then
belaran@999 7422 continue on to talk about the flow of work between different
belaran@999 7423 phases of a project, and how Mercurial can help you to isolate and
belaran@999 7424 manage this work.</para>
belaran@999 7425
belaran@999 7426 <sect1>
belaran@999 7427 <title>Giving a persistent name to a revision</title>
belaran@999 7428
belaran@999 7429 <para id="x_36c">Once you decide that you'd like to call a particular
belaran@999 7430 revision a <quote>release</quote>, it's a good idea to record
belaran@999 7431 the identity of that revision. This will let you reproduce that
belaran@999 7432 release at a later date, for whatever purpose you might need at
belaran@999 7433 the time (reproducing a bug, porting to a new platform, etc).
belaran@999 7434 <!-- BEGIN tag.init -->
belaran@999 7435 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mytag</userinput>
belaran@999 7436 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mytag</userinput>
belaran@999 7437 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello &gt; myfile</userinput>
belaran@999 7438 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Initial commit'</userinput>
belaran@999 7439 adding myfile
belaran@999 7440 </screen>
belaran@999 7441 <!-- END tag.init -->
belaran@999 7442 </para>
belaran@999 7443
belaran@999 7444 <para id="x_36d">Mercurial lets you give a permanent name to any revision
belaran@999 7445 using the <command role="hg-cmd" moreinfo="none">hg tag</command> command. Not
belaran@999 7446 surprisingly, these names are called <quote>tags</quote>.</para>
belaran@999 7447
belaran@999 7448 <!-- BEGIN tag.tag -->
belaran@999 7449 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
belaran@999 7450 </screen>
belaran@999 7451 <!-- END tag.tag -->
belaran@999 7452
belaran@999 7453
belaran@999 7454 <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote>
belaran@999 7455 for a revision. Tags exist purely for your convenience, so that
belaran@999 7456 you have a handy permanent way to refer to a revision; Mercurial
belaran@999 7457 doesn't interpret the tag names you use in any way. Neither
belaran@999 7458 does Mercurial place any restrictions on the name of a tag,
belaran@999 7459 beyond a few that are necessary to ensure that a tag can be
belaran@999 7460 parsed unambiguously. A tag name cannot contain any of the
belaran@999 7461 following characters:</para>
belaran@999 7462 <itemizedlist>
belaran@999 7463 <listitem><para id="x_36f">Colon (ASCII 58,
belaran@999 7464 <quote><literal moreinfo="none">:</literal></quote>)</para>
belaran@999 7465 </listitem>
belaran@999 7466 <listitem><para id="x_370">Carriage return (ASCII 13,
belaran@999 7467 <quote><literal moreinfo="none">\r</literal></quote>)</para>
belaran@999 7468 </listitem>
belaran@999 7469 <listitem><para id="x_371">Newline (ASCII 10,
belaran@999 7470 <quote><literal moreinfo="none">\n</literal></quote>)</para>
belaran@999 7471 </listitem></itemizedlist>
belaran@999 7472
belaran@999 7473 <para id="x_372">You can use the <command role="hg-cmd" moreinfo="none">hg tags</command>
belaran@999 7474 command to display the tags present in your repository. In the
belaran@999 7475 output, each tagged revision is identified first by its name,
belaran@999 7476 then by revision number, and finally by the unique hash of the
belaran@999 7477 revision.</para>
belaran@999 7478
belaran@999 7479 <!-- BEGIN tag.tags -->
belaran@999 7480 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
belaran@999 7481 tip 1:f283c2669b38
belaran@999 7482 v1.0 0:0c957785065f
belaran@999 7483 </screen>
belaran@999 7484 <!-- END tag.tags -->
belaran@999 7485
belaran@999 7486
belaran@999 7487 <para id="x_373">Notice that <literal moreinfo="none">tip</literal> is listed in the output
belaran@999 7488 of <command role="hg-cmd" moreinfo="none">hg tags</command>. The
belaran@999 7489 <literal moreinfo="none">tip</literal> tag is a special <quote>floating</quote>
belaran@999 7490 tag, which always identifies the newest revision in the
belaran@999 7491 repository.</para>
belaran@999 7492
belaran@999 7493 <para id="x_374">In the output of the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7494 tags</command> command, tags are listed in reverse order, by
belaran@999 7495 revision number. This usually means that recent tags are listed
belaran@999 7496 before older tags. It also means that <literal moreinfo="none">tip</literal> is
belaran@999 7497 always going to be the first tag listed in the output of
belaran@999 7498 <command role="hg-cmd" moreinfo="none">hg tags</command>.</para>
belaran@999 7499
belaran@999 7500 <para id="x_375">When you run <command role="hg-cmd" moreinfo="none">hg log</command>, if it
belaran@999 7501 displays a revision that has tags associated with it, it will
belaran@999 7502 print those tags.</para>
belaran@999 7503
belaran@999 7504 <!-- BEGIN tag.log -->
belaran@999 7505 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput>
belaran@999 7506 changeset: 1:f283c2669b38
belaran@999 7507 tag: tip
belaran@999 7508 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7509 date: Sun Aug 16 14:05:16 2009 +0000
belaran@999 7510 summary: Added tag v1.0 for changeset 0c957785065f
belaran@999 7511
belaran@999 7512 changeset: 0:0c957785065f
belaran@999 7513 tag: v1.0
belaran@999 7514 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7515 date: Sun Aug 16 14:05:15 2009 +0000
belaran@999 7516 summary: Initial commit
belaran@999 7517
belaran@999 7518 </screen>
belaran@999 7519 <!-- END tag.log -->
belaran@999 7520
belaran@999 7521
belaran@999 7522 <para id="x_376">Any time you need to provide a revision ID to a Mercurial
belaran@999 7523 command, the command will accept a tag name in its place.
belaran@999 7524 Internally, Mercurial will translate your tag name into the
belaran@999 7525 corresponding revision ID, then use that.</para>
belaran@999 7526
belaran@999 7527 <!-- BEGIN tag.log.v1.0 -->
belaran@999 7528 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye &gt; myfile2</userinput>
belaran@999 7529 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Second commit'</userinput>
belaran@999 7530 adding myfile2
belaran@999 7531 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r v1.0</userinput>
belaran@999 7532 changeset: 0:0c957785065f
belaran@999 7533 tag: v1.0
belaran@999 7534 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7535 date: Sun Aug 16 14:05:15 2009 +0000
belaran@999 7536 summary: Initial commit
belaran@999 7537
belaran@999 7538 </screen>
belaran@999 7539 <!-- END tag.log.v1.0 -->
belaran@999 7540
belaran@999 7541
belaran@999 7542 <para id="x_377">There's no limit on the number of tags you can have in a
belaran@999 7543 repository, or on the number of tags that a single revision can
belaran@999 7544 have. As a practical matter, it's not a great idea to have
belaran@999 7545 <quote>too many</quote> (a number which will vary from project
belaran@999 7546 to project), simply because tags are supposed to help you to
belaran@999 7547 find revisions. If you have lots of tags, the ease of using
belaran@999 7548 them to identify revisions diminishes rapidly.</para>
belaran@999 7549
belaran@999 7550 <para id="x_378">For example, if your project has milestones as frequent as
belaran@999 7551 every few days, it's perfectly reasonable to tag each one of
belaran@999 7552 those. But if you have a continuous build system that makes
belaran@999 7553 sure every revision can be built cleanly, you'd be introducing a
belaran@999 7554 lot of noise if you were to tag every clean build. Instead, you
belaran@999 7555 could tag failed builds (on the assumption that they're rare!),
belaran@999 7556 or simply not use tags to track buildability.</para>
belaran@999 7557
belaran@999 7558 <para id="x_379">If you want to remove a tag that you no longer want, use
belaran@999 7559 <command role="hg-cmd" moreinfo="none">hg tag --remove</command>.</para>
belaran@999 7560
belaran@999 7561 <!-- BEGIN tag.remove -->
belaran@999 7562 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag --remove v1.0</userinput>
belaran@999 7563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
belaran@999 7564 tip 3:0f446f1d1f7f
belaran@999 7565 </screen>
belaran@999 7566 <!-- END tag.remove -->
belaran@999 7567
belaran@999 7568
belaran@999 7569 <para id="x_37a">You can also modify a tag at any time, so that it identifies
belaran@999 7570 a different revision, by simply issuing a new <command role="hg-cmd" moreinfo="none">hg tag</command> command. You'll have to use the
belaran@999 7571 <option role="hg-opt-tag">-f</option> option to tell Mercurial
belaran@999 7572 that you <emphasis>really</emphasis> want to update the
belaran@999 7573 tag.</para>
belaran@999 7574
belaran@999 7575 <!-- BEGIN tag.replace -->
belaran@999 7576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 1 v1.1</userinput>
belaran@999 7577 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
belaran@999 7578 tip 4:12fc7bf92915
belaran@999 7579 v1.1 1:f283c2669b38
belaran@999 7580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 2 v1.1</userinput>
belaran@999 7581 abort: tag 'v1.1' already exists (use -f to force)
belaran@999 7582 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -f -r 2 v1.1</userinput>
belaran@999 7583 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
belaran@999 7584 tip 5:17e25cf010af
belaran@999 7585 v1.1 2:737882b3cc76
belaran@999 7586 </screen>
belaran@999 7587 <!-- END tag.replace -->
belaran@999 7588
belaran@999 7589
belaran@999 7590 <para id="x_37b">There will still be a permanent record of the previous
belaran@999 7591 identity of the tag, but Mercurial will no longer use it.
belaran@999 7592 There's thus no penalty to tagging the wrong revision; all you
belaran@999 7593 have to do is turn around and tag the correct revision once you
belaran@999 7594 discover your error.</para>
belaran@999 7595
belaran@999 7596 <para id="x_37c">Mercurial stores tags in a normal revision-controlled file
belaran@999 7597 in your repository. If you've created any tags, you'll find
belaran@999 7598 them in a file in the root of your repository named <filename role="special" moreinfo="none">.hgtags</filename>. When you run the <command role="hg-cmd" moreinfo="none">hg tag</command> command, Mercurial modifies
belaran@999 7599 this file, then automatically commits the change to it. This
belaran@999 7600 means that every time you run <command role="hg-cmd" moreinfo="none">hg
belaran@999 7601 tag</command>, you'll see a corresponding changeset in the
belaran@999 7602 output of <command role="hg-cmd" moreinfo="none">hg log</command>.</para>
belaran@999 7603
belaran@999 7604 <!-- BEGIN tag.tip -->
belaran@999 7605 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 7606 changeset: 5:17e25cf010af
belaran@999 7607 tag: tip
belaran@999 7608 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7609 date: Sun Aug 16 14:05:16 2009 +0000
belaran@999 7610 summary: Added tag v1.1 for changeset 737882b3cc76
belaran@999 7611
belaran@999 7612 </screen>
belaran@999 7613 <!-- END tag.tip -->
belaran@999 7614
belaran@999 7615
belaran@999 7616 <sect2>
belaran@999 7617 <title>Handling tag conflicts during a merge</title>
belaran@999 7618
belaran@999 7619 <para id="x_37d">You won't often need to care about the <filename role="special" moreinfo="none">.hgtags</filename> file, but it sometimes
belaran@999 7620 makes its presence known during a merge. The format of the
belaran@999 7621 file is simple: it consists of a series of lines. Each line
belaran@999 7622 starts with a changeset hash, followed by a space, followed by
belaran@999 7623 the name of a tag.</para>
belaran@999 7624
belaran@999 7625 <para id="x_37e">If you're resolving a conflict in the <filename role="special" moreinfo="none">.hgtags</filename> file during a merge,
belaran@999 7626 there's one twist to modifying the <filename role="special" moreinfo="none">.hgtags</filename> file: when Mercurial is
belaran@999 7627 parsing the tags in a repository, it
belaran@999 7628 <emphasis>never</emphasis> reads the working copy of the
belaran@999 7629 <filename role="special" moreinfo="none">.hgtags</filename> file. Instead, it
belaran@999 7630 reads the <emphasis>most recently committed</emphasis>
belaran@999 7631 revision of the file.</para>
belaran@999 7632
belaran@999 7633 <para id="x_37f">An unfortunate consequence of this design is that you
belaran@999 7634 can't actually verify that your merged <filename role="special" moreinfo="none">.hgtags</filename> file is correct until
belaran@999 7635 <emphasis>after</emphasis> you've committed a change. So if
belaran@999 7636 you find yourself resolving a conflict on <filename role="special" moreinfo="none">.hgtags</filename> during a merge, be sure to
belaran@999 7637 run <command role="hg-cmd" moreinfo="none">hg tags</command> after you commit.
belaran@999 7638 If it finds an error in the <filename role="special" moreinfo="none">.hgtags</filename> file, it will report the
belaran@999 7639 location of the error, which you can then fix and commit. You
belaran@999 7640 should then run <command role="hg-cmd" moreinfo="none">hg tags</command>
belaran@999 7641 again, just to be sure that your fix is correct.</para>
belaran@999 7642 </sect2>
belaran@999 7643
belaran@999 7644 <sect2>
belaran@999 7645 <title>Tags and cloning</title>
belaran@999 7646
belaran@999 7647 <para id="x_380">You may have noticed that the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7648 clone</command> command has a <option role="hg-opt-clone">-r</option> option that lets you clone
belaran@999 7649 an exact copy of the repository as of a particular changeset.
belaran@999 7650 The new clone will not contain any project history that comes
belaran@999 7651 after the revision you specified. This has an interaction
belaran@999 7652 with tags that can surprise the unwary.</para>
belaran@999 7653
belaran@999 7654 <para id="x_381">Recall that a tag is stored as a revision to
belaran@999 7655 the <filename role="special" moreinfo="none">.hgtags</filename> file. When you
belaran@999 7656 create a tag, the changeset in which its recorded refers to an
belaran@999 7657 older changeset. When you run <command role="hg-cmd" moreinfo="none">hg clone
belaran@999 7658 -r foo</command> to clone a repository as of tag
belaran@999 7659 <literal moreinfo="none">foo</literal>, the new clone <emphasis>will not
belaran@999 7660 contain any revision newer than the one the tag refers to,
belaran@999 7661 including the revision where the tag was created</emphasis>.
belaran@999 7662 The result is that you'll get exactly the right subset of the
belaran@999 7663 project's history in the new repository, but
belaran@999 7664 <emphasis>not</emphasis> the tag you might have
belaran@999 7665 expected.</para>
belaran@999 7666 </sect2>
belaran@999 7667
belaran@999 7668 <sect2>
belaran@999 7669 <title>When permanent tags are too much</title>
belaran@999 7670
belaran@999 7671 <para id="x_382">Since Mercurial's tags are revision controlled and carried
belaran@999 7672 around with a project's history, everyone you work with will
belaran@999 7673 see the tags you create. But giving names to revisions has
belaran@999 7674 uses beyond simply noting that revision
belaran@999 7675 <literal moreinfo="none">4237e45506ee</literal> is really
belaran@999 7676 <literal moreinfo="none">v2.0.2</literal>. If you're trying to track down a
belaran@999 7677 subtle bug, you might want a tag to remind you of something
belaran@999 7678 like <quote>Anne saw the symptoms with this
belaran@999 7679 revision</quote>.</para>
belaran@999 7680
belaran@999 7681 <para id="x_383">For cases like this, what you might want to use are
belaran@999 7682 <emphasis>local</emphasis> tags. You can create a local tag
belaran@999 7683 with the <option role="hg-opt-tag">-l</option> option to the
belaran@999 7684 <command role="hg-cmd" moreinfo="none">hg tag</command> command. This will
belaran@999 7685 store the tag in a file called <filename role="special" moreinfo="none">.hg/localtags</filename>. Unlike <filename role="special" moreinfo="none">.hgtags</filename>, <filename role="special" moreinfo="none">.hg/localtags</filename> is not revision
belaran@999 7686 controlled. Any tags you create using <option role="hg-opt-tag">-l</option> remain strictly local to the
belaran@999 7687 repository you're currently working in.</para>
belaran@999 7688 </sect2>
belaran@999 7689 </sect1>
belaran@999 7690
belaran@999 7691 <sect1>
belaran@999 7692 <title>The flow of changes—big picture vs. little</title>
belaran@999 7693
belaran@999 7694 <para id="x_384">To return to the outline I sketched at the
belaran@999 7695 beginning of the chapter, let's think about a project that has
belaran@999 7696 multiple concurrent pieces of work under development at
belaran@999 7697 once.</para>
belaran@999 7698
belaran@999 7699 <para id="x_385">There might be a push for a new <quote>main</quote> release;
belaran@999 7700 a new minor bugfix release to the last main release; and an
belaran@999 7701 unexpected <quote>hot fix</quote> to an old release that is now
belaran@999 7702 in maintenance mode.</para>
belaran@999 7703
belaran@999 7704 <para id="x_386">The usual way people refer to these different concurrent
belaran@999 7705 directions of development is as <quote>branches</quote>.
belaran@999 7706 However, we've already seen numerous times that Mercurial treats
belaran@999 7707 <emphasis>all of history</emphasis> as a series of branches and
belaran@999 7708 merges. Really, what we have here is two ideas that are
belaran@999 7709 peripherally related, but which happen to share a name.</para>
belaran@999 7710 <itemizedlist>
belaran@999 7711 <listitem><para id="x_387"><quote>Big picture</quote> branches represent
belaran@999 7712 the sweep of a project's evolution; people give them names,
belaran@999 7713 and talk about them in conversation.</para>
belaran@999 7714 </listitem>
belaran@999 7715 <listitem><para id="x_388"><quote>Little picture</quote> branches are
belaran@999 7716 artefacts of the day-to-day activity of developing and
belaran@999 7717 merging changes. They expose the narrative of how the code
belaran@999 7718 was developed.</para>
belaran@999 7719 </listitem></itemizedlist>
belaran@999 7720 </sect1>
belaran@999 7721
belaran@999 7722 <sect1>
belaran@999 7723 <title>Managing big-picture branches in repositories</title>
belaran@999 7724
belaran@999 7725 <para id="x_389">The easiest way to isolate a <quote>big picture</quote>
belaran@999 7726 branch in Mercurial is in a dedicated repository. If you have
belaran@999 7727 an existing shared repository—let's call it
belaran@999 7728 <literal moreinfo="none">myproject</literal>—that reaches a
belaran@999 7729 <quote>1.0</quote> milestone, you can start to prepare for
belaran@999 7730 future maintenance releases on top of version 1.0 by tagging the
belaran@999 7731 revision from which you prepared the 1.0 release.</para>
belaran@999 7732
belaran@999 7733 <!-- BEGIN branch-repo.tag -->
belaran@999 7734 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput>
belaran@999 7735 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
belaran@999 7736 </screen>
belaran@999 7737 <!-- END branch-repo.tag -->
belaran@999 7738
belaran@999 7739
belaran@999 7740 <para id="x_38a">You can then clone a new shared
belaran@999 7741 <literal moreinfo="none">myproject-1.0.1</literal> repository as of that
belaran@999 7742 tag.</para>
belaran@999 7743
belaran@999 7744 <!-- BEGIN branch-repo.clone -->
belaran@999 7745 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 7746 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-1.0.1</userinput>
belaran@999 7747 updating working directory
belaran@999 7748 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 7749 </screen>
belaran@999 7750 <!-- END branch-repo.clone -->
belaran@999 7751
belaran@999 7752
belaran@999 7753 <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought
belaran@999 7754 to go into an upcoming 1.0.1 minor release, they clone the
belaran@999 7755 <literal moreinfo="none">myproject-1.0.1</literal> repository, make their
belaran@999 7756 changes, and push them back.</para>
belaran@999 7757
belaran@999 7758 <!-- BEGIN branch-repo.bugfix -->
belaran@999 7759 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject-1.0.1 my-1.0.1-bugfix</userinput>
belaran@999 7760 updating working directory
belaran@999 7761 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 7762 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-1.0.1-bugfix</userinput>
belaran@999 7763 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'I fixed a bug using only echo!' &gt;&gt; myfile</userinput>
belaran@999 7764 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Important fix for 1.0.1'</userinput>
belaran@999 7765 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
belaran@999 7766 pushing to /tmp/branch-repo3rVLLS/myproject-1.0.1
belaran@999 7767 searching for changes
belaran@999 7768 adding changesets
belaran@999 7769 adding manifests
belaran@999 7770 adding file changes
belaran@999 7771 added 1 changesets with 1 changes to 1 files
belaran@999 7772 </screen>
belaran@999 7773 <!-- END branch-repo.bugfix -->
belaran@999 7774
belaran@999 7775
belaran@999 7776 <para id="x_38c">Meanwhile, development for
belaran@999 7777 the next major release can continue, isolated and unabated, in
belaran@999 7778 the <literal moreinfo="none">myproject</literal> repository.</para>
belaran@999 7779
belaran@999 7780 <!-- BEGIN branch-repo.new -->
belaran@999 7781 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 7782 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject my-feature</userinput>
belaran@999 7783 updating working directory
belaran@999 7784 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 7785 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-feature</userinput>
belaran@999 7786 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This sure is an exciting new feature!' &gt; mynewfile</userinput>
belaran@999 7787 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New feature'</userinput>
belaran@999 7788 adding mynewfile
belaran@999 7789 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
belaran@999 7790 pushing to /tmp/branch-repo3rVLLS/myproject
belaran@999 7791 searching for changes
belaran@999 7792 adding changesets
belaran@999 7793 adding manifests
belaran@999 7794 adding file changes
belaran@999 7795 added 1 changesets with 1 changes to 1 files
belaran@999 7796 </screen>
belaran@999 7797 <!-- END branch-repo.new -->
belaran@999 7798
belaran@999 7799 </sect1>
belaran@999 7800
belaran@999 7801 <sect1>
belaran@999 7802 <title>Don't repeat yourself: merging across branches</title>
belaran@999 7803
belaran@999 7804 <para id="x_38d">In many cases, if you have a bug to fix on a maintenance
belaran@999 7805 branch, the chances are good that the bug exists on your
belaran@999 7806 project's main branch (and possibly other maintenance branches,
belaran@999 7807 too). It's a rare developer who wants to fix the same bug
belaran@999 7808 multiple times, so let's look at a few ways that Mercurial can
belaran@999 7809 help you to manage these bugfixes without duplicating your
belaran@999 7810 work.</para>
belaran@999 7811
belaran@999 7812 <para id="x_38e">In the simplest instance, all you need to do is pull changes
belaran@999 7813 from your maintenance branch into your local clone of the target
belaran@999 7814 branch.</para>
belaran@999 7815
belaran@999 7816 <!-- BEGIN branch-repo.pull -->
belaran@999 7817 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 7818 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-merge</userinput>
belaran@999 7819 updating working directory
belaran@999 7820 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 7821 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject-merge</userinput>
belaran@999 7822 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../myproject-1.0.1</userinput>
belaran@999 7823 pulling from ../myproject-1.0.1
belaran@999 7824 searching for changes
belaran@999 7825 adding changesets
belaran@999 7826 adding manifests
belaran@999 7827 adding file changes
belaran@999 7828 added 1 changesets with 1 changes to 1 files (+1 heads)
belaran@999 7829 (run 'hg heads' to see heads, 'hg merge' to merge)
belaran@999 7830 </screen>
belaran@999 7831 <!-- END branch-repo.pull -->
belaran@999 7832
belaran@999 7833
belaran@999 7834 <para id="x_38f">You'll then need to merge the heads of the two branches, and
belaran@999 7835 push back to the main branch.</para>
belaran@999 7836
belaran@999 7837 <!-- BEGIN branch-repo.merge -->
belaran@999 7838 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 7839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 7840 (branch merge, don't forget to commit)
belaran@999 7841 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge bugfix from 1.0.1 branch'</userinput>
belaran@999 7842 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
belaran@999 7843 pushing to /tmp/branch-repo3rVLLS/myproject
belaran@999 7844 searching for changes
belaran@999 7845 adding changesets
belaran@999 7846 adding manifests
belaran@999 7847 adding file changes
belaran@999 7848 added 2 changesets with 1 changes to 1 files
belaran@999 7849 </screen>
belaran@999 7850 <!-- END branch-repo.merge -->
belaran@999 7851
belaran@999 7852 </sect1>
belaran@999 7853
belaran@999 7854 <sect1>
belaran@999 7855 <title>Naming branches within one repository</title>
belaran@999 7856
belaran@999 7857 <para id="x_390">In most instances, isolating branches in repositories is the
belaran@999 7858 right approach. Its simplicity makes it easy to understand; and
belaran@999 7859 so it's hard to make mistakes. There's a one-to-one
belaran@999 7860 relationship between branches you're working in and directories
belaran@999 7861 on your system. This lets you use normal (non-Mercurial-aware)
belaran@999 7862 tools to work on files within a branch/repository.</para>
belaran@999 7863
belaran@999 7864 <para id="x_391">If you're more in the <quote>power user</quote> category
belaran@999 7865 (<emphasis>and</emphasis> your collaborators are too), there is
belaran@999 7866 an alternative way of handling branches that you can consider.
belaran@999 7867 I've already mentioned the human-level distinction between
belaran@999 7868 <quote>small picture</quote> and <quote>big picture</quote>
belaran@999 7869 branches. While Mercurial works with multiple <quote>small
belaran@999 7870 picture</quote> branches in a repository all the time (for
belaran@999 7871 example after you pull changes in, but before you merge them),
belaran@999 7872 it can <emphasis>also</emphasis> work with multiple <quote>big
belaran@999 7873 picture</quote> branches.</para>
belaran@999 7874
belaran@999 7875 <para id="x_392">The key to working this way is that Mercurial lets you
belaran@999 7876 assign a persistent <emphasis>name</emphasis> to a branch.
belaran@999 7877 There always exists a branch named <literal moreinfo="none">default</literal>.
belaran@999 7878 Even before you start naming branches yourself, you can find
belaran@999 7879 traces of the <literal moreinfo="none">default</literal> branch if you look for
belaran@999 7880 them.</para>
belaran@999 7881
belaran@999 7882 <para id="x_393">As an example, when you run the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7883 commit</command> command, and it pops up your editor so that
belaran@999 7884 you can enter a commit message, look for a line that contains
belaran@999 7885 the text <quote><literal moreinfo="none">HG: branch default</literal></quote> at
belaran@999 7886 the bottom. This is telling you that your commit will occur on
belaran@999 7887 the branch named <literal moreinfo="none">default</literal>.</para>
belaran@999 7888
belaran@999 7889 <para id="x_394">To start working with named branches, use the <command role="hg-cmd" moreinfo="none">hg branches</command> command. This command
belaran@999 7890 lists the named branches already present in your repository,
belaran@999 7891 telling you which changeset is the tip of each.</para>
belaran@999 7892
belaran@999 7893 <!-- BEGIN branch-named.branches -->
belaran@999 7894 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 7895 changeset: 0:90897f9e54e3
belaran@999 7896 tag: tip
belaran@999 7897 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7898 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 7899 summary: Initial commit
belaran@999 7900
belaran@999 7901 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput>
belaran@999 7902 default 0:90897f9e54e3
belaran@999 7903 </screen>
belaran@999 7904 <!-- END branch-named.branches -->
belaran@999 7905
belaran@999 7906
belaran@999 7907 <para id="x_395">Since you haven't created any named branches yet, the only
belaran@999 7908 one that exists is <literal moreinfo="none">default</literal>.</para>
belaran@999 7909
belaran@999 7910 <para id="x_396">To find out what the <quote>current</quote> branch is, run
belaran@999 7911 the <command role="hg-cmd" moreinfo="none">hg branch</command> command, giving
belaran@999 7912 it no arguments. This tells you what branch the parent of the
belaran@999 7913 current changeset is on.</para>
belaran@999 7914
belaran@999 7915 <!-- BEGIN branch-named.branch -->
belaran@999 7916 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
belaran@999 7917 default
belaran@999 7918 </screen>
belaran@999 7919 <!-- END branch-named.branch -->
belaran@999 7920
belaran@999 7921
belaran@999 7922 <para id="x_397">To create a new branch, run the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7923 branch</command> command again. This time, give it one
belaran@999 7924 argument: the name of the branch you want to create.</para>
belaran@999 7925
belaran@999 7926 <!-- BEGIN branch-named.create -->
belaran@999 7927 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch foo</userinput>
belaran@999 7928 marked working directory as branch foo
belaran@999 7929 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
belaran@999 7930 foo
belaran@999 7931 </screen>
belaran@999 7932 <!-- END branch-named.create -->
belaran@999 7933
belaran@999 7934
belaran@999 7935 <para id="x_398">After you've created a branch, you might wonder what effect
belaran@999 7936 the <command role="hg-cmd" moreinfo="none">hg branch</command> command has had.
belaran@999 7937 What do the <command role="hg-cmd" moreinfo="none">hg status</command> and
belaran@999 7938 <command role="hg-cmd" moreinfo="none">hg tip</command> commands report?</para>
belaran@999 7939
belaran@999 7940 <!-- BEGIN branch-named.status -->
belaran@999 7941 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 7942 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 7943 changeset: 0:90897f9e54e3
belaran@999 7944 tag: tip
belaran@999 7945 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7946 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 7947 summary: Initial commit
belaran@999 7948
belaran@999 7949 </screen>
belaran@999 7950 <!-- END branch-named.status -->
belaran@999 7951
belaran@999 7952
belaran@999 7953 <para id="x_399">Nothing has changed in the
belaran@999 7954 working directory, and there's been no new history created. As
belaran@999 7955 this suggests, running the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7956 branch</command> command has no permanent effect; it only
belaran@999 7957 tells Mercurial what branch name to use the
belaran@999 7958 <emphasis>next</emphasis> time you commit a changeset.</para>
belaran@999 7959
belaran@999 7960 <para id="x_39a">When you commit a change, Mercurial records the name of the
belaran@999 7961 branch on which you committed. Once you've switched from the
belaran@999 7962 <literal moreinfo="none">default</literal> branch to another and committed,
belaran@999 7963 you'll see the name of the new branch show up in the output of
belaran@999 7964 <command role="hg-cmd" moreinfo="none">hg log</command>, <command role="hg-cmd" moreinfo="none">hg tip</command>, and other commands that
belaran@999 7965 display the same kind of output.</para>
belaran@999 7966
belaran@999 7967 <!-- BEGIN branch-named.commit -->
belaran@999 7968 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'hello again' &gt;&gt; myfile</userinput>
belaran@999 7969 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Second commit'</userinput>
belaran@999 7970 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 7971 changeset: 1:5656f8ffdd49
belaran@999 7972 branch: foo
belaran@999 7973 tag: tip
belaran@999 7974 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 7975 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 7976 summary: Second commit
belaran@999 7977
belaran@999 7978 </screen>
belaran@999 7979 <!-- END branch-named.commit -->
belaran@999 7980
belaran@999 7981
belaran@999 7982 <para id="x_39b">The <command role="hg-cmd" moreinfo="none">hg log</command>-like commands
belaran@999 7983 will print the branch name of every changeset that's not on the
belaran@999 7984 <literal moreinfo="none">default</literal> branch. As a result, if you never
belaran@999 7985 use named branches, you'll never see this information.</para>
belaran@999 7986
belaran@999 7987 <para id="x_39c">Once you've named a branch and committed a change with that
belaran@999 7988 name, every subsequent commit that descends from that change
belaran@999 7989 will inherit the same branch name. You can change the name of a
belaran@999 7990 branch at any time, using the <command role="hg-cmd" moreinfo="none">hg
belaran@999 7991 branch</command> command.</para>
belaran@999 7992
belaran@999 7993 <!-- BEGIN branch-named.rebranch -->
belaran@999 7994 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
belaran@999 7995 foo
belaran@999 7996 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch bar</userinput>
belaran@999 7997 marked working directory as branch bar
belaran@999 7998 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo new file &gt; newfile</userinput>
belaran@999 7999 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Third commit'</userinput>
belaran@999 8000 adding newfile
belaran@999 8001 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 8002 changeset: 2:c59d680fc2ec
belaran@999 8003 branch: bar
belaran@999 8004 tag: tip
belaran@999 8005 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8006 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 8007 summary: Third commit
belaran@999 8008
belaran@999 8009 </screen>
belaran@999 8010 <!-- END branch-named.rebranch -->
belaran@999 8011
belaran@999 8012
belaran@999 8013 <para id="x_39d">In practice, this is something you won't do very often, as
belaran@999 8014 branch names tend to have fairly long lifetimes. (This isn't a
belaran@999 8015 rule, just an observation.)</para>
belaran@999 8016 </sect1>
belaran@999 8017
belaran@999 8018 <sect1>
belaran@999 8019 <title>Dealing with multiple named branches in a
belaran@999 8020 repository</title>
belaran@999 8021
belaran@999 8022 <para id="x_39e">If you have more than one named branch in a repository,
belaran@999 8023 Mercurial will remember the branch that your working directory
belaran@999 8024 is on when you start a command like <command role="hg-cmd" moreinfo="none">hg
belaran@999 8025 update</command> or <command role="hg-cmd" moreinfo="none">hg pull
belaran@999 8026 -u</command>. It will update the working directory to the tip
belaran@999 8027 of this branch, no matter what the <quote>repo-wide</quote> tip
belaran@999 8028 is. To update to a revision that's on a different named branch,
belaran@999 8029 you may need to use the <option role="hg-opt-update">-C</option>
belaran@999 8030 option to <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
belaran@999 8031
belaran@999 8032 <para id="x_39f">This behavior is a little subtle, so let's see it in
belaran@999 8033 action. First, let's remind ourselves what branch we're
belaran@999 8034 currently on, and what branches are in our repository.</para>
belaran@999 8035
belaran@999 8036 <!-- BEGIN branch-named.parents -->
belaran@999 8037 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 8038 changeset: 2:c59d680fc2ec
belaran@999 8039 branch: bar
belaran@999 8040 tag: tip
belaran@999 8041 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8042 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 8043 summary: Third commit
belaran@999 8044
belaran@999 8045 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput>
belaran@999 8046 bar 2:c59d680fc2ec
belaran@999 8047 foo 1:5656f8ffdd49 (inactive)
belaran@999 8048 default 0:90897f9e54e3 (inactive)
belaran@999 8049 </screen>
belaran@999 8050 <!-- END branch-named.parents -->
belaran@999 8051
belaran@999 8052
belaran@999 8053 <para id="x_3a0">We're on the <literal moreinfo="none">bar</literal> branch, but there also
belaran@999 8054 exists an older <command role="hg-cmd" moreinfo="none">hg foo</command>
belaran@999 8055 branch.</para>
belaran@999 8056
belaran@999 8057 <para id="x_3a1">We can <command role="hg-cmd" moreinfo="none">hg update</command> back and
belaran@999 8058 forth between the tips of the <literal moreinfo="none">foo</literal> and
belaran@999 8059 <literal moreinfo="none">bar</literal> branches without needing to use the
belaran@999 8060 <option role="hg-opt-update">-C</option> option, because this
belaran@999 8061 only involves going backwards and forwards linearly through our
belaran@999 8062 change history.</para>
belaran@999 8063
belaran@999 8064 <!-- BEGIN branch-named.update-switchy -->
belaran@999 8065 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput>
belaran@999 8066 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
belaran@999 8067 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 8068 changeset: 1:5656f8ffdd49
belaran@999 8069 branch: foo
belaran@999 8070 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8071 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 8072 summary: Second commit
belaran@999 8073
belaran@999 8074 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update bar</userinput>
belaran@999 8075 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 8076 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 8077 changeset: 2:c59d680fc2ec
belaran@999 8078 branch: bar
belaran@999 8079 tag: tip
belaran@999 8080 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8081 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 8082 summary: Third commit
belaran@999 8083
belaran@999 8084 </screen>
belaran@999 8085 <!-- END branch-named.update-switchy -->
belaran@999 8086
belaran@999 8087
belaran@999 8088 <para id="x_3a2">If we go back to the <literal moreinfo="none">foo</literal> branch and then
belaran@999 8089 run <command role="hg-cmd" moreinfo="none">hg update</command>, it will keep us
belaran@999 8090 on <literal moreinfo="none">foo</literal>, not move us to the tip of
belaran@999 8091 <literal moreinfo="none">bar</literal>.</para>
belaran@999 8092
belaran@999 8093 <!-- BEGIN branch-named.update-nothing -->
belaran@999 8094 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput>
belaran@999 8095 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
belaran@999 8096 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
belaran@999 8097 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 8098 </screen>
belaran@999 8099 <!-- END branch-named.update-nothing -->
belaran@999 8100
belaran@999 8101
belaran@999 8102 <para id="x_3a3">Committing a new change on the <literal moreinfo="none">foo</literal> branch
belaran@999 8103 introduces a new head.</para>
belaran@999 8104
belaran@999 8105 <!-- BEGIN branch-named.foo-commit -->
belaran@999 8106 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo something &gt; somefile</userinput>
belaran@999 8107 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New file'</userinput>
belaran@999 8108 adding somefile
belaran@999 8109 created new head
belaran@999 8110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
belaran@999 8111 changeset: 3:4dd2f7a37288
belaran@999 8112 branch: foo
belaran@999 8113 tag: tip
belaran@999 8114 parent: 1:5656f8ffdd49
belaran@999 8115 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8116 date: Sun Aug 16 14:04:43 2009 +0000
belaran@999 8117 summary: New file
belaran@999 8118
belaran@999 8119 changeset: 2:c59d680fc2ec
belaran@999 8120 branch: bar
belaran@999 8121 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8122 date: Sun Aug 16 14:04:42 2009 +0000
belaran@999 8123 summary: Third commit
belaran@999 8124
belaran@999 8125 </screen>
belaran@999 8126 <!-- END branch-named.foo-commit -->
belaran@999 8127
belaran@999 8128 </sect1>
belaran@999 8129
belaran@999 8130 <sect1>
belaran@999 8131 <title>Branch names and merging</title>
belaran@999 8132
belaran@999 8133 <para id="x_3a4">As you've probably noticed, merges in Mercurial are not
belaran@999 8134 symmetrical. Let's say our repository has two heads, 17 and 23.
belaran@999 8135 If I <command role="hg-cmd" moreinfo="none">hg update</command> to 17 and then
belaran@999 8136 <command role="hg-cmd" moreinfo="none">hg merge</command> with 23, Mercurial
belaran@999 8137 records 17 as the first parent of the merge, and 23 as the
belaran@999 8138 second. Whereas if I <command role="hg-cmd" moreinfo="none">hg update</command>
belaran@999 8139 to 23 and then <command role="hg-cmd" moreinfo="none">hg merge</command> with
belaran@999 8140 17, it records 23 as the first parent, and 17 as the
belaran@999 8141 second.</para>
belaran@999 8142
belaran@999 8143 <para id="x_3a5">This affects Mercurial's choice of branch name when you
belaran@999 8144 merge. After a merge, Mercurial will retain the branch name of
belaran@999 8145 the first parent when you commit the result of the merge. If
belaran@999 8146 your first parent's branch name is <literal moreinfo="none">foo</literal>, and
belaran@999 8147 you merge with <literal moreinfo="none">bar</literal>, the branch name will
belaran@999 8148 still be <literal moreinfo="none">foo</literal> after you merge.</para>
belaran@999 8149
belaran@999 8150 <para id="x_3a6">It's not unusual for a repository to contain multiple heads,
belaran@999 8151 each with the same branch name. Let's say I'm working on the
belaran@999 8152 <literal moreinfo="none">foo</literal> branch, and so are you. We commit
belaran@999 8153 different changes; I pull your changes; I now have two heads,
belaran@999 8154 each claiming to be on the <literal moreinfo="none">foo</literal> branch. The
belaran@999 8155 result of a merge will be a single head on the
belaran@999 8156 <literal moreinfo="none">foo</literal> branch, as you might hope.</para>
belaran@999 8157
belaran@999 8158 <para id="x_3a7">But if I'm working on the <literal moreinfo="none">bar</literal> branch, and
belaran@999 8159 I merge work from the <literal moreinfo="none">foo</literal> branch, the result
belaran@999 8160 will remain on the <literal moreinfo="none">bar</literal> branch.</para>
belaran@999 8161
belaran@999 8162 <!-- BEGIN branch-named.merge -->
belaran@999 8163 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
belaran@999 8164 bar
belaran@999 8165 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge foo</userinput>
belaran@999 8166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 8167 (branch merge, don't forget to commit)
belaran@999 8168 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge'</userinput>
belaran@999 8169 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 8170 changeset: 4:9f05d4ef3efe
belaran@999 8171 branch: bar
belaran@999 8172 tag: tip
belaran@999 8173 parent: 2:c59d680fc2ec
belaran@999 8174 parent: 3:4dd2f7a37288
belaran@999 8175 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8176 date: Sun Aug 16 14:04:44 2009 +0000
belaran@999 8177 summary: Merge
belaran@999 8178
belaran@999 8179 </screen>
belaran@999 8180 <!-- END branch-named.merge -->
belaran@999 8181
belaran@999 8182
belaran@999 8183 <para id="x_3a8">To give a more concrete example, if I'm working on the
belaran@999 8184 <literal moreinfo="none">bleeding-edge</literal> branch, and I want to bring in
belaran@999 8185 the latest fixes from the <literal moreinfo="none">stable</literal> branch,
belaran@999 8186 Mercurial will choose the <quote>right</quote>
belaran@999 8187 (<literal moreinfo="none">bleeding-edge</literal>) branch name when I pull and
belaran@999 8188 merge from <literal moreinfo="none">stable</literal>.</para>
belaran@999 8189 </sect1>
belaran@999 8190
belaran@999 8191 <sect1>
belaran@999 8192 <title>Branch naming is generally useful</title>
belaran@999 8193
belaran@999 8194 <para id="x_3a9">You shouldn't think of named branches as applicable only to
belaran@999 8195 situations where you have multiple long-lived branches
belaran@999 8196 cohabiting in a single repository. They're very useful even in
belaran@999 8197 the one-branch-per-repository case.</para>
belaran@999 8198
belaran@999 8199 <para id="x_3aa">In the simplest case, giving a name to each branch gives you
belaran@999 8200 a permanent record of which branch a changeset originated on.
belaran@999 8201 This gives you more context when you're trying to follow the
belaran@999 8202 history of a long-lived branchy project.</para>
belaran@999 8203
belaran@999 8204 <para id="x_3ab">If you're working with shared repositories, you can set up a
belaran@999 8205 <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook on each
belaran@999 8206 that will block incoming changes that have the
belaran@999 8207 <quote>wrong</quote> branch name. This provides a simple, but
belaran@999 8208 effective, defence against people accidentally pushing changes
belaran@999 8209 from a <quote>bleeding edge</quote> branch to a
belaran@999 8210 <quote>stable</quote> branch. Such a hook might look like this
belaran@999 8211 inside the shared repo's <filename role="special" moreinfo="none">
belaran@999 8212 /.hgrc</filename>.</para>
belaran@999 8213 <programlisting format="linespecific">[hooks]
belaran@999 8214 pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting>
belaran@999 8215 </sect1>
belaran@999 8216 </chapter>
belaran@999 8217
belaran@999 8218 <!--
belaran@999 8219 local variables:
belaran@999 8220 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 8221 end:
belaran@999 8222 -->
belaran@999 8223
belaran@999 8224 <!-- BEGIN ch09 -->
belaran@999 8225 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 8226
belaran@999 8227 <chapter id="chap:undo">
belaran@999 8228 <?dbhtml filename="finding-and-fixing-mistakes.html"?>
belaran@999 8229 <title>Finding and fixing mistakes</title>
belaran@999 8230
belaran@999 8231 <para id="x_d2">To err might be human, but to really handle the consequences
belaran@999 8232 well takes a top-notch revision control system. In this chapter,
belaran@999 8233 we'll discuss some of the techniques you can use when you find
belaran@999 8234 that a problem has crept into your project. Mercurial has some
belaran@999 8235 highly capable features that will help you to isolate the sources
belaran@999 8236 of problems, and to handle them appropriately.</para>
belaran@999 8237
belaran@999 8238 <sect1>
belaran@999 8239 <title>Erasing local history</title>
belaran@999 8240
belaran@999 8241 <sect2>
belaran@999 8242 <title>The accidental commit</title>
belaran@999 8243
belaran@999 8244 <para id="x_d3">I have the occasional but persistent problem of typing
belaran@999 8245 rather more quickly than I can think, which sometimes results
belaran@999 8246 in me committing a changeset that is either incomplete or
belaran@999 8247 plain wrong. In my case, the usual kind of incomplete
belaran@999 8248 changeset is one in which I've created a new source file, but
belaran@999 8249 forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> it. A
belaran@999 8250 <quote>plain wrong</quote> changeset is not as common, but no
belaran@999 8251 less annoying.</para>
belaran@999 8252
belaran@999 8253 </sect2>
belaran@999 8254 <sect2 id="sec:undo:rollback">
belaran@999 8255 <title>Rolling back a transaction</title>
belaran@999 8256
belaran@999 8257 <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I
belaran@999 8258 mentioned that Mercurial treats each modification of a
belaran@999 8259 repository as a <emphasis>transaction</emphasis>. Every time
belaran@999 8260 you commit a changeset or pull changes from another
belaran@999 8261 repository, Mercurial remembers what you did. You can undo,
belaran@999 8262 or <emphasis>roll back</emphasis>, exactly one of these
belaran@999 8263 actions using the <command role="hg-cmd" moreinfo="none">hg rollback</command>
belaran@999 8264 command. (See <xref linkend="sec:undo:rollback-after-push"/>
belaran@999 8265 for an important caveat about the use of this command.)</para>
belaran@999 8266
belaran@999 8267 <para id="x_d5">Here's a mistake that I often find myself making:
belaran@999 8268 committing a change in which I've created a new file, but
belaran@999 8269 forgotten to <command role="hg-cmd" moreinfo="none">hg add</command>
belaran@999 8270 it.</para>
belaran@999 8271
belaran@999 8272 <!-- BEGIN rollback.commit -->
belaran@999 8273 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8274 M a
belaran@999 8275 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
belaran@999 8276 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b'</userinput>
belaran@999 8277 </screen>
belaran@999 8278 <!-- END rollback.commit -->
belaran@999 8279
belaran@999 8280
belaran@999 8281 <para id="x_d6">Looking at the output of <command role="hg-cmd" moreinfo="none">hg
belaran@999 8282 status</command> after the commit immediately confirms the
belaran@999 8283 error.</para>
belaran@999 8284
belaran@999 8285 <!-- BEGIN rollback.status -->
belaran@999 8286 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8287 ? b
belaran@999 8288 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 8289 changeset: 1:246e2aada1c5
belaran@999 8290 tag: tip
belaran@999 8291 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8292 date: Sun Aug 16 14:05:14 2009 +0000
belaran@999 8293 summary: Add file b
belaran@999 8294
belaran@999 8295 </screen>
belaran@999 8296 <!-- END rollback.status -->
belaran@999 8297
belaran@999 8298
belaran@999 8299 <para id="x_d7">The commit captured the changes to the file
belaran@999 8300 <filename moreinfo="none">a</filename>, but not the new file
belaran@999 8301 <filename moreinfo="none">b</filename>. If I were to push this changeset to a
belaran@999 8302 repository that I shared with a colleague, the chances are
belaran@999 8303 high that something in <filename moreinfo="none">a</filename> would refer to
belaran@999 8304 <filename moreinfo="none">b</filename>, which would not be present in their
belaran@999 8305 repository when they pulled my changes. I would thus become
belaran@999 8306 the object of some indignation.</para>
belaran@999 8307
belaran@999 8308 <para id="x_d8">However, luck is with me—I've caught my error
belaran@999 8309 before I pushed the changeset. I use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, and Mercurial
belaran@999 8310 makes that last changeset vanish.</para>
belaran@999 8311
belaran@999 8312 <!-- BEGIN rollback.rollback -->
belaran@999 8313 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
belaran@999 8314 rolling back last transaction
belaran@999 8315 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 8316 changeset: 0:c37ce4157509
belaran@999 8317 tag: tip
belaran@999 8318 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8319 date: Sun Aug 16 14:05:14 2009 +0000
belaran@999 8320 summary: First commit
belaran@999 8321
belaran@999 8322 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8323 M a
belaran@999 8324 ? b
belaran@999 8325 </screen>
belaran@999 8326 <!-- END rollback.rollback -->
belaran@999 8327
belaran@999 8328
belaran@999 8329 <para id="x_d9">Notice that the changeset is no longer present in the
belaran@999 8330 repository's history, and the working directory once again
belaran@999 8331 thinks that the file <filename moreinfo="none">a</filename> is modified. The
belaran@999 8332 commit and rollback have left the working directory exactly as
belaran@999 8333 it was prior to the commit; the changeset has been completely
belaran@999 8334 erased. I can now safely <command role="hg-cmd" moreinfo="none">hg
belaran@999 8335 add</command> the file <filename moreinfo="none">b</filename>, and rerun my
belaran@999 8336 commit.</para>
belaran@999 8337
belaran@999 8338 <!-- BEGIN rollback.add -->
belaran@999 8339 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput>
belaran@999 8340 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b, this time for real'</userinput>
belaran@999 8341 </screen>
belaran@999 8342 <!-- END rollback.add -->
belaran@999 8343
belaran@999 8344
belaran@999 8345 </sect2>
belaran@999 8346 <sect2>
belaran@999 8347 <title>The erroneous pull</title>
belaran@999 8348
belaran@999 8349 <para id="x_da">It's common practice with Mercurial to maintain separate
belaran@999 8350 development branches of a project in different repositories.
belaran@999 8351 Your development team might have one shared repository for
belaran@999 8352 your project's <quote>0.9</quote> release, and another,
belaran@999 8353 containing different changes, for the <quote>1.0</quote>
belaran@999 8354 release.</para>
belaran@999 8355
belaran@999 8356 <para id="x_db">Given this, you can imagine that the consequences could be
belaran@999 8357 messy if you had a local <quote>0.9</quote> repository, and
belaran@999 8358 accidentally pulled changes from the shared <quote>1.0</quote>
belaran@999 8359 repository into it. At worst, you could be paying
belaran@999 8360 insufficient attention, and push those changes into the shared
belaran@999 8361 <quote>0.9</quote> tree, confusing your entire team (but don't
belaran@999 8362 worry, we'll return to this horror scenario later). However,
belaran@999 8363 it's more likely that you'll notice immediately, because
belaran@999 8364 Mercurial will display the URL it's pulling from, or you will
belaran@999 8365 see it pull a suspiciously large number of changes into the
belaran@999 8366 repository.</para>
belaran@999 8367
belaran@999 8368 <para id="x_dc">The <command role="hg-cmd" moreinfo="none">hg rollback</command> command
belaran@999 8369 will work nicely to expunge all of the changesets that you
belaran@999 8370 just pulled. Mercurial groups all changes from one <command role="hg-cmd" moreinfo="none">hg pull</command> into a single transaction,
belaran@999 8371 so one <command role="hg-cmd" moreinfo="none">hg rollback</command> is all you
belaran@999 8372 need to undo this mistake.</para>
belaran@999 8373
belaran@999 8374 </sect2>
belaran@999 8375 <sect2 id="sec:undo:rollback-after-push">
belaran@999 8376 <title>Rolling back is useless once you've pushed</title>
belaran@999 8377
belaran@999 8378 <para id="x_dd">The value of the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8379 rollback</command> command drops to zero once you've pushed
belaran@999 8380 your changes to another repository. Rolling back a change
belaran@999 8381 makes it disappear entirely, but <emphasis>only</emphasis> in
belaran@999 8382 the repository in which you perform the <command role="hg-cmd" moreinfo="none">hg rollback</command>. Because a rollback
belaran@999 8383 eliminates history, there's no way for the disappearance of a
belaran@999 8384 change to propagate between repositories.</para>
belaran@999 8385
belaran@999 8386 <para id="x_de">If you've pushed a change to another
belaran@999 8387 repository—particularly if it's a shared
belaran@999 8388 repository—it has essentially <quote>escaped into the
belaran@999 8389 wild,</quote> and you'll have to recover from your mistake
belaran@999 8390 in a different way. If you push a changeset somewhere, then
belaran@999 8391 roll it back, then pull from the repository you pushed to, the
belaran@999 8392 changeset you thought you'd gotten rid of will simply reappear
belaran@999 8393 in your repository.</para>
belaran@999 8394
belaran@999 8395 <para id="x_df">(If you absolutely know for sure that the change
belaran@999 8396 you want to roll back is the most recent change in the
belaran@999 8397 repository that you pushed to, <emphasis>and</emphasis> you
belaran@999 8398 know that nobody else could have pulled it from that
belaran@999 8399 repository, you can roll back the changeset there, too, but
belaran@999 8400 you really should not expect this to work reliably. Sooner or
belaran@999 8401 later a change really will make it into a repository that you
belaran@999 8402 don't directly control (or have forgotten about), and come
belaran@999 8403 back to bite you.)</para>
belaran@999 8404
belaran@999 8405 </sect2>
belaran@999 8406 <sect2>
belaran@999 8407 <title>You can only roll back once</title>
belaran@999 8408
belaran@999 8409 <para id="x_e0">Mercurial stores exactly one transaction in its
belaran@999 8410 transaction log; that transaction is the most recent one that
belaran@999 8411 occurred in the repository. This means that you can only roll
belaran@999 8412 back one transaction. If you expect to be able to roll back
belaran@999 8413 one transaction, then its predecessor, this is not the
belaran@999 8414 behavior you will get.</para>
belaran@999 8415
belaran@999 8416 <!-- BEGIN rollback.twice -->
belaran@999 8417 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
belaran@999 8418 rolling back last transaction
belaran@999 8419 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
belaran@999 8420 no rollback information available
belaran@999 8421 </screen>
belaran@999 8422 <!-- END rollback.twice -->
belaran@999 8423
belaran@999 8424
belaran@999 8425 <para id="x_e1">Once you've rolled back one transaction in a repository,
belaran@999 8426 you can't roll back again in that repository until you perform
belaran@999 8427 another commit or pull.</para>
belaran@999 8428
belaran@999 8429 </sect2>
belaran@999 8430 </sect1>
belaran@999 8431 <sect1>
belaran@999 8432 <title>Reverting the mistaken change</title>
belaran@999 8433
belaran@999 8434 <para id="x_e2">If you make a modification to a file, and decide that you
belaran@999 8435 really didn't want to change the file at all, and you haven't
belaran@999 8436 yet committed your changes, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8437 revert</command> command is the one you'll need. It looks at
belaran@999 8438 the changeset that's the parent of the working directory, and
belaran@999 8439 restores the contents of the file to their state as of that
belaran@999 8440 changeset. (That's a long-winded way of saying that, in the
belaran@999 8441 normal case, it undoes your modifications.)</para>
belaran@999 8442
belaran@999 8443 <para id="x_e3">Let's illustrate how the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8444 revert</command> command works with yet another small example.
belaran@999 8445 We'll begin by modifying a file that Mercurial is already
belaran@999 8446 tracking.</para>
belaran@999 8447
belaran@999 8448 <!-- BEGIN daily.revert.modify -->
belaran@999 8449 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput>
belaran@999 8450 original content
belaran@999 8451 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo unwanted change &gt;&gt; file</userinput>
belaran@999 8452 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff file</userinput>
belaran@999 8453 diff -r 2eacf948d309 file
belaran@999 8454 --- a/file Sun Aug 16 14:05:00 2009 +0000
belaran@999 8455 +++ b/file Sun Aug 16 14:05:00 2009 +0000
belaran@999 8456 @@ -1,1 +1,2 @@
belaran@999 8457 original content
belaran@999 8458 +unwanted change
belaran@999 8459 </screen>
belaran@999 8460 <!-- END daily.revert.modify -->
belaran@999 8461
belaran@999 8462
belaran@999 8463 <para id="x_e4">If we don't
belaran@999 8464 want that change, we can simply <command role="hg-cmd" moreinfo="none">hg
belaran@999 8465 revert</command> the file.</para>
belaran@999 8466
belaran@999 8467 <!-- BEGIN daily.revert.unmodify -->
belaran@999 8468 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8469 M file
belaran@999 8470 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
belaran@999 8471 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput>
belaran@999 8472 original content
belaran@999 8473 </screen>
belaran@999 8474 <!-- END daily.revert.unmodify -->
belaran@999 8475
belaran@999 8476
belaran@999 8477 <para id="x_e5">The <command role="hg-cmd" moreinfo="none">hg revert</command> command
belaran@999 8478 provides us with an extra degree of safety by saving our
belaran@999 8479 modified file with a <filename moreinfo="none">.orig</filename>
belaran@999 8480 extension.</para>
belaran@999 8481
belaran@999 8482 <!-- BEGIN daily.revert.status -->
belaran@999 8483 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8484 ? file.orig
belaran@999 8485 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file.orig</userinput>
belaran@999 8486 original content
belaran@999 8487 unwanted change
belaran@999 8488 </screen>
belaran@999 8489 <!-- END daily.revert.status -->
belaran@999 8490
belaran@999 8491
belaran@999 8492 <tip>
belaran@999 8493 <title>Be careful with <filename moreinfo="none">.orig</filename> files</title>
belaran@999 8494
belaran@999 8495 <para id="x_6b8">It's extremely unlikely that you are either using
belaran@999 8496 Mercurial to manage files with <filename moreinfo="none">.orig</filename>
belaran@999 8497 extensions or that you even care about the contents of such
belaran@999 8498 files. Just in case, though, it's useful to remember that
belaran@999 8499 <command role="hg-cmd" moreinfo="none">hg revert</command> will
belaran@999 8500 unconditionally overwrite an existing file with a
belaran@999 8501 <filename moreinfo="none">.orig</filename> extension. For instance, if you
belaran@999 8502 already have a file named <filename moreinfo="none">foo.orig</filename> when
belaran@999 8503 you revert <filename moreinfo="none">foo</filename>, the contents of
belaran@999 8504 <filename moreinfo="none">foo.orig</filename> will be clobbered.</para>
belaran@999 8505 </tip>
belaran@999 8506
belaran@999 8507 <para id="x_e6">Here is a summary of the cases that the <command role="hg-cmd" moreinfo="none">hg revert</command> command can deal with. We
belaran@999 8508 will describe each of these in more detail in the section that
belaran@999 8509 follows.</para>
belaran@999 8510 <itemizedlist>
belaran@999 8511 <listitem><para id="x_e7">If you modify a file, it will restore the file
belaran@999 8512 to its unmodified state.</para>
belaran@999 8513 </listitem>
belaran@999 8514 <listitem><para id="x_e8">If you <command role="hg-cmd" moreinfo="none">hg add</command> a
belaran@999 8515 file, it will undo the <quote>added</quote> state of the
belaran@999 8516 file, but leave the file itself untouched.</para>
belaran@999 8517 </listitem>
belaran@999 8518 <listitem><para id="x_e9">If you delete a file without telling Mercurial,
belaran@999 8519 it will restore the file to its unmodified contents.</para>
belaran@999 8520 </listitem>
belaran@999 8521 <listitem><para id="x_ea">If you use the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8522 remove</command> command to remove a file, it will undo
belaran@999 8523 the <quote>removed</quote> state of the file, and restore
belaran@999 8524 the file to its unmodified contents.</para>
belaran@999 8525 </listitem></itemizedlist>
belaran@999 8526
belaran@999 8527 <sect2 id="sec:undo:mgmt">
belaran@999 8528 <title>File management errors</title>
belaran@999 8529
belaran@999 8530 <para id="x_eb">The <command role="hg-cmd" moreinfo="none">hg revert</command> command is
belaran@999 8531 useful for more than just modified files. It lets you reverse
belaran@999 8532 the results of all of Mercurial's file management
belaran@999 8533 commands—<command role="hg-cmd" moreinfo="none">hg add</command>,
belaran@999 8534 <command role="hg-cmd" moreinfo="none">hg remove</command>, and so on.</para>
belaran@999 8535
belaran@999 8536 <para id="x_ec">If you <command role="hg-cmd" moreinfo="none">hg add</command> a file,
belaran@999 8537 then decide that in fact you don't want Mercurial to track it,
belaran@999 8538 use <command role="hg-cmd" moreinfo="none">hg revert</command> to undo the
belaran@999 8539 add. Don't worry; Mercurial will not modify the file in any
belaran@999 8540 way. It will just <quote>unmark</quote> the file.</para>
belaran@999 8541
belaran@999 8542 <!-- BEGIN daily.revert.add -->
belaran@999 8543 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo oops &gt; oops</userinput>
belaran@999 8544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add oops</userinput>
belaran@999 8545 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status oops</userinput>
belaran@999 8546 A oops
belaran@999 8547 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert oops</userinput>
belaran@999 8548 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8549 ? oops
belaran@999 8550 </screen>
belaran@999 8551 <!-- END daily.revert.add -->
belaran@999 8552
belaran@999 8553
belaran@999 8554 <para id="x_ed">Similarly, if you ask Mercurial to <command role="hg-cmd" moreinfo="none">hg remove</command> a file, you can use
belaran@999 8555 <command role="hg-cmd" moreinfo="none">hg revert</command> to restore it to
belaran@999 8556 the contents it had as of the parent of the working directory.
belaran@999 8557 <!-- BEGIN daily.revert.remove -->
belaran@999 8558 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove file</userinput>
belaran@999 8559 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8560 R file
belaran@999 8561 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
belaran@999 8562 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput>
belaran@999 8564 file
belaran@999 8565 </screen>
belaran@999 8566 <!-- END daily.revert.remove -->
belaran@999 8567 This works just as
belaran@999 8568 well for a file that you deleted by hand, without telling
belaran@999 8569 Mercurial (recall that in Mercurial terminology, this kind of
belaran@999 8570 file is called <quote>missing</quote>).</para>
belaran@999 8571
belaran@999 8572 <!-- BEGIN daily.revert.missing -->
belaran@999 8573 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm file</userinput>
belaran@999 8574 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8575 ! file
belaran@999 8576 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
belaran@999 8577 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput>
belaran@999 8578 file
belaran@999 8579 </screen>
belaran@999 8580 <!-- END daily.revert.missing -->
belaran@999 8581
belaran@999 8582
belaran@999 8583 <para id="x_ee">If you revert a <command role="hg-cmd" moreinfo="none">hg copy</command>,
belaran@999 8584 the copied-to file remains in your working directory
belaran@999 8585 afterwards, untracked. Since a copy doesn't affect the
belaran@999 8586 copied-from file in any way, Mercurial doesn't do anything
belaran@999 8587 with the copied-from file.</para>
belaran@999 8588
belaran@999 8589 <!-- BEGIN daily.revert.copy -->
belaran@999 8590 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput>
belaran@999 8591 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert new-file</userinput>
belaran@999 8592 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 8593 ? new-file
belaran@999 8594 </screen>
belaran@999 8595 <!-- END daily.revert.copy -->
belaran@999 8596
belaran@999 8597 </sect2>
belaran@999 8598 </sect1>
belaran@999 8599
belaran@999 8600 <sect1>
belaran@999 8601 <title>Dealing with committed changes</title>
belaran@999 8602
belaran@999 8603 <para id="x_f5">Consider a case where you have committed a change
belaran@999 8604 <emphasis>a</emphasis>, and another change
belaran@999 8605 <emphasis>b</emphasis> on top of it; you then realise that
belaran@999 8606 change <emphasis>a</emphasis> was incorrect. Mercurial lets you
belaran@999 8607 <quote>back out</quote> an entire changeset automatically, and
belaran@999 8608 building blocks that let you reverse part of a changeset by
belaran@999 8609 hand.</para>
belaran@999 8610
belaran@999 8611 <para id="x_f6">Before you read this section, here's something to
belaran@999 8612 keep in mind: the <command role="hg-cmd" moreinfo="none">hg backout</command>
belaran@999 8613 command undoes the effect of a change by
belaran@999 8614 <emphasis>adding</emphasis> to your repository's history, not by
belaran@999 8615 modifying or erasing it. It's the right tool to use if you're
belaran@999 8616 fixing bugs, but not if you're trying to undo some change that
belaran@999 8617 has catastrophic consequences. To deal with those, see
belaran@999 8618 <xref linkend="sec:undo:aaaiiieee"/>.</para>
belaran@999 8619
belaran@999 8620 <sect2>
belaran@999 8621 <title>Backing out a changeset</title>
belaran@999 8622
belaran@999 8623 <para id="x_f7">The <command role="hg-cmd" moreinfo="none">hg backout</command> command
belaran@999 8624 lets you <quote>undo</quote> the effects of an entire
belaran@999 8625 changeset in an automated fashion. Because Mercurial's
belaran@999 8626 history is immutable, this command <emphasis>does
belaran@999 8627 not</emphasis> get rid of the changeset you want to undo.
belaran@999 8628 Instead, it creates a new changeset that
belaran@999 8629 <emphasis>reverses</emphasis> the effect of the to-be-undone
belaran@999 8630 changeset.</para>
belaran@999 8631
belaran@999 8632 <para id="x_f8">The operation of the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8633 backout</command> command is a little intricate, so let's
belaran@999 8634 illustrate it with some examples. First, we'll create a
belaran@999 8635 repository with some simple changes.</para>
belaran@999 8636
belaran@999 8637 <!-- BEGIN backout.init -->
belaran@999 8638 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput>
belaran@999 8639 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput>
belaran@999 8640 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first change &gt;&gt; myfile</userinput>
belaran@999 8641 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile</userinput>
belaran@999 8642 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'first change'</userinput>
belaran@999 8643 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo second change &gt;&gt; myfile</userinput>
belaran@999 8644 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'second change'</userinput>
belaran@999 8645 </screen>
belaran@999 8646 <!-- END backout.init -->
belaran@999 8647
belaran@999 8648
belaran@999 8649 <para id="x_f9">The <command role="hg-cmd" moreinfo="none">hg backout</command> command
belaran@999 8650 takes a single changeset ID as its argument; this is the
belaran@999 8651 changeset to back out. Normally, <command role="hg-cmd" moreinfo="none">hg
belaran@999 8652 backout</command> will drop you into a text editor to write
belaran@999 8653 a commit message, so you can record why you're backing the
belaran@999 8654 change out. In this example, we provide a commit message on
belaran@999 8655 the command line using the <option role="hg-opt-backout">-m</option> option.</para>
belaran@999 8656
belaran@999 8657 </sect2>
belaran@999 8658 <sect2>
belaran@999 8659 <title>Backing out the tip changeset</title>
belaran@999 8660
belaran@999 8661 <para id="x_fa">We're going to start by backing out the last changeset we
belaran@999 8662 committed.</para>
belaran@999 8663
belaran@999 8664 <!-- BEGIN backout.simple -->
belaran@999 8665 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' tip</userinput>
belaran@999 8666 reverting myfile
belaran@999 8667 changeset 2:611a0cae251c backs out changeset 1:43700a9b3ec8
belaran@999 8668 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 8669 first change
belaran@999 8670 </screen>
belaran@999 8671 <!-- END backout.simple -->
belaran@999 8672
belaran@999 8673
belaran@999 8674 <para id="x_fb">You can see that the second line from
belaran@999 8675 <filename moreinfo="none">myfile</filename> is no longer present. Taking a
belaran@999 8676 look at the output of <command role="hg-cmd" moreinfo="none">hg log</command>
belaran@999 8677 gives us an idea of what the <command role="hg-cmd" moreinfo="none">hg
belaran@999 8678 backout</command> command has done.
belaran@999 8679 <!-- BEGIN backout.simple.log -->
belaran@999 8680 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
belaran@999 8681 2[tip] 611a0cae251c 2009-08-16 14:04 +0000 bos
belaran@999 8682 back out second change
belaran@999 8683
belaran@999 8684 1 43700a9b3ec8 2009-08-16 14:04 +0000 bos
belaran@999 8685 second change
belaran@999 8686
belaran@999 8687 0 f2ef23d503fd 2009-08-16 14:04 +0000 bos
belaran@999 8688 first change
belaran@999 8689
belaran@999 8690 </screen>
belaran@999 8691 <!-- END backout.simple.log -->
belaran@999 8692 Notice that the new changeset
belaran@999 8693 that <command role="hg-cmd" moreinfo="none">hg backout</command> has created
belaran@999 8694 is a child of the changeset we backed out. It's easier to see
belaran@999 8695 this in <xref linkend="fig:undo:backout"/>, which presents a
belaran@999 8696 graphical view of the change history. As you can see, the
belaran@999 8697 history is nice and linear.</para>
belaran@999 8698
belaran@999 8699 <figure id="fig:undo:backout" float="0">
belaran@999 8700 <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
belaran@999 8701 <mediaobject>
belaran@999 8702 <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject>
belaran@999 8703 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 8704 </mediaobject>
belaran@999 8705 </figure>
belaran@999 8706
belaran@999 8707 </sect2>
belaran@999 8708 <sect2>
belaran@999 8709 <title>Backing out a non-tip change</title>
belaran@999 8710
belaran@999 8711 <para id="x_fd">If you want to back out a change other than the last one
belaran@999 8712 you committed, pass the <option role="hg-opt-backout">--merge</option> option to the
belaran@999 8713 <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para>
belaran@999 8714
belaran@999 8715 <!-- BEGIN backout.non-tip.clone -->
belaran@999 8716 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 8717 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo non-tip-repo</userinput>
belaran@999 8718 requesting all changes
belaran@999 8719 adding changesets
belaran@999 8720 adding manifests
belaran@999 8721 adding file changes
belaran@999 8722 added 2 changesets with 2 changes to 1 files
belaran@999 8723 updating working directory
belaran@999 8724 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 8725 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd non-tip-repo</userinput>
belaran@999 8726 </screen>
belaran@999 8727 <!-- END backout.non-tip.clone -->
belaran@999 8728
belaran@999 8729
belaran@999 8730 <para id="x_fe">This makes backing out any changeset a
belaran@999 8731 <quote>one-shot</quote> operation that's usually simple and
belaran@999 8732 fast.</para>
belaran@999 8733
belaran@999 8734 <!-- BEGIN backout.non-tip.backout -->
belaran@999 8735 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change &gt;&gt; myfile</userinput>
belaran@999 8736 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput>
belaran@999 8737 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout --merge -m 'back out second change' 1</userinput>
belaran@999 8738 reverting myfile
belaran@999 8739 created new head
belaran@999 8740 changeset 3:611a0cae251c backs out changeset 1:43700a9b3ec8
belaran@999 8741 merging with changeset 3:611a0cae251c
belaran@999 8742 merging myfile
belaran@999 8743 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
belaran@999 8744 (branch merge, don't forget to commit)
belaran@999 8745 </screen>
belaran@999 8746 <!-- END backout.non-tip.backout -->
belaran@999 8747
belaran@999 8748
belaran@999 8749 <para id="x_ff">If you take a look at the contents of
belaran@999 8750 <filename moreinfo="none">myfile</filename> after the backout finishes, you'll
belaran@999 8751 see that the first and third changes are present, but not the
belaran@999 8752 second.</para>
belaran@999 8753
belaran@999 8754 <!-- BEGIN backout.non-tip.cat -->
belaran@999 8755 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 8756 first change
belaran@999 8757 third change
belaran@999 8758 </screen>
belaran@999 8759 <!-- END backout.non-tip.cat -->
belaran@999 8760
belaran@999 8761
belaran@999 8762 <para id="x_100">As the graphical history in <xref linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
belaran@999 8763 still commits one change in this kind of situation (the
belaran@999 8764 box-shaped node is the ones that Mercurial commits
belaran@999 8765 automatically), but the revision graph now looks different.
belaran@999 8766 Before Mercurial begins the backout process, it first
belaran@999 8767 remembers what the current parent of the working directory is.
belaran@999 8768 It then backs out the target changeset, and commits that as a
belaran@999 8769 changeset. Finally, it merges back to the previous parent of
belaran@999 8770 the working directory, but notice that it <emphasis>does not
belaran@999 8771 commit</emphasis> the result of the merge. The repository
belaran@999 8772 now contains two heads, and the working directory is in a
belaran@999 8773 merge state.</para>
belaran@999 8774
belaran@999 8775 <figure id="fig:undo:backout-non-tip" float="0">
belaran@999 8776 <title>Automated backout of a non-tip change using the
belaran@999 8777 <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
belaran@999 8778 <mediaobject>
belaran@999 8779 <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject>
belaran@999 8780 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 8781 </mediaobject>
belaran@999 8782 </figure>
belaran@999 8783
belaran@999 8784 <para id="x_103">The result is that you end up <quote>back where you
belaran@999 8785 were</quote>, only with some extra history that undoes the
belaran@999 8786 effect of the changeset you wanted to back out.</para>
belaran@999 8787
belaran@999 8788 <para id="x_6b9">You might wonder why Mercurial does not commit the result
belaran@999 8789 of the merge that it performed. The reason lies in Mercurial
belaran@999 8790 behaving conservatively: a merge naturally has more scope for
belaran@999 8791 error than simply undoing the effect of the tip changeset,
belaran@999 8792 so your work will be safest if you first inspect (and test!)
belaran@999 8793 the result of the merge, <emphasis>then</emphasis> commit
belaran@999 8794 it.</para>
belaran@999 8795
belaran@999 8796 <sect3>
belaran@999 8797 <title>Always use the <option role="hg-opt-backout">--merge</option> option</title>
belaran@999 8798
belaran@999 8799 <para id="x_104">In fact, since the <option role="hg-opt-backout">--merge</option> option will do the
belaran@999 8800 <quote>right thing</quote> whether or not the changeset
belaran@999 8801 you're backing out is the tip (i.e. it won't try to merge if
belaran@999 8802 it's backing out the tip, since there's no need), you should
belaran@999 8803 <emphasis>always</emphasis> use this option when you run the
belaran@999 8804 <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para>
belaran@999 8805
belaran@999 8806 </sect3>
belaran@999 8807 </sect2>
belaran@999 8808 <sect2>
belaran@999 8809 <title>Gaining more control of the backout process</title>
belaran@999 8810
belaran@999 8811 <para id="x_105">While I've recommended that you always use the <option role="hg-opt-backout">--merge</option> option when backing
belaran@999 8812 out a change, the <command role="hg-cmd" moreinfo="none">hg backout</command>
belaran@999 8813 command lets you decide how to merge a backout changeset.
belaran@999 8814 Taking control of the backout process by hand is something you
belaran@999 8815 will rarely need to do, but it can be useful to understand
belaran@999 8816 what the <command role="hg-cmd" moreinfo="none">hg backout</command> command
belaran@999 8817 is doing for you automatically. To illustrate this, let's
belaran@999 8818 clone our first repository, but omit the backout change that
belaran@999 8819 it contains.</para>
belaran@999 8820
belaran@999 8821 <!-- BEGIN backout.manual.clone -->
belaran@999 8822 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 8823 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo newrepo</userinput>
belaran@999 8824 requesting all changes
belaran@999 8825 adding changesets
belaran@999 8826 adding manifests
belaran@999 8827 adding file changes
belaran@999 8828 added 2 changesets with 2 changes to 1 files
belaran@999 8829 updating working directory
belaran@999 8830 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 8831 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd newrepo</userinput>
belaran@999 8832 </screen>
belaran@999 8833 <!-- END backout.manual.clone -->
belaran@999 8834
belaran@999 8835
belaran@999 8836 <para id="x_106">As with our
belaran@999 8837 earlier example, We'll commit a third changeset, then back out
belaran@999 8838 its parent, and see what happens.</para>
belaran@999 8839
belaran@999 8840 <!-- BEGIN backout.manual.backout -->
belaran@999 8841 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change &gt;&gt; myfile</userinput>
belaran@999 8842 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput>
belaran@999 8843 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' 1</userinput>
belaran@999 8844 reverting myfile
belaran@999 8845 created new head
belaran@999 8846 changeset 3:bf906ee0baae backs out changeset 1:43700a9b3ec8
belaran@999 8847 the backout changeset is a new head - do not forget to merge
belaran@999 8848 (use "backout --merge" if you want to auto-merge)
belaran@999 8849 </screen>
belaran@999 8850 <!-- END backout.manual.backout -->
belaran@999 8851
belaran@999 8852
belaran@999 8853 <para id="x_107">Our new changeset is again a descendant of the changeset
belaran@999 8854 we backout out; it's thus a new head, <emphasis>not</emphasis>
belaran@999 8855 a descendant of the changeset that was the tip. The <command role="hg-cmd" moreinfo="none">hg backout</command> command was quite
belaran@999 8856 explicit in telling us this.</para>
belaran@999 8857
belaran@999 8858 <!-- BEGIN backout.manual.log -->
belaran@999 8859 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
belaran@999 8860 3[tip]:1 bf906ee0baae 2009-08-16 14:04 +0000 bos
belaran@999 8861 back out second change
belaran@999 8862
belaran@999 8863 2 2521379001ad 2009-08-16 14:04 +0000 bos
belaran@999 8864 third change
belaran@999 8865
belaran@999 8866 1 43700a9b3ec8 2009-08-16 14:04 +0000 bos
belaran@999 8867 second change
belaran@999 8868
belaran@999 8869 0 f2ef23d503fd 2009-08-16 14:04 +0000 bos
belaran@999 8870 first change
belaran@999 8871
belaran@999 8872 </screen>
belaran@999 8873 <!-- END backout.manual.log -->
belaran@999 8874
belaran@999 8875
belaran@999 8876 <para id="x_108">Again, it's easier to see what has happened by looking at
belaran@999 8877 a graph of the revision history, in <xref linkend="fig:undo:backout-manual"/>. This makes it clear
belaran@999 8878 that when we use <command role="hg-cmd" moreinfo="none">hg backout</command>
belaran@999 8879 to back out a change other than the tip, Mercurial adds a new
belaran@999 8880 head to the repository (the change it committed is
belaran@999 8881 box-shaped).</para>
belaran@999 8882
belaran@999 8883 <figure id="fig:undo:backout-manual" float="0">
belaran@999 8884 <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
belaran@999 8885 <mediaobject>
belaran@999 8886 <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject>
belaran@999 8887 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 8888 </mediaobject>
belaran@999 8889 </figure>
belaran@999 8890
belaran@999 8891 <para id="x_10a">After the <command role="hg-cmd" moreinfo="none">hg backout</command>
belaran@999 8892 command has completed, it leaves the new
belaran@999 8893 <quote>backout</quote> changeset as the parent of the working
belaran@999 8894 directory.</para>
belaran@999 8895
belaran@999 8896 <!-- BEGIN backout.manual.parents -->
belaran@999 8897 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
belaran@999 8898 changeset: 2:2521379001ad
belaran@999 8899 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8900 date: Sun Aug 16 14:04:37 2009 +0000
belaran@999 8901 summary: third change
belaran@999 8902
belaran@999 8903 </screen>
belaran@999 8904 <!-- END backout.manual.parents -->
belaran@999 8905
belaran@999 8906
belaran@999 8907 <para id="x_10b">Now we have two isolated sets of changes.</para>
belaran@999 8908
belaran@999 8909 <!-- BEGIN backout.manual.heads -->
belaran@999 8910 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
belaran@999 8911 changeset: 3:bf906ee0baae
belaran@999 8912 tag: tip
belaran@999 8913 parent: 1:43700a9b3ec8
belaran@999 8914 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8915 date: Sun Aug 16 14:04:37 2009 +0000
belaran@999 8916 summary: back out second change
belaran@999 8917
belaran@999 8918 changeset: 2:2521379001ad
belaran@999 8919 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 8920 date: Sun Aug 16 14:04:37 2009 +0000
belaran@999 8921 summary: third change
belaran@999 8922
belaran@999 8923 </screen>
belaran@999 8924 <!-- END backout.manual.heads -->
belaran@999 8925
belaran@999 8926
belaran@999 8927 <para id="x_10c">Let's think about what we expect to see as the contents of
belaran@999 8928 <filename moreinfo="none">myfile</filename> now. The first change should be
belaran@999 8929 present, because we've never backed it out. The second change
belaran@999 8930 should be missing, as that's the change we backed out. Since
belaran@999 8931 the history graph shows the third change as a separate head,
belaran@999 8932 we <emphasis>don't</emphasis> expect to see the third change
belaran@999 8933 present in <filename moreinfo="none">myfile</filename>.</para>
belaran@999 8934
belaran@999 8935 <!-- BEGIN backout.manual.cat -->
belaran@999 8936 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 8937 first change
belaran@999 8938 </screen>
belaran@999 8939 <!-- END backout.manual.cat -->
belaran@999 8940
belaran@999 8941
belaran@999 8942 <para id="x_10d">To get the third change back into the file, we just do a
belaran@999 8943 normal merge of our two heads.</para>
belaran@999 8944
belaran@999 8945 <!-- BEGIN backout.manual.merge -->
belaran@999 8946 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
belaran@999 8947 abort: outstanding uncommitted changes
belaran@999 8948 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'merged backout with previous tip'</userinput>
belaran@999 8949 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
belaran@999 8950 first change
belaran@999 8951 </screen>
belaran@999 8952 <!-- END backout.manual.merge -->
belaran@999 8953
belaran@999 8954
belaran@999 8955 <para id="x_10e">Afterwards, the graphical history of our
belaran@999 8956 repository looks like
belaran@999 8957 <xref linkend="fig:undo:backout-manual-merge"/>.</para>
belaran@999 8958
belaran@999 8959 <figure id="fig:undo:backout-manual-merge" float="0">
belaran@999 8960 <title>Manually merging a backout change</title>
belaran@999 8961 <mediaobject>
belaran@999 8962 <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject>
belaran@999 8963 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 8964 </mediaobject>
belaran@999 8965 </figure>
belaran@999 8966
belaran@999 8967 </sect2>
belaran@999 8968 <sect2>
belaran@999 8969 <title>Why <command role="hg-cmd" moreinfo="none">hg backout</command> works as
belaran@999 8970 it does</title>
belaran@999 8971
belaran@999 8972 <para id="x_110">Here's a brief description of how the <command role="hg-cmd" moreinfo="none">hg backout</command> command works.</para>
belaran@999 8973 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 8974 <listitem><para id="x_111">It ensures that the working directory is
belaran@999 8975 <quote>clean</quote>, i.e. that the output of <command role="hg-cmd" moreinfo="none">hg status</command> would be empty.</para>
belaran@999 8976 </listitem>
belaran@999 8977 <listitem><para id="x_112">It remembers the current parent of the working
belaran@999 8978 directory. Let's call this changeset
belaran@999 8979 <literal moreinfo="none">orig</literal>.</para>
belaran@999 8980 </listitem>
belaran@999 8981 <listitem><para id="x_113">It does the equivalent of a <command role="hg-cmd" moreinfo="none">hg update</command> to sync the working
belaran@999 8982 directory to the changeset you want to back out. Let's
belaran@999 8983 call this changeset <literal moreinfo="none">backout</literal>.</para>
belaran@999 8984 </listitem>
belaran@999 8985 <listitem><para id="x_114">It finds the parent of that changeset. Let's
belaran@999 8986 call that changeset <literal moreinfo="none">parent</literal>.</para>
belaran@999 8987 </listitem>
belaran@999 8988 <listitem><para id="x_115">For each file that the
belaran@999 8989 <literal moreinfo="none">backout</literal> changeset affected, it does the
belaran@999 8990 equivalent of a <command role="hg-cmd" moreinfo="none">hg revert -r
belaran@999 8991 parent</command> on that file, to restore it to the
belaran@999 8992 contents it had before that changeset was
belaran@999 8993 committed.</para>
belaran@999 8994 </listitem>
belaran@999 8995 <listitem><para id="x_116">It commits the result as a new changeset.
belaran@999 8996 This changeset has <literal moreinfo="none">backout</literal> as its
belaran@999 8997 parent.</para>
belaran@999 8998 </listitem>
belaran@999 8999 <listitem><para id="x_117">If you specify <option role="hg-opt-backout">--merge</option> on the command
belaran@999 9000 line, it merges with <literal moreinfo="none">orig</literal>, and commits
belaran@999 9001 the result of the merge.</para>
belaran@999 9002 </listitem></orderedlist>
belaran@999 9003
belaran@999 9004 <para id="x_118">An alternative way to implement the <command role="hg-cmd" moreinfo="none">hg backout</command> command would be to
belaran@999 9005 <command role="hg-cmd" moreinfo="none">hg export</command> the
belaran@999 9006 to-be-backed-out changeset as a diff, then use the <option role="cmd-opt-patch">--reverse</option> option to the
belaran@999 9007 <command moreinfo="none">patch</command> command to reverse the effect of the
belaran@999 9008 change without fiddling with the working directory. This
belaran@999 9009 sounds much simpler, but it would not work nearly as
belaran@999 9010 well.</para>
belaran@999 9011
belaran@999 9012 <para id="x_119">The reason that <command role="hg-cmd" moreinfo="none">hg
belaran@999 9013 backout</command> does an update, a commit, a merge, and
belaran@999 9014 another commit is to give the merge machinery the best chance
belaran@999 9015 to do a good job when dealing with all the changes
belaran@999 9016 <emphasis>between</emphasis> the change you're backing out and
belaran@999 9017 the current tip.</para>
belaran@999 9018
belaran@999 9019 <para id="x_11a">If you're backing out a changeset that's 100 revisions
belaran@999 9020 back in your project's history, the chances that the
belaran@999 9021 <command moreinfo="none">patch</command> command will be able to apply a
belaran@999 9022 reverse diff cleanly are not good, because intervening changes
belaran@999 9023 are likely to have <quote>broken the context</quote> that
belaran@999 9024 <command moreinfo="none">patch</command> uses to determine whether it can
belaran@999 9025 apply a patch (if this sounds like gibberish, see <xref linkend="sec:mq:patch"/> for a
belaran@999 9026 discussion of the <command moreinfo="none">patch</command> command). Also,
belaran@999 9027 Mercurial's merge machinery will handle files and directories
belaran@999 9028 being renamed, permission changes, and modifications to binary
belaran@999 9029 files, none of which <command moreinfo="none">patch</command> can deal
belaran@999 9030 with.</para>
belaran@999 9031
belaran@999 9032 </sect2>
belaran@999 9033 </sect1>
belaran@999 9034 <sect1 id="sec:undo:aaaiiieee">
belaran@999 9035 <title>Changes that should never have been</title>
belaran@999 9036
belaran@999 9037 <para id="x_11b">Most of the time, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9038 backout</command> command is exactly what you need if you want
belaran@999 9039 to undo the effects of a change. It leaves a permanent record
belaran@999 9040 of exactly what you did, both when committing the original
belaran@999 9041 changeset and when you cleaned up after it.</para>
belaran@999 9042
belaran@999 9043 <para id="x_11c">On rare occasions, though, you may find that you've
belaran@999 9044 committed a change that really should not be present in the
belaran@999 9045 repository at all. For example, it would be very unusual, and
belaran@999 9046 usually considered a mistake, to commit a software project's
belaran@999 9047 object files as well as its source files. Object files have
belaran@999 9048 almost no intrinsic value, and they're <emphasis>big</emphasis>,
belaran@999 9049 so they increase the size of the repository and the amount of
belaran@999 9050 time it takes to clone or pull changes.</para>
belaran@999 9051
belaran@999 9052 <para id="x_11d">Before I discuss the options that you have if you commit a
belaran@999 9053 <quote>brown paper bag</quote> change (the kind that's so bad
belaran@999 9054 that you want to pull a brown paper bag over your head), let me
belaran@999 9055 first discuss some approaches that probably won't work.</para>
belaran@999 9056
belaran@999 9057 <para id="x_11e">Since Mercurial treats history as
belaran@999 9058 accumulative—every change builds on top of all changes
belaran@999 9059 that preceded it—you generally can't just make disastrous
belaran@999 9060 changes disappear. The one exception is when you've just
belaran@999 9061 committed a change, and it hasn't been pushed or pulled into
belaran@999 9062 another repository. That's when you can safely use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, as I detailed in
belaran@999 9063 <xref linkend="sec:undo:rollback"/>.</para>
belaran@999 9064
belaran@999 9065 <para id="x_11f">After you've pushed a bad change to another repository, you
belaran@999 9066 <emphasis>could</emphasis> still use <command role="hg-cmd" moreinfo="none">hg
belaran@999 9067 rollback</command> to make your local copy of the change
belaran@999 9068 disappear, but it won't have the consequences you want. The
belaran@999 9069 change will still be present in the remote repository, so it
belaran@999 9070 will reappear in your local repository the next time you
belaran@999 9071 pull.</para>
belaran@999 9072
belaran@999 9073 <para id="x_120">If a situation like this arises, and you know which
belaran@999 9074 repositories your bad change has propagated into, you can
belaran@999 9075 <emphasis>try</emphasis> to get rid of the change from
belaran@999 9076 <emphasis>every</emphasis> one of those repositories. This is,
belaran@999 9077 of course, not a satisfactory solution: if you miss even a
belaran@999 9078 single repository while you're expunging, the change is still
belaran@999 9079 <quote>in the wild</quote>, and could propagate further.</para>
belaran@999 9080
belaran@999 9081 <para id="x_121">If you've committed one or more changes
belaran@999 9082 <emphasis>after</emphasis> the change that you'd like to see
belaran@999 9083 disappear, your options are further reduced. Mercurial doesn't
belaran@999 9084 provide a way to <quote>punch a hole</quote> in history, leaving
belaran@999 9085 changesets intact.</para>
belaran@999 9086
belaran@999 9087 <sect2>
belaran@999 9088 <title>Backing out a merge</title>
belaran@999 9089
belaran@999 9090 <para id="x_6ba">Since merges are often complicated, it is not unheard of
belaran@999 9091 for a merge to be mangled badly, but committed erroneously.
belaran@999 9092 Mercurial provides an important safeguard against bad merges
belaran@999 9093 by refusing to commit unresolved files, but human ingenuity
belaran@999 9094 guarantees that it is still possible to mess a merge up and
belaran@999 9095 commit it.</para>
belaran@999 9096
belaran@999 9097 <para id="x_6bb">Given a bad merge that has been committed, usually the
belaran@999 9098 best way to approach it is to simply try to repair the damage
belaran@999 9099 by hand. A complete disaster that cannot be easily fixed up
belaran@999 9100 by hand ought to be very rare, but the <command role="hg-cmd" moreinfo="none">hg backout</command> command may help in
belaran@999 9101 making the cleanup easier. It offers a <option role="hg-opt-backout">--parent</option> option, which lets
belaran@999 9102 you specify which parent to revert to when backing out a
belaran@999 9103 merge.</para>
belaran@999 9104
belaran@999 9105 <figure id="fig:undo:bad-merge-1" float="0">
belaran@999 9106 <title>A bad merge</title>
belaran@999 9107 <mediaobject>
belaran@999 9108 <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
belaran@999 9109 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 9110 </mediaobject>
belaran@999 9111 </figure>
belaran@999 9112
belaran@999 9113 <para id="x_6bc">Suppose we have a revision graph like that in <xref linkend="fig:undo:bad-merge-1"/>. What we'd like is to
belaran@999 9114 <emphasis>redo</emphasis> the merge of revisions 2 and
belaran@999 9115 3.</para>
belaran@999 9116
belaran@999 9117 <para id="x_6bd">One way to do so would be as follows.</para>
belaran@999 9118
belaran@999 9119 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 9120 <listitem>
belaran@999 9121 <para id="x_6be">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4
belaran@999 9122 --parent=2</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision
belaran@999 9123 4, which is the bad merge, and to when deciding which
belaran@999 9124 revision to prefer, to choose parent 2, one of the parents
belaran@999 9125 of the merge. The effect can be seen in <xref linkend="fig:undo:bad-merge-2"/>.</para>
belaran@999 9126 <figure id="fig:undo:bad-merge-2" float="0">
belaran@999 9127 <title>Backing out the merge, favoring one parent</title>
belaran@999 9128 <mediaobject>
belaran@999 9129 <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
belaran@999 9130 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 9131 </mediaobject>
belaran@999 9132 </figure>
belaran@999 9133 </listitem>
belaran@999 9134
belaran@999 9135 <listitem>
belaran@999 9136 <para id="x_6bf">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4
belaran@999 9137 --parent=3</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision
belaran@999 9138 4 again, but this time to choose parent 3, the other
belaran@999 9139 parent of the merge. The result is visible in <xref linkend="fig:undo:bad-merge-3"/>, in which the repository
belaran@999 9140 now contains three heads.</para>
belaran@999 9141 <figure id="fig:undo:bad-merge-3" float="0">
belaran@999 9142 <title>Backing out the merge, favoring the other
belaran@999 9143 parent</title>
belaran@999 9144 <mediaobject>
belaran@999 9145 <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
belaran@999 9146 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 9147 </mediaobject>
belaran@999 9148 </figure>
belaran@999 9149 </listitem>
belaran@999 9150
belaran@999 9151 <listitem>
belaran@999 9152 <para id="x_6c0">Redo the bad merge by merging the two backout heads,
belaran@999 9153 which reduces the number of heads in the repository to
belaran@999 9154 two, as can be seen in <xref linkend="fig:undo:bad-merge-4"/>.</para>
belaran@999 9155 <figure id="fig:undo:bad-merge-4" float="0">
belaran@999 9156 <title>Merging the backouts</title>
belaran@999 9157 <mediaobject>
belaran@999 9158 <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
belaran@999 9159 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 9160 </mediaobject>
belaran@999 9161 </figure>
belaran@999 9162 </listitem>
belaran@999 9163
belaran@999 9164 <listitem>
belaran@999 9165 <para id="x_6c1">Merge with the commit that was made after the bad
belaran@999 9166 merge, as shown in <xref linkend="fig:undo:bad-merge-5"/>.</para>
belaran@999 9167 <figure id="fig:undo:bad-merge-5" float="0">
belaran@999 9168 <title>Merging the backouts</title>
belaran@999 9169 <mediaobject>
belaran@999 9170 <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
belaran@999 9171 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 9172 </mediaobject>
belaran@999 9173 </figure>
belaran@999 9174 </listitem>
belaran@999 9175 </orderedlist>
belaran@999 9176 </sect2>
belaran@999 9177
belaran@999 9178 <sect2>
belaran@999 9179 <title>Protect yourself from <quote>escaped</quote>
belaran@999 9180 changes</title>
belaran@999 9181
belaran@999 9182 <para id="x_123">If you've committed some changes to your local repository
belaran@999 9183 and they've been pushed or pulled somewhere else, this isn't
belaran@999 9184 necessarily a disaster. You can protect yourself ahead of
belaran@999 9185 time against some classes of bad changeset. This is
belaran@999 9186 particularly easy if your team usually pulls changes from a
belaran@999 9187 central repository.</para>
belaran@999 9188
belaran@999 9189 <para id="x_124">By configuring some hooks on that repository to validate
belaran@999 9190 incoming changesets (see chapter <xref linkend="chap:hook"/>),
belaran@999 9191 you can
belaran@999 9192 automatically prevent some kinds of bad changeset from being
belaran@999 9193 pushed to the central repository at all. With such a
belaran@999 9194 configuration in place, some kinds of bad changeset will
belaran@999 9195 naturally tend to <quote>die out</quote> because they can't
belaran@999 9196 propagate into the central repository. Better yet, this
belaran@999 9197 happens without any need for explicit intervention.</para>
belaran@999 9198
belaran@999 9199 <para id="x_125">For instance, an incoming change hook that
belaran@999 9200 verifies that a changeset will actually compile can prevent
belaran@999 9201 people from inadvertently <quote>breaking the
belaran@999 9202 build</quote>.</para>
belaran@999 9203 </sect2>
belaran@999 9204
belaran@999 9205 <sect2>
belaran@999 9206 <title>What to do about sensitive changes that escape</title>
belaran@999 9207
belaran@999 9208 <para id="x_6c2">Even a carefully run project can suffer an unfortunate
belaran@999 9209 event such as the committing and uncontrolled propagation of a
belaran@999 9210 file that contains important passwords.</para>
belaran@999 9211
belaran@999 9212 <para id="x_6c3">If something like this happens to you, and the information
belaran@999 9213 that gets accidentally propagated is truly sensitive, your
belaran@999 9214 first step should be to mitigate the effect of the leak
belaran@999 9215 without trying to control the leak itself. If you are not 100%
belaran@999 9216 certain that you know exactly who could have seen the changes,
belaran@999 9217 you should immediately change passwords, cancel credit cards,
belaran@999 9218 or find some other way to make sure that the information that
belaran@999 9219 has leaked is no longer useful. In other words, assume that
belaran@999 9220 the change has propagated far and wide, and that there's
belaran@999 9221 nothing more you can do.</para>
belaran@999 9222
belaran@999 9223 <para id="x_6c4">You might hope that there would be mechanisms you could
belaran@999 9224 use to either figure out who has seen a change or to erase the
belaran@999 9225 change permanently everywhere, but there are good reasons why
belaran@999 9226 these are not possible.</para>
belaran@999 9227
belaran@999 9228 <para id="x_6c5">Mercurial does not provide an audit trail of who has
belaran@999 9229 pulled changes from a repository, because it is usually either
belaran@999 9230 impossible to record such information or trivial to spoof it.
belaran@999 9231 In a multi-user or networked environment, you should thus be
belaran@999 9232 extremely skeptical of yourself if you think that you have
belaran@999 9233 identified every place that a sensitive changeset has
belaran@999 9234 propagated to. Don't forget that people can and will send
belaran@999 9235 bundles by email, have their backup software save data
belaran@999 9236 offsite, carry repositories on USB sticks, and find other
belaran@999 9237 completely innocent ways to confound your attempts to track
belaran@999 9238 down every copy of a problematic change.</para>
belaran@999 9239
belaran@999 9240 <para id="x_6c6">Mercurial also does not provide a way to make a file or
belaran@999 9241 changeset completely disappear from history, because there is
belaran@999 9242 no way to enforce its disappearance; someone could easily
belaran@999 9243 modify their copy of Mercurial to ignore such directives. In
belaran@999 9244 addition, even if Mercurial provided such a capability,
belaran@999 9245 someone who simply hadn't pulled a <quote>make this file
belaran@999 9246 disappear</quote> changeset wouldn't be affected by it, nor
belaran@999 9247 would web crawlers visiting at the wrong time, disk backups,
belaran@999 9248 or other mechanisms. Indeed, no distributed revision control
belaran@999 9249 system can make data reliably vanish. Providing the illusion
belaran@999 9250 of such control could easily give a false sense of security,
belaran@999 9251 and be worse than not providing it at all.</para>
belaran@999 9252 </sect2>
belaran@999 9253 </sect1>
belaran@999 9254
belaran@999 9255 <sect1 id="sec:undo:bisect">
belaran@999 9256 <title>Finding the source of a bug</title>
belaran@999 9257
belaran@999 9258 <para id="x_126">While it's all very well to be able to back out a changeset
belaran@999 9259 that introduced a bug, this requires that you know which
belaran@999 9260 changeset to back out. Mercurial provides an invaluable
belaran@999 9261 command, called <command role="hg-cmd" moreinfo="none">hg bisect</command>, that
belaran@999 9262 helps you to automate this process and accomplish it very
belaran@999 9263 efficiently.</para>
belaran@999 9264
belaran@999 9265 <para id="x_127">The idea behind the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9266 bisect</command> command is that a changeset has introduced
belaran@999 9267 some change of behavior that you can identify with a simple
belaran@999 9268 pass/fail test. You don't know which piece of code introduced the
belaran@999 9269 change, but you know how to test for the presence of the bug.
belaran@999 9270 The <command role="hg-cmd" moreinfo="none">hg bisect</command> command uses your
belaran@999 9271 test to direct its search for the changeset that introduced the
belaran@999 9272 code that caused the bug.</para>
belaran@999 9273
belaran@999 9274 <para id="x_128">Here are a few scenarios to help you understand how you
belaran@999 9275 might apply this command.</para>
belaran@999 9276 <itemizedlist>
belaran@999 9277 <listitem><para id="x_129">The most recent version of your software has a
belaran@999 9278 bug that you remember wasn't present a few weeks ago, but
belaran@999 9279 you don't know when it was introduced. Here, your binary
belaran@999 9280 test checks for the presence of that bug.</para>
belaran@999 9281 </listitem>
belaran@999 9282 <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to
belaran@999 9283 close the entry in your team's bug database. The bug
belaran@999 9284 database requires a changeset ID when you close an entry,
belaran@999 9285 but you don't remember which changeset you fixed the bug in.
belaran@999 9286 Once again, your binary test checks for the presence of the
belaran@999 9287 bug.</para>
belaran@999 9288 </listitem>
belaran@999 9289 <listitem><para id="x_12b">Your software works correctly, but runs 15%
belaran@999 9290 slower than the last time you measured it. You want to know
belaran@999 9291 which changeset introduced the performance regression. In
belaran@999 9292 this case, your binary test measures the performance of your
belaran@999 9293 software, to see whether it's <quote>fast</quote> or
belaran@999 9294 <quote>slow</quote>.</para>
belaran@999 9295 </listitem>
belaran@999 9296 <listitem><para id="x_12c">The sizes of the components of your project that
belaran@999 9297 you ship exploded recently, and you suspect that something
belaran@999 9298 changed in the way you build your project.</para>
belaran@999 9299 </listitem></itemizedlist>
belaran@999 9300
belaran@999 9301 <para id="x_12d">From these examples, it should be clear that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command is not useful only
belaran@999 9302 for finding the sources of bugs. You can use it to find any
belaran@999 9303 <quote>emergent property</quote> of a repository (anything that
belaran@999 9304 you can't find from a simple text search of the files in the
belaran@999 9305 tree) for which you can write a binary test.</para>
belaran@999 9306
belaran@999 9307 <para id="x_12e">We'll introduce a little bit of terminology here, just to
belaran@999 9308 make it clear which parts of the search process are your
belaran@999 9309 responsibility, and which are Mercurial's. A
belaran@999 9310 <emphasis>test</emphasis> is something that
belaran@999 9311 <emphasis>you</emphasis> run when <command role="hg-cmd" moreinfo="none">hg
belaran@999 9312 bisect</command> chooses a changeset. A
belaran@999 9313 <emphasis>probe</emphasis> is what <command role="hg-cmd" moreinfo="none">hg
belaran@999 9314 bisect</command> runs to tell whether a revision is good.
belaran@999 9315 Finally, we'll use the word <quote>bisect</quote>, as both a
belaran@999 9316 noun and a verb, to stand in for the phrase <quote>search using
belaran@999 9317 the <command role="hg-cmd" moreinfo="none">hg bisect</command>
belaran@999 9318 command</quote>.</para>
belaran@999 9319
belaran@999 9320 <para id="x_12f">One simple way to automate the searching process would be
belaran@999 9321 simply to probe every changeset. However, this scales poorly.
belaran@999 9322 If it took ten minutes to test a single changeset, and you had
belaran@999 9323 10,000 changesets in your repository, the exhaustive approach
belaran@999 9324 would take on average 35 <emphasis>days</emphasis> to find the
belaran@999 9325 changeset that introduced a bug. Even if you knew that the bug
belaran@999 9326 was introduced by one of the last 500 changesets, and limited
belaran@999 9327 your search to those, you'd still be looking at over 40 hours to
belaran@999 9328 find the changeset that introduced your bug.</para>
belaran@999 9329
belaran@999 9330 <para id="x_130">What the <command role="hg-cmd" moreinfo="none">hg bisect</command> command
belaran@999 9331 does is use its knowledge of the <quote>shape</quote> of your
belaran@999 9332 project's revision history to perform a search in time
belaran@999 9333 proportional to the <emphasis>logarithm</emphasis> of the number
belaran@999 9334 of changesets to check (the kind of search it performs is called
belaran@999 9335 a dichotomic search). With this approach, searching through
belaran@999 9336 10,000 changesets will take less than three hours, even at ten
belaran@999 9337 minutes per test (the search will require about 14 tests).
belaran@999 9338 Limit your search to the last hundred changesets, and it will
belaran@999 9339 take only about an hour (roughly seven tests).</para>
belaran@999 9340
belaran@999 9341 <para id="x_131">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command is
belaran@999 9342 aware of the <quote>branchy</quote> nature of a Mercurial
belaran@999 9343 project's revision history, so it has no problems dealing with
belaran@999 9344 branches, merges, or multiple heads in a repository. It can
belaran@999 9345 prune entire branches of history with a single probe, which is
belaran@999 9346 how it operates so efficiently.</para>
belaran@999 9347
belaran@999 9348 <sect2>
belaran@999 9349 <title>Using the <command role="hg-cmd" moreinfo="none">hg bisect</command>
belaran@999 9350 command</title>
belaran@999 9351
belaran@999 9352 <para id="x_132">Here's an example of <command role="hg-cmd" moreinfo="none">hg
belaran@999 9353 bisect</command> in action.</para>
belaran@999 9354
belaran@999 9355 <note>
belaran@999 9356 <para id="x_133"> In versions 0.9.5 and earlier of Mercurial, <command role="hg-cmd" moreinfo="none">hg bisect</command> was not a core command:
belaran@999 9357 it was distributed with Mercurial as an extension. This
belaran@999 9358 section describes the built-in command, not the old
belaran@999 9359 extension.</para>
belaran@999 9360 </note>
belaran@999 9361
belaran@999 9362 <para id="x_134">Now let's create a repository, so that we can try out the
belaran@999 9363 <command role="hg-cmd" moreinfo="none">hg bisect</command> command in
belaran@999 9364 isolation.</para>
belaran@999 9365
belaran@999 9366 <!-- BEGIN bisect.init -->
belaran@999 9367 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mybug</userinput>
belaran@999 9368 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mybug</userinput>
belaran@999 9369 </screen>
belaran@999 9370 <!-- END bisect.init -->
belaran@999 9371
belaran@999 9372
belaran@999 9373 <para id="x_135">We'll simulate a project that has a bug in it in a
belaran@999 9374 simple-minded way: create trivial changes in a loop, and
belaran@999 9375 nominate one specific change that will have the
belaran@999 9376 <quote>bug</quote>. This loop creates 35 changesets, each
belaran@999 9377 adding a single file to the repository. We'll represent our
belaran@999 9378 <quote>bug</quote> with a file that contains the text <quote>i
belaran@999 9379 have a gub</quote>.</para>
belaran@999 9380
belaran@999 9381 <!-- BEGIN bisect.commits -->
belaran@999 9382 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">buggy_change=22</userinput>
belaran@999 9383 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">for (( i = 0; i &lt; 35; i++ )); do</userinput>
belaran@999 9384 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> if [[ $i = $buggy_change ]]; then</userinput>
belaran@999 9385 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> echo 'i have a gub' &gt; myfile$i</userinput>
belaran@999 9386 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> hg commit -q -A -m 'buggy changeset'</userinput>
belaran@999 9387 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> else</userinput>
belaran@999 9388 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> echo 'nothing to see here, move along' &gt; myfile$i</userinput>
belaran@999 9389 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> hg commit -q -A -m 'normal changeset'</userinput>
belaran@999 9390 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> fi</userinput>
belaran@999 9391 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">done</userinput>
belaran@999 9392 </screen>
belaran@999 9393 <!-- END bisect.commits -->
belaran@999 9394
belaran@999 9395
belaran@999 9396 <para id="x_136">The next thing that we'd like to do is figure out how to
belaran@999 9397 use the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.
belaran@999 9398 We can use Mercurial's normal built-in help mechanism for
belaran@999 9399 this.</para>
belaran@999 9400
belaran@999 9401 <!-- BEGIN bisect.help -->
belaran@999 9402 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help bisect</userinput>
belaran@999 9403 hg bisect [-gbsr] [-c CMD] [REV]
belaran@999 9404
belaran@999 9405 subdivision search of changesets
belaran@999 9406
belaran@999 9407 This command helps to find changesets which introduce problems.
belaran@999 9408 To use, mark the earliest changeset you know exhibits the problem
belaran@999 9409 as bad, then mark the latest changeset which is free from the
belaran@999 9410 problem as good. Bisect will update your working directory to a
belaran@999 9411 revision for testing (unless the --noupdate option is specified).
belaran@999 9412 Once you have performed tests, mark the working directory as bad
belaran@999 9413 or good and bisect will either update to another candidate changeset
belaran@999 9414 or announce that it has found the bad revision.
belaran@999 9415
belaran@999 9416 As a shortcut, you can also use the revision argument to mark a
belaran@999 9417 revision as good or bad without checking it out first.
belaran@999 9418
belaran@999 9419 If you supply a command it will be used for automatic bisection. Its exit
belaran@999 9420 status will be used as flag to mark revision as bad or good. In case exit
belaran@999 9421 status is 0 the revision is marked as good, 125 - skipped, 127 (command not
belaran@999 9422 found) - bisection will be aborted; any other status bigger than 0 will
belaran@999 9423 mark revision as bad.
belaran@999 9424
belaran@999 9425 options:
belaran@999 9426
belaran@999 9427 -r --reset reset bisect state
belaran@999 9428 -g --good mark changeset good
belaran@999 9429 -b --bad mark changeset bad
belaran@999 9430 -s --skip skip testing changeset
belaran@999 9431 -c --command use command to check changeset state
belaran@999 9432 -U --noupdate do not update to target
belaran@999 9433
belaran@999 9434 use "hg -v help bisect" to show global options
belaran@999 9435 </screen>
belaran@999 9436 <!-- END bisect.help -->
belaran@999 9437
belaran@999 9438
belaran@999 9439 <para id="x_137">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command
belaran@999 9440 works in steps. Each step proceeds as follows.</para>
belaran@999 9441 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 9442 <listitem><para id="x_138">You run your binary test.</para>
belaran@999 9443 <itemizedlist>
belaran@999 9444 <listitem><para id="x_139">If the test succeeded, you tell <command role="hg-cmd" moreinfo="none">hg bisect</command> by running the
belaran@999 9445 <command role="hg-cmd" moreinfo="none">hg bisect --good</command>
belaran@999 9446 command.</para>
belaran@999 9447 </listitem>
belaran@999 9448 <listitem><para id="x_13a">If it failed, run the <command role="hg-cmd" moreinfo="none">hg bisect --bad</command>
belaran@999 9449 command.</para></listitem></itemizedlist>
belaran@999 9450 </listitem>
belaran@999 9451 <listitem><para id="x_13b">The command uses your information to decide
belaran@999 9452 which changeset to test next.</para>
belaran@999 9453 </listitem>
belaran@999 9454 <listitem><para id="x_13c">It updates the working directory to that
belaran@999 9455 changeset, and the process begins again.</para>
belaran@999 9456 </listitem></orderedlist>
belaran@999 9457 <para id="x_13d">The process ends when <command role="hg-cmd" moreinfo="none">hg
belaran@999 9458 bisect</command> identifies a unique changeset that marks
belaran@999 9459 the point where your test transitioned from
belaran@999 9460 <quote>succeeding</quote> to <quote>failing</quote>.</para>
belaran@999 9461
belaran@999 9462 <para id="x_13e">To start the search, we must run the <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command.</para>
belaran@999 9463
belaran@999 9464 <!-- BEGIN bisect.search.init -->
belaran@999 9465 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput>
belaran@999 9466 </screen>
belaran@999 9467 <!-- END bisect.search.init -->
belaran@999 9468
belaran@999 9469
belaran@999 9470 <para id="x_13f">In our case, the binary test we use is simple: we check to
belaran@999 9471 see if any file in the repository contains the string <quote>i
belaran@999 9472 have a gub</quote>. If it does, this changeset contains the
belaran@999 9473 change that <quote>caused the bug</quote>. By convention, a
belaran@999 9474 changeset that has the property we're searching for is
belaran@999 9475 <quote>bad</quote>, while one that doesn't is
belaran@999 9476 <quote>good</quote>.</para>
belaran@999 9477
belaran@999 9478 <para id="x_140">Most of the time, the revision to which the working
belaran@999 9479 directory is synced (usually the tip) already exhibits the
belaran@999 9480 problem introduced by the buggy change, so we'll mark it as
belaran@999 9481 <quote>bad</quote>.</para>
belaran@999 9482
belaran@999 9483 <!-- BEGIN bisect.search.bad-init -->
belaran@999 9484 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --bad</userinput>
belaran@999 9485 </screen>
belaran@999 9486 <!-- END bisect.search.bad-init -->
belaran@999 9487
belaran@999 9488
belaran@999 9489 <para id="x_141">Our next task is to nominate a changeset that we know
belaran@999 9490 <emphasis>doesn't</emphasis> have the bug; the <command role="hg-cmd" moreinfo="none">hg bisect</command> command will
belaran@999 9491 <quote>bracket</quote> its search between the first pair of
belaran@999 9492 good and bad changesets. In our case, we know that revision
belaran@999 9493 10 didn't have the bug. (I'll have more words about choosing
belaran@999 9494 the first <quote>good</quote> changeset later.)</para>
belaran@999 9495
belaran@999 9496 <!-- BEGIN bisect.search.good-init -->
belaran@999 9497 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --good 10</userinput>
belaran@999 9498 Testing changeset 22:69f52b967ab8 (24 changesets remaining, ~4 tests)
belaran@999 9499 0 files updated, 0 files merged, 12 files removed, 0 files unresolved
belaran@999 9500 </screen>
belaran@999 9501 <!-- END bisect.search.good-init -->
belaran@999 9502
belaran@999 9503
belaran@999 9504 <para id="x_142">Notice that this command printed some output.</para>
belaran@999 9505 <itemizedlist>
belaran@999 9506 <listitem><para id="x_143">It told us how many changesets it must
belaran@999 9507 consider before it can identify the one that introduced
belaran@999 9508 the bug, and how many tests that will require.</para>
belaran@999 9509 </listitem>
belaran@999 9510 <listitem><para id="x_144">It updated the working directory to the next
belaran@999 9511 changeset to test, and told us which changeset it's
belaran@999 9512 testing.</para>
belaran@999 9513 </listitem></itemizedlist>
belaran@999 9514
belaran@999 9515 <para id="x_145">We now run our test in the working directory. We use the
belaran@999 9516 <command moreinfo="none">grep</command> command to see if our
belaran@999 9517 <quote>bad</quote> file is present in the working directory.
belaran@999 9518 If it is, this revision is bad; if not, this revision is good.
belaran@999 9519 <!-- BEGIN bisect.search.step1 -->
belaran@999 9520 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">if grep -q 'i have a gub' *</userinput>
belaran@999 9521 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">then</userinput>
belaran@999 9522 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> result=bad</userinput>
belaran@999 9523 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">else</userinput>
belaran@999 9524 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> result=good</userinput>
belaran@999 9525 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">fi</userinput>
belaran@999 9526 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo this revision is $result</userinput>
belaran@999 9527 this revision is bad
belaran@999 9528 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --$result</userinput>
belaran@999 9529 Testing changeset 16:f1dd8bc690ae (12 changesets remaining, ~3 tests)
belaran@999 9530 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
belaran@999 9531 </screen>
belaran@999 9532 <!-- END bisect.search.step1 -->
belaran@999 9533 </para>
belaran@999 9534
belaran@999 9535 <para id="x_146">This test looks like a perfect candidate for automation,
belaran@999 9536 so let's turn it into a shell function.</para>
belaran@999 9537 <!-- BEGIN bisect.search.mytest -->
belaran@999 9538 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest() {</userinput>
belaran@999 9539 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> if grep -q 'i have a gub' *</userinput>
belaran@999 9540 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> then</userinput>
belaran@999 9541 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> result=bad</userinput>
belaran@999 9542 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> else</userinput>
belaran@999 9543 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> result=good</userinput>
belaran@999 9544 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> fi</userinput>
belaran@999 9545 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> echo this revision is $result</userinput>
belaran@999 9546 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none"> hg bisect --$result</userinput>
belaran@999 9547 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">}</userinput>
belaran@999 9548 </screen>
belaran@999 9549 <!-- END bisect.search.mytest -->
belaran@999 9550
belaran@999 9551
belaran@999 9552 <para id="x_147">We can now run an entire test step with a single command,
belaran@999 9553 <literal moreinfo="none">mytest</literal>.</para>
belaran@999 9554
belaran@999 9555 <!-- BEGIN bisect.search.step2 -->
belaran@999 9556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
belaran@999 9557 this revision is good
belaran@999 9558 Testing changeset 19:88d99d97058a (6 changesets remaining, ~2 tests)
belaran@999 9559 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 9560 </screen>
belaran@999 9561 <!-- END bisect.search.step2 -->
belaran@999 9562
belaran@999 9563
belaran@999 9564 <para id="x_148">A few more invocations of our canned test step command,
belaran@999 9565 and we're done.</para>
belaran@999 9566
belaran@999 9567 <!-- BEGIN bisect.search.rest -->
belaran@999 9568 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
belaran@999 9569 this revision is good
belaran@999 9570 Testing changeset 20:32a195a31d51 (3 changesets remaining, ~1 tests)
belaran@999 9571 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 9572 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
belaran@999 9573 this revision is good
belaran@999 9574 Testing changeset 21:a2efe8e4f624 (2 changesets remaining, ~1 tests)
belaran@999 9575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 9576 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
belaran@999 9577 this revision is good
belaran@999 9578 The first bad revision is:
belaran@999 9579 changeset: 22:69f52b967ab8
belaran@999 9580 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 9581 date: Sun Aug 16 14:04:39 2009 +0000
belaran@999 9582 summary: buggy changeset
belaran@999 9583
belaran@999 9584 </screen>
belaran@999 9585 <!-- END bisect.search.rest -->
belaran@999 9586
belaran@999 9587
belaran@999 9588 <para id="x_149">Even though we had 40 changesets to search through, the
belaran@999 9589 <command role="hg-cmd" moreinfo="none">hg bisect</command> command let us find
belaran@999 9590 the changeset that introduced our <quote>bug</quote> with only
belaran@999 9591 five tests. Because the number of tests that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command performs grows
belaran@999 9592 logarithmically with the number of changesets to search, the
belaran@999 9593 advantage that it has over the <quote>brute force</quote>
belaran@999 9594 search approach increases with every changeset you add.</para>
belaran@999 9595
belaran@999 9596 </sect2>
belaran@999 9597 <sect2>
belaran@999 9598 <title>Cleaning up after your search</title>
belaran@999 9599
belaran@999 9600 <para id="x_14a">When you're finished using the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9601 bisect</command> command in a repository, you can use the
belaran@999 9602 <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command to
belaran@999 9603 drop the information it was using to drive your search. The
belaran@999 9604 command doesn't use much space, so it doesn't matter if you
belaran@999 9605 forget to run this command. However, <command role="hg-cmd" moreinfo="none">hg bisect</command> won't let you start a new
belaran@999 9606 search in that repository until you do a <command role="hg-cmd" moreinfo="none">hg bisect --reset</command>.</para>
belaran@999 9607
belaran@999 9608 <!-- BEGIN bisect.search.reset -->
belaran@999 9609 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput>
belaran@999 9610 </screen>
belaran@999 9611 <!-- END bisect.search.reset -->
belaran@999 9612
belaran@999 9613
belaran@999 9614 </sect2>
belaran@999 9615 </sect1>
belaran@999 9616 <sect1>
belaran@999 9617 <title>Tips for finding bugs effectively</title>
belaran@999 9618
belaran@999 9619 <sect2>
belaran@999 9620 <title>Give consistent input</title>
belaran@999 9621
belaran@999 9622 <para id="x_14b">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command
belaran@999 9623 requires that you correctly report the result of every test
belaran@999 9624 you perform. If you tell it that a test failed when it really
belaran@999 9625 succeeded, it <emphasis>might</emphasis> be able to detect the
belaran@999 9626 inconsistency. If it can identify an inconsistency in your
belaran@999 9627 reports, it will tell you that a particular changeset is both
belaran@999 9628 good and bad. However, it can't do this perfectly; it's about
belaran@999 9629 as likely to report the wrong changeset as the source of the
belaran@999 9630 bug.</para>
belaran@999 9631
belaran@999 9632 </sect2>
belaran@999 9633 <sect2>
belaran@999 9634 <title>Automate as much as possible</title>
belaran@999 9635
belaran@999 9636 <para id="x_14c">When I started using the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9637 bisect</command> command, I tried a few times to run my
belaran@999 9638 tests by hand, on the command line. This is an approach that
belaran@999 9639 I, at least, am not suited to. After a few tries, I found
belaran@999 9640 that I was making enough mistakes that I was having to restart
belaran@999 9641 my searches several times before finally getting correct
belaran@999 9642 results.</para>
belaran@999 9643
belaran@999 9644 <para id="x_14d">My initial problems with driving the <command role="hg-cmd" moreinfo="none">hg bisect</command> command by hand occurred
belaran@999 9645 even with simple searches on small repositories; if the
belaran@999 9646 problem you're looking for is more subtle, or the number of
belaran@999 9647 tests that <command role="hg-cmd" moreinfo="none">hg bisect</command> must
belaran@999 9648 perform increases, the likelihood of operator error ruining
belaran@999 9649 the search is much higher. Once I started automating my
belaran@999 9650 tests, I had much better results.</para>
belaran@999 9651
belaran@999 9652 <para id="x_14e">The key to automated testing is twofold:</para>
belaran@999 9653 <itemizedlist>
belaran@999 9654 <listitem><para id="x_14f">always test for the same symptom, and</para>
belaran@999 9655 </listitem>
belaran@999 9656 <listitem><para id="x_150">always feed consistent input to the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.</para>
belaran@999 9657 </listitem></itemizedlist>
belaran@999 9658 <para id="x_151">In my tutorial example above, the <command moreinfo="none">grep</command>
belaran@999 9659 command tests for the symptom, and the <literal moreinfo="none">if</literal>
belaran@999 9660 statement takes the result of this check and ensures that we
belaran@999 9661 always feed the same input to the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9662 bisect</command> command. The <literal moreinfo="none">mytest</literal>
belaran@999 9663 function marries these together in a reproducible way, so that
belaran@999 9664 every test is uniform and consistent.</para>
belaran@999 9665
belaran@999 9666 </sect2>
belaran@999 9667 <sect2>
belaran@999 9668 <title>Check your results</title>
belaran@999 9669
belaran@999 9670 <para id="x_152">Because the output of a <command role="hg-cmd" moreinfo="none">hg
belaran@999 9671 bisect</command> search is only as good as the input you
belaran@999 9672 give it, don't take the changeset it reports as the absolute
belaran@999 9673 truth. A simple way to cross-check its report is to manually
belaran@999 9674 run your test at each of the following changesets:</para>
belaran@999 9675 <itemizedlist>
belaran@999 9676 <listitem><para id="x_153">The changeset that it reports as the first bad
belaran@999 9677 revision. Your test should still report this as
belaran@999 9678 bad.</para>
belaran@999 9679 </listitem>
belaran@999 9680 <listitem><para id="x_154">The parent of that changeset (either parent,
belaran@999 9681 if it's a merge). Your test should report this changeset
belaran@999 9682 as good.</para>
belaran@999 9683 </listitem>
belaran@999 9684 <listitem><para id="x_155">A child of that changeset. Your test should
belaran@999 9685 report this changeset as bad.</para>
belaran@999 9686 </listitem></itemizedlist>
belaran@999 9687
belaran@999 9688 </sect2>
belaran@999 9689 <sect2>
belaran@999 9690 <title>Beware interference between bugs</title>
belaran@999 9691
belaran@999 9692 <para id="x_156">It's possible that your search for one bug could be
belaran@999 9693 disrupted by the presence of another. For example, let's say
belaran@999 9694 your software crashes at revision 100, and worked correctly at
belaran@999 9695 revision 50. Unknown to you, someone else introduced a
belaran@999 9696 different crashing bug at revision 60, and fixed it at
belaran@999 9697 revision 80. This could distort your results in one of
belaran@999 9698 several ways.</para>
belaran@999 9699
belaran@999 9700 <para id="x_157">It is possible that this other bug completely
belaran@999 9701 <quote>masks</quote> yours, which is to say that it occurs
belaran@999 9702 before your bug has a chance to manifest itself. If you can't
belaran@999 9703 avoid that other bug (for example, it prevents your project
belaran@999 9704 from building), and so can't tell whether your bug is present
belaran@999 9705 in a particular changeset, the <command role="hg-cmd" moreinfo="none">hg
belaran@999 9706 bisect</command> command cannot help you directly. Instead,
belaran@999 9707 you can mark a changeset as untested by running <command role="hg-cmd" moreinfo="none">hg bisect --skip</command>.</para>
belaran@999 9708
belaran@999 9709 <para id="x_158">A different problem could arise if your test for a bug's
belaran@999 9710 presence is not specific enough. If you check for <quote>my
belaran@999 9711 program crashes</quote>, then both your crashing bug and an
belaran@999 9712 unrelated crashing bug that masks it will look like the same
belaran@999 9713 thing, and mislead <command role="hg-cmd" moreinfo="none">hg
belaran@999 9714 bisect</command>.</para>
belaran@999 9715
belaran@999 9716 <para id="x_159">Another useful situation in which to use <command role="hg-cmd" moreinfo="none">hg bisect --skip</command> is if you can't
belaran@999 9717 test a revision because your project was in a broken and hence
belaran@999 9718 untestable state at that revision, perhaps because someone
belaran@999 9719 checked in a change that prevented the project from
belaran@999 9720 building.</para>
belaran@999 9721
belaran@999 9722 </sect2>
belaran@999 9723 <sect2>
belaran@999 9724 <title>Bracket your search lazily</title>
belaran@999 9725
belaran@999 9726 <para id="x_15a">Choosing the first <quote>good</quote> and
belaran@999 9727 <quote>bad</quote> changesets that will mark the end points of
belaran@999 9728 your search is often easy, but it bears a little discussion
belaran@999 9729 nevertheless. From the perspective of <command role="hg-cmd" moreinfo="none">hg bisect</command>, the <quote>newest</quote>
belaran@999 9730 changeset is conventionally <quote>bad</quote>, and the older
belaran@999 9731 changeset is <quote>good</quote>.</para>
belaran@999 9732
belaran@999 9733 <para id="x_15b">If you're having trouble remembering when a suitable
belaran@999 9734 <quote>good</quote> change was, so that you can tell <command role="hg-cmd" moreinfo="none">hg bisect</command>, you could do worse than
belaran@999 9735 testing changesets at random. Just remember to eliminate
belaran@999 9736 contenders that can't possibly exhibit the bug (perhaps
belaran@999 9737 because the feature with the bug isn't present yet) and those
belaran@999 9738 where another problem masks the bug (as I discussed
belaran@999 9739 above).</para>
belaran@999 9740
belaran@999 9741 <para id="x_15c">Even if you end up <quote>early</quote> by thousands of
belaran@999 9742 changesets or months of history, you will only add a handful
belaran@999 9743 of tests to the total number that <command role="hg-cmd" moreinfo="none">hg
belaran@999 9744 bisect</command> must perform, thanks to its logarithmic
belaran@999 9745 behavior.</para>
belaran@999 9746
belaran@999 9747 </sect2>
belaran@999 9748 </sect1>
belaran@999 9749 </chapter>
belaran@999 9750
belaran@999 9751 <!--
belaran@999 9752 local variables:
belaran@999 9753 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 9754 end:
belaran@999 9755 -->
belaran@999 9756
belaran@999 9757 <!-- BEGIN ch10 -->
belaran@999 9758 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 9759
belaran@999 9760 <chapter id="chap:hook">
belaran@999 9761 <?dbhtml filename="handling-repository-events-with-hooks.html"?>
belaran@999 9762 <title>Handling repository events with hooks</title>
belaran@999 9763
belaran@999 9764 <para id="x_1e6">Mercurial offers a powerful mechanism to let you perform
belaran@999 9765 automated actions in response to events that occur in a
belaran@999 9766 repository. In some cases, you can even control Mercurial's
belaran@999 9767 response to those events.</para>
belaran@999 9768
belaran@999 9769 <para id="x_1e7">The name Mercurial uses for one of these actions is a
belaran@999 9770 <emphasis>hook</emphasis>. Hooks are called
belaran@999 9771 <quote>triggers</quote> in some revision control systems, but the
belaran@999 9772 two names refer to the same idea.</para>
belaran@999 9773
belaran@999 9774 <sect1>
belaran@999 9775 <title>An overview of hooks in Mercurial</title>
belaran@999 9776
belaran@999 9777 <para id="x_1e8">Here is a brief list of the hooks that Mercurial
belaran@999 9778 supports. We will revisit each of these hooks in more detail
belaran@999 9779 later, in <xref linkend="sec:hook:ref"/>.</para>
belaran@999 9780
belaran@999 9781 <para id="x_1f6">Each of the hooks whose description begins with the word
belaran@999 9782 <quote>Controlling</quote> has the ability to determine whether
belaran@999 9783 an activity can proceed. If the hook succeeds, the activity may
belaran@999 9784 proceed; if it fails, the activity is either not permitted or
belaran@999 9785 undone, depending on the hook.</para>
belaran@999 9786
belaran@999 9787 <itemizedlist>
belaran@999 9788 <listitem><para id="x_1e9"><literal role="hook" moreinfo="none">changegroup</literal>: This
belaran@999 9789 is run after a group of changesets has been brought into the
belaran@999 9790 repository from elsewhere.</para>
belaran@999 9791 </listitem>
belaran@999 9792 <listitem><para id="x_1ea"><literal role="hook" moreinfo="none">commit</literal>: This is
belaran@999 9793 run after a new changeset has been created in the local
belaran@999 9794 repository.</para>
belaran@999 9795 </listitem>
belaran@999 9796 <listitem><para id="x_1eb"><literal role="hook" moreinfo="none">incoming</literal>: This is
belaran@999 9797 run once for each new changeset that is brought into the
belaran@999 9798 repository from elsewhere. Notice the difference from
belaran@999 9799 <literal role="hook" moreinfo="none">changegroup</literal>, which is run
belaran@999 9800 once per <emphasis>group</emphasis> of changesets brought
belaran@999 9801 in.</para>
belaran@999 9802 </listitem>
belaran@999 9803 <listitem><para id="x_1ec"><literal role="hook" moreinfo="none">outgoing</literal>: This is
belaran@999 9804 run after a group of changesets has been transmitted from
belaran@999 9805 this repository.</para>
belaran@999 9806 </listitem>
belaran@999 9807 <listitem><para id="x_1ed"><literal role="hook" moreinfo="none">prechangegroup</literal>:
belaran@999 9808 This is run before starting to bring a group of changesets
belaran@999 9809 into the repository.
belaran@999 9810 </para>
belaran@999 9811 </listitem>
belaran@999 9812 <listitem><para id="x_1ee"><literal role="hook" moreinfo="none">precommit</literal>:
belaran@999 9813 Controlling. This is run before starting a commit.
belaran@999 9814 </para>
belaran@999 9815 </listitem>
belaran@999 9816 <listitem><para id="x_1ef"><literal role="hook" moreinfo="none">preoutgoing</literal>:
belaran@999 9817 Controlling. This is run before starting to transmit a group
belaran@999 9818 of changesets from this repository.
belaran@999 9819 </para>
belaran@999 9820 </listitem>
belaran@999 9821 <listitem><para id="x_1f0"><literal role="hook" moreinfo="none">pretag</literal>:
belaran@999 9822 Controlling. This is run before creating a tag.
belaran@999 9823 </para>
belaran@999 9824 </listitem>
belaran@999 9825 <listitem><para id="x_1f1"><literal role="hook" moreinfo="none">pretxnchangegroup</literal>: Controlling. This
belaran@999 9826 is run after a group of changesets has been brought into the
belaran@999 9827 local repository from another, but before the transaction
belaran@999 9828 completes that will make the changes permanent in the
belaran@999 9829 repository.
belaran@999 9830 </para>
belaran@999 9831 </listitem>
belaran@999 9832 <listitem><para id="x_1f2"><literal role="hook" moreinfo="none">pretxncommit</literal>:
belaran@999 9833 Controlling. This is run after a new changeset has been
belaran@999 9834 created in the local repository, but before the transaction
belaran@999 9835 completes that will make it permanent.
belaran@999 9836 </para>
belaran@999 9837 </listitem>
belaran@999 9838 <listitem><para id="x_1f3"><literal role="hook" moreinfo="none">preupdate</literal>:
belaran@999 9839 Controlling. This is run before starting an update or merge
belaran@999 9840 of the working directory.
belaran@999 9841 </para>
belaran@999 9842 </listitem>
belaran@999 9843 <listitem><para id="x_1f4"><literal role="hook" moreinfo="none">tag</literal>: This is run
belaran@999 9844 after a tag is created.
belaran@999 9845 </para>
belaran@999 9846 </listitem>
belaran@999 9847 <listitem><para id="x_1f5"><literal role="hook" moreinfo="none">update</literal>: This is
belaran@999 9848 run after an update or merge of the working directory has
belaran@999 9849 finished.
belaran@999 9850 </para>
belaran@999 9851 </listitem></itemizedlist>
belaran@999 9852
belaran@999 9853 </sect1>
belaran@999 9854 <sect1>
belaran@999 9855 <title>Hooks and security</title>
belaran@999 9856
belaran@999 9857 <sect2>
belaran@999 9858 <title>Hooks are run with your privileges</title>
belaran@999 9859
belaran@999 9860 <para id="x_1f7">When you run a Mercurial command in a repository, and the
belaran@999 9861 command causes a hook to run, that hook runs on
belaran@999 9862 <emphasis>your</emphasis> system, under
belaran@999 9863 <emphasis>your</emphasis> user account, with
belaran@999 9864 <emphasis>your</emphasis> privilege level. Since hooks are
belaran@999 9865 arbitrary pieces of executable code, you should treat them
belaran@999 9866 with an appropriate level of suspicion. Do not install a hook
belaran@999 9867 unless you are confident that you know who created it and what
belaran@999 9868 it does.
belaran@999 9869 </para>
belaran@999 9870
belaran@999 9871 <para id="x_1f8">In some cases, you may be exposed to hooks that you did
belaran@999 9872 not install yourself. If you work with Mercurial on an
belaran@999 9873 unfamiliar system, Mercurial will run hooks defined in that
belaran@999 9874 system's global <filename role="special" moreinfo="none">~/.hgrc</filename>
belaran@999 9875 file.
belaran@999 9876 </para>
belaran@999 9877
belaran@999 9878 <para id="x_1f9">If you are working with a repository owned by another
belaran@999 9879 user, Mercurial can run hooks defined in that user's
belaran@999 9880 repository, but it will still run them as <quote>you</quote>.
belaran@999 9881 For example, if you <command role="hg-cmd" moreinfo="none">hg pull</command>
belaran@999 9882 from that repository, and its <filename role="special" moreinfo="none">.hg/hgrc</filename> defines a local <literal role="hook" moreinfo="none">outgoing</literal> hook, that hook will run
belaran@999 9883 under your user account, even though you don't own that
belaran@999 9884 repository.
belaran@999 9885 </para>
belaran@999 9886
belaran@999 9887 <note>
belaran@999 9888 <para id="x_1fa"> This only applies if you are pulling from a repository
belaran@999 9889 on a local or network filesystem. If you're pulling over
belaran@999 9890 http or ssh, any <literal role="hook" moreinfo="none">outgoing</literal>
belaran@999 9891 hook will run under whatever account is executing the server
belaran@999 9892 process, on the server.
belaran@999 9893 </para>
belaran@999 9894 </note>
belaran@999 9895
belaran@999 9896 <para id="x_1fb">To see what hooks are defined in a repository,
belaran@999 9897 use the <command role="hg-cmd" moreinfo="none">hg showconfig hooks</command>
belaran@999 9898 command. If you are working in one repository, but talking to
belaran@999 9899 another that you do not own (e.g. using <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg
belaran@999 9900 incoming</command>), remember that it is the other
belaran@999 9901 repository's hooks you should be checking, not your own.
belaran@999 9902 </para>
belaran@999 9903 </sect2>
belaran@999 9904
belaran@999 9905 <sect2>
belaran@999 9906 <title>Hooks do not propagate</title>
belaran@999 9907
belaran@999 9908 <para id="x_1fc">In Mercurial, hooks are not revision controlled, and do
belaran@999 9909 not propagate when you clone, or pull from, a repository. The
belaran@999 9910 reason for this is simple: a hook is a completely arbitrary
belaran@999 9911 piece of executable code. It runs under your user identity,
belaran@999 9912 with your privilege level, on your machine.
belaran@999 9913 </para>
belaran@999 9914
belaran@999 9915 <para id="x_1fd">It would be extremely reckless for any distributed
belaran@999 9916 revision control system to implement revision-controlled
belaran@999 9917 hooks, as this would offer an easily exploitable way to
belaran@999 9918 subvert the accounts of users of the revision control system.
belaran@999 9919 </para>
belaran@999 9920
belaran@999 9921 <para id="x_1fe">Since Mercurial does not propagate hooks, if you are
belaran@999 9922 collaborating with other people on a common project, you
belaran@999 9923 should not assume that they are using the same Mercurial hooks
belaran@999 9924 as you are, or that theirs are correctly configured. You
belaran@999 9925 should document the hooks you expect people to use.
belaran@999 9926 </para>
belaran@999 9927
belaran@999 9928 <para id="x_1ff">In a corporate intranet, this is somewhat easier to
belaran@999 9929 control, as you can for example provide a
belaran@999 9930 <quote>standard</quote> installation of Mercurial on an NFS
belaran@999 9931 filesystem, and use a site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file to define hooks that all users will
belaran@999 9932 see. However, this too has its limits; see below.
belaran@999 9933 </para>
belaran@999 9934 </sect2>
belaran@999 9935
belaran@999 9936 <sect2>
belaran@999 9937 <title>Hooks can be overridden</title>
belaran@999 9938
belaran@999 9939 <para id="x_200">Mercurial allows you to override a hook definition by
belaran@999 9940 redefining the hook. You can disable it by setting its value
belaran@999 9941 to the empty string, or change its behavior as you wish.
belaran@999 9942 </para>
belaran@999 9943
belaran@999 9944 <para id="x_201">If you deploy a system- or site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file that defines some
belaran@999 9945 hooks, you should thus understand that your users can disable
belaran@999 9946 or override those hooks.
belaran@999 9947 </para>
belaran@999 9948 </sect2>
belaran@999 9949
belaran@999 9950 <sect2>
belaran@999 9951 <title>Ensuring that critical hooks are run</title>
belaran@999 9952
belaran@999 9953 <para id="x_202">Sometimes you may want to enforce a policy that you do not
belaran@999 9954 want others to be able to work around. For example, you may
belaran@999 9955 have a requirement that every changeset must pass a rigorous
belaran@999 9956 set of tests. Defining this requirement via a hook in a
belaran@999 9957 site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> won't
belaran@999 9958 work for remote users on laptops, and of course local users
belaran@999 9959 can subvert it at will by overriding the hook.
belaran@999 9960 </para>
belaran@999 9961
belaran@999 9962 <para id="x_203">Instead, you can set up your policies for use of Mercurial
belaran@999 9963 so that people are expected to propagate changes through a
belaran@999 9964 well-known <quote>canonical</quote> server that you have
belaran@999 9965 locked down and configured appropriately.
belaran@999 9966 </para>
belaran@999 9967
belaran@999 9968 <para id="x_204">One way to do this is via a combination of social
belaran@999 9969 engineering and technology. Set up a restricted-access
belaran@999 9970 account; users can push changes over the network to
belaran@999 9971 repositories managed by this account, but they cannot log into
belaran@999 9972 the account and run normal shell commands. In this scenario,
belaran@999 9973 a user can commit a changeset that contains any old garbage
belaran@999 9974 they want.
belaran@999 9975 </para>
belaran@999 9976
belaran@999 9977 <para id="x_205">When someone pushes a changeset to the server that
belaran@999 9978 everyone pulls from, the server will test the changeset before
belaran@999 9979 it accepts it as permanent, and reject it if it fails to pass
belaran@999 9980 the test suite. If people only pull changes from this
belaran@999 9981 filtering server, it will serve to ensure that all changes
belaran@999 9982 that people pull have been automatically vetted.
belaran@999 9983 </para>
belaran@999 9984
belaran@999 9985 </sect2>
belaran@999 9986 </sect1>
belaran@999 9987
belaran@999 9988 <sect1 id="sec:hook:simple">
belaran@999 9989 <title>A short tutorial on using hooks</title>
belaran@999 9990
belaran@999 9991 <para id="x_212">It is easy to write a Mercurial hook. Let's start with a
belaran@999 9992 hook that runs when you finish a <command role="hg-cmd" moreinfo="none">hg
belaran@999 9993 commit</command>, and simply prints the hash of the changeset
belaran@999 9994 you just created. The hook is called <literal role="hook" moreinfo="none">commit</literal>.
belaran@999 9995 </para>
belaran@999 9996
belaran@999 9997 <para id="x_213">All hooks follow the pattern in this example.</para>
belaran@999 9998
belaran@999 9999 <!-- BEGIN hook.simple.init -->
belaran@999 10000 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hook-test</userinput>
belaran@999 10001 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hook-test</userinput>
belaran@999 10002 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '[hooks]' &gt;&gt; .hg/hgrc</userinput>
belaran@999 10003 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit = echo committed $HG_NODE' &gt;&gt; .hg/hgrc</userinput>
belaran@999 10004 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
belaran@999 10005 [hooks]
belaran@999 10006 commit = echo committed $HG_NODE
belaran@999 10007 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 10008 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
belaran@999 10009 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'testing commit hook'</userinput>
belaran@999 10010 committed 13a334d1e5ca83fea465aa779110eec3c5ddd6b1
belaran@999 10011 </screen>
belaran@999 10012 <!-- END hook.simple.init -->
belaran@999 10013
belaran@999 10014
belaran@999 10015 <para id="x_214">You add an entry to the <literal role="rc-hooks" moreinfo="none">hooks</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>. On the left is the name of
belaran@999 10016 the event to trigger on; on the right is the action to take. As
belaran@999 10017 you can see, you can run an arbitrary shell command in a hook.
belaran@999 10018 Mercurial passes extra information to the hook using environment
belaran@999 10019 variables (look for <envar>HG_NODE</envar> in the example).
belaran@999 10020 </para>
belaran@999 10021
belaran@999 10022 <sect2>
belaran@999 10023 <title>Performing multiple actions per event</title>
belaran@999 10024
belaran@999 10025 <para id="x_215">Quite often, you will want to define more than one hook
belaran@999 10026 for a particular kind of event, as shown below.</para>
belaran@999 10027
belaran@999 10028 <!-- BEGIN hook.simple.ext -->
belaran@999 10029 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit.when = echo -n "date of commit: "; date' &gt;&gt; .hg/hgrc</userinput>
belaran@999 10030 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt;&gt; a</userinput>
belaran@999 10031 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i have two hooks'</userinput>
belaran@999 10032 committed 3be6e2778fb853cbc7e5138d0b9c29386504670b
belaran@999 10033 date of commit: Sun Aug 16 14:05:05 GMT 2009
belaran@999 10034 </screen>
belaran@999 10035 <!-- END hook.simple.ext -->
belaran@999 10036
belaran@999 10037
belaran@999 10038 <para id="x_216">Mercurial lets you do this by adding an
belaran@999 10039 <emphasis>extension</emphasis> to the end of a hook's name.
belaran@999 10040 You extend a hook's name by giving the name of the hook,
belaran@999 10041 followed by a full stop (the
belaran@999 10042 <quote><literal moreinfo="none">.</literal></quote> character), followed by
belaran@999 10043 some more text of your choosing. For example, Mercurial will
belaran@999 10044 run both <literal moreinfo="none">commit.foo</literal> and
belaran@999 10045 <literal moreinfo="none">commit.bar</literal> when the
belaran@999 10046 <literal moreinfo="none">commit</literal> event occurs.
belaran@999 10047 </para>
belaran@999 10048
belaran@999 10049 <para id="x_217">To give a well-defined order of execution when there are
belaran@999 10050 multiple hooks defined for an event, Mercurial sorts hooks by
belaran@999 10051 extension, and executes the hook commands in this sorted
belaran@999 10052 order. In the above example, it will execute
belaran@999 10053 <literal moreinfo="none">commit.bar</literal> before
belaran@999 10054 <literal moreinfo="none">commit.foo</literal>, and <literal moreinfo="none">commit</literal>
belaran@999 10055 before both.
belaran@999 10056 </para>
belaran@999 10057
belaran@999 10058 <para id="x_218">It is a good idea to use a somewhat descriptive
belaran@999 10059 extension when you define a new hook. This will help you to
belaran@999 10060 remember what the hook was for. If the hook fails, you'll get
belaran@999 10061 an error message that contains the hook name and extension, so
belaran@999 10062 using a descriptive extension could give you an immediate hint
belaran@999 10063 as to why the hook failed (see <xref linkend="sec:hook:perm"/> for an example).
belaran@999 10064 </para>
belaran@999 10065
belaran@999 10066 </sect2>
belaran@999 10067 <sect2 id="sec:hook:perm">
belaran@999 10068 <title>Controlling whether an activity can proceed</title>
belaran@999 10069
belaran@999 10070 <para id="x_219">In our earlier examples, we used the <literal role="hook" moreinfo="none">commit</literal> hook, which is run after a
belaran@999 10071 commit has completed. This is one of several Mercurial hooks
belaran@999 10072 that run after an activity finishes. Such hooks have no way
belaran@999 10073 of influencing the activity itself.
belaran@999 10074 </para>
belaran@999 10075
belaran@999 10076 <para id="x_21a">Mercurial defines a number of events that occur before an
belaran@999 10077 activity starts; or after it starts, but before it finishes.
belaran@999 10078 Hooks that trigger on these events have the added ability to
belaran@999 10079 choose whether the activity can continue, or will abort.
belaran@999 10080 </para>
belaran@999 10081
belaran@999 10082 <para id="x_21b">The <literal role="hook" moreinfo="none">pretxncommit</literal> hook runs
belaran@999 10083 after a commit has all but completed. In other words, the
belaran@999 10084 metadata representing the changeset has been written out to
belaran@999 10085 disk, but the transaction has not yet been allowed to
belaran@999 10086 complete. The <literal role="hook" moreinfo="none">pretxncommit</literal>
belaran@999 10087 hook has the ability to decide whether the transaction can
belaran@999 10088 complete, or must be rolled back.
belaran@999 10089 </para>
belaran@999 10090
belaran@999 10091 <para id="x_21c">If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook
belaran@999 10092 exits with a status code of zero, the transaction is allowed
belaran@999 10093 to complete; the commit finishes; and the <literal role="hook" moreinfo="none">commit</literal> hook is run. If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook exits with a
belaran@999 10094 non-zero status code, the transaction is rolled back; the
belaran@999 10095 metadata representing the changeset is erased; and the
belaran@999 10096 <literal role="hook" moreinfo="none">commit</literal> hook is not run.
belaran@999 10097 </para>
belaran@999 10098
belaran@999 10099 <!-- BEGIN hook.simple.pretxncommit -->
belaran@999 10100 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat check_bug_id</userinput>
belaran@999 10101 #!/bin/sh
belaran@999 10102 # check that a commit comment mentions a numeric bug id
belaran@999 10103 hg log -r $1 --template {desc} | grep -q "\&lt;bug *[0-9]"
belaran@999 10104 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' &gt;&gt; .hg/hgrc</userinput>
belaran@999 10105 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt;&gt; a</userinput>
belaran@999 10106 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i am not mentioning a bug id'</userinput>
belaran@999 10107 transaction abort!
belaran@999 10108 rollback completed
belaran@999 10109 abort: pretxncommit.bug_id_required hook exited with status 1
belaran@999 10110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i refer you to bug 666'</userinput>
belaran@999 10111 committed 1a52be73a1ca4fa05e269f99003ed00912e8e836
belaran@999 10112 date of commit: Sun Aug 16 14:05:05 GMT 2009
belaran@999 10113 </screen>
belaran@999 10114 <!-- END hook.simple.pretxncommit -->
belaran@999 10115
belaran@999 10116
belaran@999 10117 <para id="x_21d">The hook in the example above checks that a commit comment
belaran@999 10118 contains a bug ID. If it does, the commit can complete. If
belaran@999 10119 not, the commit is rolled back.
belaran@999 10120 </para>
belaran@999 10121
belaran@999 10122 </sect2>
belaran@999 10123 </sect1>
belaran@999 10124 <sect1>
belaran@999 10125 <title>Writing your own hooks</title>
belaran@999 10126
belaran@999 10127 <para id="x_21e">When you are writing a hook, you might find it useful to run
belaran@999 10128 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
belaran@999 10129 <quote>true</quote>. When you do so, Mercurial will print a
belaran@999 10130 message before it calls each hook.
belaran@999 10131 </para>
belaran@999 10132
belaran@999 10133 <sect2 id="sec:hook:lang">
belaran@999 10134 <title>Choosing how your hook should run</title>
belaran@999 10135
belaran@999 10136 <para id="x_21f">You can write a hook either as a normal
belaran@999 10137 program—typically a shell script—or as a Python
belaran@999 10138 function that is executed within the Mercurial process.
belaran@999 10139 </para>
belaran@999 10140
belaran@999 10141 <para id="x_220">Writing a hook as an external program has the advantage
belaran@999 10142 that it requires no knowledge of Mercurial's internals. You
belaran@999 10143 can call normal Mercurial commands to get any added
belaran@999 10144 information you need. The trade-off is that external hooks
belaran@999 10145 are slower than in-process hooks.
belaran@999 10146 </para>
belaran@999 10147
belaran@999 10148 <para id="x_221">An in-process Python hook has complete access to the
belaran@999 10149 Mercurial API, and does not <quote>shell out</quote> to
belaran@999 10150 another process, so it is inherently faster than an external
belaran@999 10151 hook. It is also easier to obtain much of the information
belaran@999 10152 that a hook requires by using the Mercurial API than by
belaran@999 10153 running Mercurial commands.
belaran@999 10154 </para>
belaran@999 10155
belaran@999 10156 <para id="x_222">If you are comfortable with Python, or require high
belaran@999 10157 performance, writing your hooks in Python may be a good
belaran@999 10158 choice. However, when you have a straightforward hook to
belaran@999 10159 write and you don't need to care about performance (probably
belaran@999 10160 the majority of hooks), a shell script is perfectly fine.
belaran@999 10161 </para>
belaran@999 10162
belaran@999 10163 </sect2>
belaran@999 10164 <sect2 id="sec:hook:param">
belaran@999 10165 <title>Hook parameters</title>
belaran@999 10166
belaran@999 10167 <para id="x_223">Mercurial calls each hook with a set of well-defined
belaran@999 10168 parameters. In Python, a parameter is passed as a keyword
belaran@999 10169 argument to your hook function. For an external program, a
belaran@999 10170 parameter is passed as an environment variable.
belaran@999 10171 </para>
belaran@999 10172
belaran@999 10173 <para id="x_224">Whether your hook is written in Python or as a shell
belaran@999 10174 script, the hook-specific parameter names and values will be
belaran@999 10175 the same. A boolean parameter will be represented as a
belaran@999 10176 boolean value in Python, but as the number 1 (for
belaran@999 10177 <quote>true</quote>) or 0 (for <quote>false</quote>) as an
belaran@999 10178 environment variable for an external hook. If a hook
belaran@999 10179 parameter is named <literal moreinfo="none">foo</literal>, the keyword
belaran@999 10180 argument for a Python hook will also be named
belaran@999 10181 <literal moreinfo="none">foo</literal>, while the environment variable for an
belaran@999 10182 external hook will be named <literal moreinfo="none">HG_FOO</literal>.
belaran@999 10183 </para>
belaran@999 10184 </sect2>
belaran@999 10185
belaran@999 10186 <sect2>
belaran@999 10187 <title>Hook return values and activity control</title>
belaran@999 10188
belaran@999 10189 <para id="x_225">A hook that executes successfully must exit with a status
belaran@999 10190 of zero if external, or return boolean <quote>false</quote> if
belaran@999 10191 in-process. Failure is indicated with a non-zero exit status
belaran@999 10192 from an external hook, or an in-process hook returning boolean
belaran@999 10193 <quote>true</quote>. If an in-process hook raises an
belaran@999 10194 exception, the hook is considered to have failed.
belaran@999 10195 </para>
belaran@999 10196
belaran@999 10197 <para id="x_226">For a hook that controls whether an activity can proceed,
belaran@999 10198 zero/false means <quote>allow</quote>, while
belaran@999 10199 non-zero/true/exception means <quote>deny</quote>.
belaran@999 10200 </para>
belaran@999 10201 </sect2>
belaran@999 10202
belaran@999 10203 <sect2>
belaran@999 10204 <title>Writing an external hook</title>
belaran@999 10205
belaran@999 10206 <para id="x_227">When you define an external hook in your <filename role="special" moreinfo="none">~/.hgrc</filename> and the hook is run, its
belaran@999 10207 value is passed to your shell, which interprets it. This
belaran@999 10208 means that you can use normal shell constructs in the body of
belaran@999 10209 the hook.
belaran@999 10210 </para>
belaran@999 10211
belaran@999 10212 <para id="x_228">An executable hook is always run with its current
belaran@999 10213 directory set to a repository's root directory.
belaran@999 10214 </para>
belaran@999 10215
belaran@999 10216 <para id="x_229">Each hook parameter is passed in as an environment
belaran@999 10217 variable; the name is upper-cased, and prefixed with the
belaran@999 10218 string <quote><literal moreinfo="none">HG_</literal></quote>.
belaran@999 10219 </para>
belaran@999 10220
belaran@999 10221 <para id="x_22a">With the exception of hook parameters, Mercurial does not
belaran@999 10222 set or modify any environment variables when running a hook.
belaran@999 10223 This is useful to remember if you are writing a site-wide hook
belaran@999 10224 that may be run by a number of different users with differing
belaran@999 10225 environment variables set. In multi-user situations, you
belaran@999 10226 should not rely on environment variables being set to the
belaran@999 10227 values you have in your environment when testing the hook.
belaran@999 10228 </para>
belaran@999 10229 </sect2>
belaran@999 10230
belaran@999 10231 <sect2>
belaran@999 10232 <title>Telling Mercurial to use an in-process hook</title>
belaran@999 10233
belaran@999 10234 <para id="x_22b">The <filename role="special" moreinfo="none">~/.hgrc</filename> syntax
belaran@999 10235 for defining an in-process hook is slightly different than for
belaran@999 10236 an executable hook. The value of the hook must start with the
belaran@999 10237 text <quote><literal moreinfo="none">python:</literal></quote>, and continue
belaran@999 10238 with the fully-qualified name of a callable object to use as
belaran@999 10239 the hook's value.
belaran@999 10240 </para>
belaran@999 10241
belaran@999 10242 <para id="x_22c">The module in which a hook lives is automatically imported
belaran@999 10243 when a hook is run. So long as you have the module name and
belaran@999 10244 <envar>PYTHONPATH</envar> right, it should <quote>just
belaran@999 10245 work</quote>.
belaran@999 10246 </para>
belaran@999 10247
belaran@999 10248 <para id="x_22d">The following <filename role="special" moreinfo="none">~/.hgrc</filename>
belaran@999 10249 example snippet illustrates the syntax and meaning of the
belaran@999 10250 notions we just described.
belaran@999 10251 </para>
belaran@999 10252 <programlisting format="linespecific">[hooks]
belaran@999 10253 commit.example = python:mymodule.submodule.myhook</programlisting>
belaran@999 10254 <para id="x_22e">When Mercurial runs the <literal moreinfo="none">commit.example</literal>
belaran@999 10255 hook, it imports <literal moreinfo="none">mymodule.submodule</literal>, looks
belaran@999 10256 for the callable object named <literal moreinfo="none">myhook</literal>, and
belaran@999 10257 calls it.
belaran@999 10258 </para>
belaran@999 10259 </sect2>
belaran@999 10260
belaran@999 10261 <sect2>
belaran@999 10262 <title>Writing an in-process hook</title>
belaran@999 10263
belaran@999 10264 <para id="x_22f">The simplest in-process hook does nothing, but illustrates
belaran@999 10265 the basic shape of the hook API:
belaran@999 10266 </para>
belaran@999 10267 <programlisting format="linespecific">def myhook(ui, repo, **kwargs):
belaran@999 10268 pass</programlisting>
belaran@999 10269 <para id="x_230">The first argument to a Python hook is always a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object. The second
belaran@999 10270 is a repository object; at the moment, it is always an
belaran@999 10271 instance of <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>.
belaran@999 10272 Following these two arguments are other keyword arguments.
belaran@999 10273 Which ones are passed in depends on the hook being called, but
belaran@999 10274 a hook can ignore arguments it doesn't care about by dropping
belaran@999 10275 them into a keyword argument dict, as with
belaran@999 10276 <literal moreinfo="none">**kwargs</literal> above.
belaran@999 10277 </para>
belaran@999 10278
belaran@999 10279 </sect2>
belaran@999 10280 </sect1>
belaran@999 10281 <sect1>
belaran@999 10282 <title>Some hook examples</title>
belaran@999 10283
belaran@999 10284 <sect2>
belaran@999 10285 <title>Writing meaningful commit messages</title>
belaran@999 10286
belaran@999 10287 <para id="x_231">It's hard to imagine a useful commit message being very
belaran@999 10288 short. The simple <literal role="hook" moreinfo="none">pretxncommit</literal>
belaran@999 10289 hook of the example below will prevent you from committing a
belaran@999 10290 changeset with a message that is less than ten bytes long.
belaran@999 10291 </para>
belaran@999 10292
belaran@999 10293 <!-- BEGIN hook.msglen.go -->
belaran@999 10294 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
belaran@999 10295 [hooks]
belaran@999 10296 pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10
belaran@999 10297 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 10298 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
belaran@999 10299 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'too short'</userinput>
belaran@999 10300 transaction abort!
belaran@999 10301 rollback completed
belaran@999 10302 abort: pretxncommit.msglen hook exited with status 1
belaran@999 10303 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'long enough'</userinput>
belaran@999 10304 </screen>
belaran@999 10305 <!-- END hook.msglen.go -->
belaran@999 10306
belaran@999 10307 </sect2>
belaran@999 10308
belaran@999 10309 <sect2>
belaran@999 10310 <title>Checking for trailing whitespace</title>
belaran@999 10311
belaran@999 10312 <para id="x_232">An interesting use of a commit-related hook is to help you
belaran@999 10313 to write cleaner code. A simple example of <quote>cleaner
belaran@999 10314 code</quote> is the dictum that a change should not add any
belaran@999 10315 new lines of text that contain <quote>trailing
belaran@999 10316 whitespace</quote>. Trailing whitespace is a series of
belaran@999 10317 space and tab characters at the end of a line of text. In
belaran@999 10318 most cases, trailing whitespace is unnecessary, invisible
belaran@999 10319 noise, but it is occasionally problematic, and people often
belaran@999 10320 prefer to get rid of it.
belaran@999 10321 </para>
belaran@999 10322
belaran@999 10323 <para id="x_233">You can use either the <literal role="hook" moreinfo="none">precommit</literal> or <literal role="hook" moreinfo="none">pretxncommit</literal> hook to tell whether you
belaran@999 10324 have a trailing whitespace problem. If you use the <literal role="hook" moreinfo="none">precommit</literal> hook, the hook will not know
belaran@999 10325 which files you are committing, so it will have to check every
belaran@999 10326 modified file in the repository for trailing white space. If
belaran@999 10327 you want to commit a change to just the file
belaran@999 10328 <filename moreinfo="none">foo</filename>, but the file
belaran@999 10329 <filename moreinfo="none">bar</filename> contains trailing whitespace, doing a
belaran@999 10330 check in the <literal role="hook" moreinfo="none">precommit</literal> hook
belaran@999 10331 will prevent you from committing <filename moreinfo="none">foo</filename> due
belaran@999 10332 to the problem with <filename moreinfo="none">bar</filename>. This doesn't
belaran@999 10333 seem right.
belaran@999 10334 </para>
belaran@999 10335
belaran@999 10336 <para id="x_234">Should you choose the <literal role="hook" moreinfo="none">pretxncommit</literal> hook, the check won't
belaran@999 10337 occur until just before the transaction for the commit
belaran@999 10338 completes. This will allow you to check for problems only the
belaran@999 10339 exact files that are being committed. However, if you entered
belaran@999 10340 the commit message interactively and the hook fails, the
belaran@999 10341 transaction will roll back; you'll have to re-enter the commit
belaran@999 10342 message after you fix the trailing whitespace and run <command role="hg-cmd" moreinfo="none">hg commit</command> again.
belaran@999 10343 </para>
belaran@999 10344
belaran@999 10345 <!-- BEGIN ch09/hook.ws.simple -->
belaran@999 10346 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
belaran@999 10347 [hooks]
belaran@999 10348 pretxncommit.whitespace = hg export tip | (! egrep -q '^\+.*[ \t]$')
belaran@999 10349 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' &gt; a</userinput>
belaran@999 10350 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'test with trailing whitespace'</userinput>
belaran@999 10351 adding a
belaran@999 10352 transaction abort!
belaran@999 10353 rollback completed
belaran@999 10354 abort: pretxncommit.whitespace hook exited with status 1
belaran@999 10355 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a' &gt; a</userinput>
belaran@999 10356 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'drop trailing whitespace and try again'</userinput>
belaran@999 10357 </screen>
belaran@999 10358 <!-- END ch09/hook.ws.simple -->
belaran@999 10359
belaran@999 10360
belaran@999 10361 <para id="x_235">In this example, we introduce a simple <literal role="hook" moreinfo="none">pretxncommit</literal> hook that checks for
belaran@999 10362 trailing whitespace. This hook is short, but not very
belaran@999 10363 helpful. It exits with an error status if a change adds a
belaran@999 10364 line with trailing whitespace to any file, but does not print
belaran@999 10365 any information that might help us to identify the offending
belaran@999 10366 file or line. It also has the nice property of not paying
belaran@999 10367 attention to unmodified lines; only lines that introduce new
belaran@999 10368 trailing whitespace cause problems.
belaran@999 10369 </para>
belaran@999 10370
belaran@999 10371 <!-- BEGIN ch09/check_whitespace.py.lst -->
belaran@999 10372 <programlisting format="linespecific">#!/usr/bin/env python
belaran@999 10373 #
belaran@999 10374 # save as .hg/check_whitespace.py and make executable
belaran@999 10375
belaran@999 10376 import re
belaran@999 10377
belaran@999 10378 def trailing_whitespace(difflines):
belaran@999 10379 #
belaran@999 10380 linenum, header = 0, False
belaran@999 10381
belaran@999 10382 for line in difflines:
belaran@999 10383 if header:
belaran@999 10384 # remember the name of the file that this diff affects
belaran@999 10385 m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line)
belaran@999 10386 if m and m.group(1) != '/dev/null':
belaran@999 10387 filename = m.group(1).split('/', 1)[-1]
belaran@999 10388 if line.startswith('+++ '):
belaran@999 10389 header = False
belaran@999 10390 continue
belaran@999 10391 if line.startswith('diff '):
belaran@999 10392 header = True
belaran@999 10393 continue
belaran@999 10394 # hunk header - save the line number
belaran@999 10395 m = re.match(r'@@ -\d+,\d+ \+(\d+),', line)
belaran@999 10396 if m:
belaran@999 10397 linenum = int(m.group(1))
belaran@999 10398 continue
belaran@999 10399 # hunk body - check for an added line with trailing whitespace
belaran@999 10400 m = re.match(r'\+.*\s$', line)
belaran@999 10401 if m:
belaran@999 10402 yield filename, linenum
belaran@999 10403 if line and line[0] in ' +':
belaran@999 10404 linenum += 1
belaran@999 10405
belaran@999 10406 if __name__ == '__main__':
belaran@999 10407 import os, sys
belaran@999 10408
belaran@999 10409 added = 0
belaran@999 10410 for filename, linenum in trailing_whitespace(os.popen('hg export tip')):
belaran@999 10411 print &gt;&gt; sys.stderr, ('%s, line %d: trailing whitespace added' %
belaran@999 10412 (filename, linenum))
belaran@999 10413 added += 1
belaran@999 10414 if added:
belaran@999 10415 # save the commit message so we don't need to retype it
belaran@999 10416 os.system('hg tip --template "{desc}" &gt; .hg/commit.save')
belaran@999 10417 print &gt;&gt; sys.stderr, 'commit message saved to .hg/commit.save'
belaran@999 10418 sys.exit(1)</programlisting>
belaran@999 10419 <!-- END ch09/check_whitespace.py.lst -->
belaran@999 10420
belaran@999 10421
belaran@999 10422 <para id="x_236">The above version is much more complex, but also more
belaran@999 10423 useful. It parses a unified diff to see if any lines add
belaran@999 10424 trailing whitespace, and prints the name of the file and the
belaran@999 10425 line number of each such occurrence. Even better, if the
belaran@999 10426 change adds trailing whitespace, this hook saves the commit
belaran@999 10427 comment and prints the name of the save file before exiting
belaran@999 10428 and telling Mercurial to roll the transaction back, so you can
belaran@999 10429 use the <option role="hg-opt-commit">-l filename</option>
belaran@999 10430 option to <command role="hg-cmd" moreinfo="none">hg commit</command> to reuse
belaran@999 10431 the saved commit message once you've corrected the problem.
belaran@999 10432 </para>
belaran@999 10433
belaran@999 10434 <!-- BEGIN ch09/hook.ws.better -->
belaran@999 10435 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
belaran@999 10436 [hooks]
belaran@999 10437 pretxncommit.whitespace = .hg/check_whitespace.py
belaran@999 10438 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' &gt;&gt; a</userinput>
belaran@999 10439 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'add new line with trailing whitespace'</userinput>
belaran@999 10440 a, line 2: trailing whitespace added
belaran@999 10441 commit message saved to .hg/commit.save
belaran@999 10442 transaction abort!
belaran@999 10443 rollback completed
belaran@999 10444 abort: pretxncommit.whitespace hook exited with status 1
belaran@999 10445 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">sed -i 's, *$,,' a</userinput>
belaran@999 10446 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'trimmed trailing whitespace'</userinput>
belaran@999 10447 a, line 2: trailing whitespace added
belaran@999 10448 commit message saved to .hg/commit.save
belaran@999 10449 transaction abort!
belaran@999 10450 rollback completed
belaran@999 10451 abort: pretxncommit.whitespace hook exited with status 1
belaran@999 10452 </screen>
belaran@999 10453 <!-- END ch09/hook.ws.better -->
belaran@999 10454
belaran@999 10455
belaran@999 10456 <para id="x_237">As a final aside, note in the example above the
belaran@999 10457 use of <command moreinfo="none">sed</command>'s in-place editing feature to
belaran@999 10458 get rid of trailing whitespace from a file. This is concise
belaran@999 10459 and useful enough that I will reproduce it here (using
belaran@999 10460 <command moreinfo="none">perl</command> for good measure).</para>
belaran@999 10461 <programlisting format="linespecific">perl -pi -e 's,\s+$,,' filename</programlisting>
belaran@999 10462
belaran@999 10463 </sect2>
belaran@999 10464 </sect1>
belaran@999 10465 <sect1>
belaran@999 10466 <title>Bundled hooks</title>
belaran@999 10467
belaran@999 10468 <para id="x_238">Mercurial ships with several bundled hooks. You can find
belaran@999 10469 them in the <filename class="directory" moreinfo="none">hgext</filename>
belaran@999 10470 directory of a Mercurial source tree. If you are using a
belaran@999 10471 Mercurial binary package, the hooks will be located in the
belaran@999 10472 <filename class="directory" moreinfo="none">hgext</filename> directory of
belaran@999 10473 wherever your package installer put Mercurial.
belaran@999 10474 </para>
belaran@999 10475
belaran@999 10476 <sect2>
belaran@999 10477 <title><literal role="hg-ext" moreinfo="none">acl</literal>—access
belaran@999 10478 control for parts of a repository</title>
belaran@999 10479
belaran@999 10480 <para id="x_239">The <literal role="hg-ext" moreinfo="none">acl</literal> extension lets
belaran@999 10481 you control which remote users are allowed to push changesets
belaran@999 10482 to a networked server. You can protect any portion of a
belaran@999 10483 repository (including the entire repo), so that a specific
belaran@999 10484 remote user can push changes that do not affect the protected
belaran@999 10485 portion.
belaran@999 10486 </para>
belaran@999 10487
belaran@999 10488 <para id="x_23a">This extension implements access control based on the
belaran@999 10489 identity of the user performing a push,
belaran@999 10490 <emphasis>not</emphasis> on who committed the changesets
belaran@999 10491 they're pushing. It makes sense to use this hook only if you
belaran@999 10492 have a locked-down server environment that authenticates
belaran@999 10493 remote users, and you want to be sure that only specific users
belaran@999 10494 are allowed to push changes to that server.
belaran@999 10495 </para>
belaran@999 10496
belaran@999 10497 <sect3>
belaran@999 10498 <title>Configuring the <literal role="hook" moreinfo="none">acl</literal>
belaran@999 10499 hook</title>
belaran@999 10500
belaran@999 10501 <para id="x_23b">In order to manage incoming changesets, the <literal role="hg-ext" moreinfo="none">acl</literal> hook must be used as a
belaran@999 10502 <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook. This
belaran@999 10503 lets it see which files are modified by each incoming
belaran@999 10504 changeset, and roll back a group of changesets if they
belaran@999 10505 modify <quote>forbidden</quote> files. Example:
belaran@999 10506 </para>
belaran@999 10507 <programlisting format="linespecific">[hooks]
belaran@999 10508 pretxnchangegroup.acl = python:hgext.acl.hook</programlisting>
belaran@999 10509
belaran@999 10510 <para id="x_23c">The <literal role="hg-ext" moreinfo="none">acl</literal> extension is
belaran@999 10511 configured using three sections.
belaran@999 10512 </para>
belaran@999 10513
belaran@999 10514 <para id="x_23d">The <literal role="rc-acl" moreinfo="none">acl</literal> section has
belaran@999 10515 only one entry, <envar role="rc-item-acl">sources</envar>,
belaran@999 10516 which lists the sources of incoming changesets that the hook
belaran@999 10517 should pay attention to. You don't normally need to
belaran@999 10518 configure this section.
belaran@999 10519 </para>
belaran@999 10520 <itemizedlist>
belaran@999 10521 <listitem><para id="x_23e"><envar role="rc-item-acl">serve</envar>:
belaran@999 10522 Control incoming changesets that are arriving from a
belaran@999 10523 remote repository over http or ssh. This is the default
belaran@999 10524 value of <envar role="rc-item-acl">sources</envar>, and
belaran@999 10525 usually the only setting you'll need for this
belaran@999 10526 configuration item.
belaran@999 10527 </para>
belaran@999 10528 </listitem>
belaran@999 10529 <listitem><para id="x_23f"><envar role="rc-item-acl">pull</envar>:
belaran@999 10530 Control incoming changesets that are arriving via a pull
belaran@999 10531 from a local repository.
belaran@999 10532 </para>
belaran@999 10533 </listitem>
belaran@999 10534 <listitem><para id="x_240"><envar role="rc-item-acl">push</envar>:
belaran@999 10535 Control incoming changesets that are arriving via a push
belaran@999 10536 from a local repository.
belaran@999 10537 </para>
belaran@999 10538 </listitem>
belaran@999 10539 <listitem><para id="x_241"><envar role="rc-item-acl">bundle</envar>:
belaran@999 10540 Control incoming changesets that are arriving from
belaran@999 10541 another repository via a bundle.
belaran@999 10542 </para>
belaran@999 10543 </listitem></itemizedlist>
belaran@999 10544
belaran@999 10545 <para id="x_242">The <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal>
belaran@999 10546 section controls the users that are allowed to add
belaran@999 10547 changesets to the repository. If this section is not
belaran@999 10548 present, all users that are not explicitly denied are
belaran@999 10549 allowed. If this section is present, all users that are not
belaran@999 10550 explicitly allowed are denied (so an empty section means
belaran@999 10551 that all users are denied).
belaran@999 10552 </para>
belaran@999 10553
belaran@999 10554 <para id="x_243">The <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal>
belaran@999 10555 section determines which users are denied from adding
belaran@999 10556 changesets to the repository. If this section is not
belaran@999 10557 present or is empty, no users are denied.
belaran@999 10558 </para>
belaran@999 10559
belaran@999 10560 <para id="x_244">The syntaxes for the <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal> and <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal> sections are
belaran@999 10561 identical. On the left of each entry is a glob pattern that
belaran@999 10562 matches files or directories, relative to the root of the
belaran@999 10563 repository; on the right, a user name.
belaran@999 10564 </para>
belaran@999 10565
belaran@999 10566 <para id="x_245">In the following example, the user
belaran@999 10567 <literal moreinfo="none">docwriter</literal> can only push changes to the
belaran@999 10568 <filename class="directory" moreinfo="none">docs</filename> subtree of the
belaran@999 10569 repository, while <literal moreinfo="none">intern</literal> can push changes
belaran@999 10570 to any file or directory except <filename class="directory" moreinfo="none">source/sensitive</filename>.
belaran@999 10571 </para>
belaran@999 10572 <programlisting format="linespecific">[acl.allow]
belaran@999 10573 docs/** = docwriter
belaran@999 10574 [acl.deny]
belaran@999 10575 source/sensitive/** = intern</programlisting>
belaran@999 10576
belaran@999 10577 </sect3>
belaran@999 10578 <sect3>
belaran@999 10579 <title>Testing and troubleshooting</title>
belaran@999 10580
belaran@999 10581 <para id="x_246">If you want to test the <literal role="hg-ext" moreinfo="none">acl</literal> hook, run it with Mercurial's
belaran@999 10582 debugging output enabled. Since you'll probably be running
belaran@999 10583 it on a server where it's not convenient (or sometimes
belaran@999 10584 possible) to pass in the <option role="hg-opt-global">--debug</option> option, don't forget
belaran@999 10585 that you can enable debugging output in your <filename role="special" moreinfo="none">~/.hgrc</filename>:
belaran@999 10586 </para>
belaran@999 10587 <programlisting format="linespecific">[ui]
belaran@999 10588 debug = true</programlisting>
belaran@999 10589 <para id="x_247">With this enabled, the <literal role="hg-ext" moreinfo="none">acl</literal> hook will print enough
belaran@999 10590 information to let you figure out why it is allowing or
belaran@999 10591 forbidding pushes from specific users.
belaran@999 10592 </para>
belaran@999 10593
belaran@999 10594 </sect3> </sect2>
belaran@999 10595
belaran@999 10596 <sect2>
belaran@999 10597 <title><literal role="hg-ext" moreinfo="none">bugzilla</literal>—integration with
belaran@999 10598 Bugzilla</title>
belaran@999 10599
belaran@999 10600 <para id="x_248">The <literal role="hg-ext" moreinfo="none">bugzilla</literal> extension
belaran@999 10601 adds a comment to a Bugzilla bug whenever it finds a reference
belaran@999 10602 to that bug ID in a commit comment. You can install this hook
belaran@999 10603 on a shared server, so that any time a remote user pushes
belaran@999 10604 changes to this server, the hook gets run.
belaran@999 10605 </para>
belaran@999 10606
belaran@999 10607 <para id="x_249">It adds a comment to the bug that looks like this (you can
belaran@999 10608 configure the contents of the comment—see below):
belaran@999 10609 </para>
belaran@999 10610 <programlisting format="linespecific">Changeset aad8b264143a, made by Joe User
belaran@999 10611 &lt;joe.user@domain.com&gt; in the frobnitz repository, refers
belaran@999 10612 to this bug. For complete details, see
belaran@999 10613 http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
belaran@999 10614 Changeset description: Fix bug 10483 by guarding against some
belaran@999 10615 NULL pointers</programlisting>
belaran@999 10616 <para id="x_24a">The value of this hook is that it automates the process of
belaran@999 10617 updating a bug any time a changeset refers to it. If you
belaran@999 10618 configure the hook properly, it makes it easy for people to
belaran@999 10619 browse straight from a Bugzilla bug to a changeset that refers
belaran@999 10620 to that bug.
belaran@999 10621 </para>
belaran@999 10622
belaran@999 10623 <para id="x_24b">You can use the code in this hook as a starting point for
belaran@999 10624 some more exotic Bugzilla integration recipes. Here are a few
belaran@999 10625 possibilities:
belaran@999 10626 </para>
belaran@999 10627 <itemizedlist>
belaran@999 10628 <listitem><para id="x_24c">Require that every changeset pushed to the
belaran@999 10629 server have a valid bug ID in its commit comment. In this
belaran@999 10630 case, you'd want to configure the hook as a <literal role="hook" moreinfo="none">pretxncommit</literal> hook. This would
belaran@999 10631 allow the hook to reject changes that didn't contain bug
belaran@999 10632 IDs.
belaran@999 10633 </para>
belaran@999 10634 </listitem>
belaran@999 10635 <listitem><para id="x_24d">Allow incoming changesets to automatically
belaran@999 10636 modify the <emphasis>state</emphasis> of a bug, as well as
belaran@999 10637 simply adding a comment. For example, the hook could
belaran@999 10638 recognise the string <quote>fixed bug 31337</quote> as
belaran@999 10639 indicating that it should update the state of bug 31337 to
belaran@999 10640 <quote>requires testing</quote>.
belaran@999 10641 </para>
belaran@999 10642 </listitem></itemizedlist>
belaran@999 10643
belaran@999 10644 <sect3 id="sec:hook:bugzilla:config">
belaran@999 10645 <title>Configuring the <literal role="hook" moreinfo="none">bugzilla</literal>
belaran@999 10646 hook</title>
belaran@999 10647
belaran@999 10648 <para id="x_24e">You should configure this hook in your server's
belaran@999 10649 <filename role="special" moreinfo="none">~/.hgrc</filename> as an <literal role="hook" moreinfo="none">incoming</literal> hook, for example as
belaran@999 10650 follows:
belaran@999 10651 </para>
belaran@999 10652 <programlisting format="linespecific">[hooks]
belaran@999 10653 incoming.bugzilla = python:hgext.bugzilla.hook</programlisting>
belaran@999 10654
belaran@999 10655 <para id="x_24f">Because of the specialised nature of this hook, and
belaran@999 10656 because Bugzilla was not written with this kind of
belaran@999 10657 integration in mind, configuring this hook is a somewhat
belaran@999 10658 involved process.
belaran@999 10659 </para>
belaran@999 10660
belaran@999 10661 <para id="x_250">Before you begin, you must install the MySQL bindings
belaran@999 10662 for Python on the host(s) where you'll be running the hook.
belaran@999 10663 If this is not available as a binary package for your
belaran@999 10664 system, you can download it from
belaran@999 10665 <citation>web:mysql-python</citation>.
belaran@999 10666 </para>
belaran@999 10667
belaran@999 10668 <para id="x_251">Configuration information for this hook lives in the
belaran@999 10669 <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> section of
belaran@999 10670 your <filename role="special" moreinfo="none">~/.hgrc</filename>.
belaran@999 10671 </para>
belaran@999 10672 <itemizedlist>
belaran@999 10673 <listitem><para id="x_252"><envar role="rc-item-bugzilla">version</envar>: The version
belaran@999 10674 of Bugzilla installed on the server. The database
belaran@999 10675 schema that Bugzilla uses changes occasionally, so this
belaran@999 10676 hook has to know exactly which schema to use.</para>
belaran@999 10677 </listitem>
belaran@999 10678 <listitem><para id="x_253"><envar role="rc-item-bugzilla">host</envar>:
belaran@999 10679 The hostname of the MySQL server that stores your
belaran@999 10680 Bugzilla data. The database must be configured to allow
belaran@999 10681 connections from whatever host you are running the
belaran@999 10682 <literal role="hook" moreinfo="none">bugzilla</literal> hook on.
belaran@999 10683 </para>
belaran@999 10684 </listitem>
belaran@999 10685 <listitem><para id="x_254"><envar role="rc-item-bugzilla">user</envar>:
belaran@999 10686 The username with which to connect to the MySQL server.
belaran@999 10687 The database must be configured to allow this user to
belaran@999 10688 connect from whatever host you are running the <literal role="hook" moreinfo="none">bugzilla</literal> hook on. This user
belaran@999 10689 must be able to access and modify Bugzilla tables. The
belaran@999 10690 default value of this item is <literal moreinfo="none">bugs</literal>,
belaran@999 10691 which is the standard name of the Bugzilla user in a
belaran@999 10692 MySQL database.
belaran@999 10693 </para>
belaran@999 10694 </listitem>
belaran@999 10695 <listitem><para id="x_255"><envar role="rc-item-bugzilla">password</envar>: The MySQL
belaran@999 10696 password for the user you configured above. This is
belaran@999 10697 stored as plain text, so you should make sure that
belaran@999 10698 unauthorised users cannot read the <filename role="special" moreinfo="none">~/.hgrc</filename> file where you
belaran@999 10699 store this information.
belaran@999 10700 </para>
belaran@999 10701 </listitem>
belaran@999 10702 <listitem><para id="x_256"><envar role="rc-item-bugzilla">db</envar>:
belaran@999 10703 The name of the Bugzilla database on the MySQL server.
belaran@999 10704 The default value of this item is
belaran@999 10705 <literal moreinfo="none">bugs</literal>, which is the standard name of
belaran@999 10706 the MySQL database where Bugzilla stores its data.
belaran@999 10707 </para>
belaran@999 10708 </listitem>
belaran@999 10709 <listitem><para id="x_257"><envar role="rc-item-bugzilla">notify</envar>: If you want
belaran@999 10710 Bugzilla to send out a notification email to subscribers
belaran@999 10711 after this hook has added a comment to a bug, you will
belaran@999 10712 need this hook to run a command whenever it updates the
belaran@999 10713 database. The command to run depends on where you have
belaran@999 10714 installed Bugzilla, but it will typically look something
belaran@999 10715 like this, if you have Bugzilla installed in <filename class="directory" moreinfo="none">/var/www/html/bugzilla</filename>:
belaran@999 10716 </para>
belaran@999 10717 <programlisting format="linespecific">cd /var/www/html/bugzilla &amp;&amp;
belaran@999 10718 ./processmail %s nobody@nowhere.com</programlisting>
belaran@999 10719 </listitem>
belaran@999 10720 <listitem><para id="x_258"> The Bugzilla
belaran@999 10721 <literal moreinfo="none">processmail</literal> program expects to be
belaran@999 10722 given a bug ID (the hook replaces
belaran@999 10723 <quote><literal moreinfo="none">%s</literal></quote> with the bug ID)
belaran@999 10724 and an email address. It also expects to be able to
belaran@999 10725 write to some files in the directory that it runs in.
belaran@999 10726 If Bugzilla and this hook are not installed on the same
belaran@999 10727 machine, you will need to find a way to run
belaran@999 10728 <literal moreinfo="none">processmail</literal> on the server where
belaran@999 10729 Bugzilla is installed.
belaran@999 10730 </para>
belaran@999 10731 </listitem></itemizedlist>
belaran@999 10732
belaran@999 10733 </sect3>
belaran@999 10734 <sect3>
belaran@999 10735 <title>Mapping committer names to Bugzilla user names</title>
belaran@999 10736
belaran@999 10737 <para id="x_259">By default, the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook tries to use the
belaran@999 10738 email address of a changeset's committer as the Bugzilla
belaran@999 10739 user name with which to update a bug. If this does not suit
belaran@999 10740 your needs, you can map committer email addresses to
belaran@999 10741 Bugzilla user names using a <literal role="rc-usermap" moreinfo="none">usermap</literal> section.
belaran@999 10742 </para>
belaran@999 10743
belaran@999 10744 <para id="x_25a">Each item in the <literal role="rc-usermap" moreinfo="none">usermap</literal> section contains an
belaran@999 10745 email address on the left, and a Bugzilla user name on the
belaran@999 10746 right.
belaran@999 10747 </para>
belaran@999 10748 <programlisting format="linespecific">[usermap]
belaran@999 10749 jane.user@example.com = jane</programlisting>
belaran@999 10750 <para id="x_25b">You can either keep the <literal role="rc-usermap" moreinfo="none">usermap</literal> data in a normal
belaran@999 10751 <filename role="special" moreinfo="none">~/.hgrc</filename>, or tell the
belaran@999 10752 <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook to read the
belaran@999 10753 information from an external <filename moreinfo="none">usermap</filename>
belaran@999 10754 file. In the latter case, you can store
belaran@999 10755 <filename moreinfo="none">usermap</filename> data by itself in (for example)
belaran@999 10756 a user-modifiable repository. This makes it possible to let
belaran@999 10757 your users maintain their own <envar role="rc-item-bugzilla">usermap</envar> entries. The main
belaran@999 10758 <filename role="special" moreinfo="none">~/.hgrc</filename> file might look
belaran@999 10759 like this:
belaran@999 10760 </para>
belaran@999 10761 <programlisting format="linespecific"># regular hgrc file refers to external usermap file
belaran@999 10762 [bugzilla]
belaran@999 10763 usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting>
belaran@999 10764 <para id="x_25c">While the <filename moreinfo="none">usermap</filename> file that it
belaran@999 10765 refers to might look like this:
belaran@999 10766 </para>
belaran@999 10767 <programlisting format="linespecific"># bugzilla-usermap.conf - inside a hg repository
belaran@999 10768 [usermap] stephanie@example.com = steph</programlisting>
belaran@999 10769
belaran@999 10770 </sect3>
belaran@999 10771 <sect3>
belaran@999 10772 <title>Configuring the text that gets added to a bug</title>
belaran@999 10773
belaran@999 10774 <para id="x_25d">You can configure the text that this hook adds as a
belaran@999 10775 comment; you specify it in the form of a Mercurial template.
belaran@999 10776 Several <filename role="special" moreinfo="none">~/.hgrc</filename> entries
belaran@999 10777 (still in the <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal>
belaran@999 10778 section) control this behavior.
belaran@999 10779 </para>
belaran@999 10780 <itemizedlist>
belaran@999 10781 <listitem><para id="x_25e"><literal moreinfo="none">strip</literal>: The number of
belaran@999 10782 leading path elements to strip from a repository's path
belaran@999 10783 name to construct a partial path for a URL. For example,
belaran@999 10784 if the repositories on your server live under <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and you
belaran@999 10785 have a repository whose path is <filename class="directory" moreinfo="none">/home/hg/repos/app/tests</filename>,
belaran@999 10786 then setting <literal moreinfo="none">strip</literal> to
belaran@999 10787 <literal moreinfo="none">4</literal> will give a partial path of
belaran@999 10788 <filename class="directory" moreinfo="none">app/tests</filename>. The
belaran@999 10789 hook will make this partial path available when
belaran@999 10790 expanding a template, as <literal moreinfo="none">webroot</literal>.
belaran@999 10791 </para>
belaran@999 10792 </listitem>
belaran@999 10793 <listitem><para id="x_25f"><literal moreinfo="none">template</literal>: The text of the
belaran@999 10794 template to use. In addition to the usual
belaran@999 10795 changeset-related variables, this template can use
belaran@999 10796 <literal moreinfo="none">hgweb</literal> (the value of the
belaran@999 10797 <literal moreinfo="none">hgweb</literal> configuration item above) and
belaran@999 10798 <literal moreinfo="none">webroot</literal> (the path constructed using
belaran@999 10799 <literal moreinfo="none">strip</literal> above).
belaran@999 10800 </para>
belaran@999 10801 </listitem></itemizedlist>
belaran@999 10802
belaran@999 10803 <para id="x_260">In addition, you can add a <envar role="rc-item-web">baseurl</envar> item to the <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>. The <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook will make this
belaran@999 10804 available when expanding a template, as the base string to
belaran@999 10805 use when constructing a URL that will let users browse from
belaran@999 10806 a Bugzilla comment to view a changeset. Example:
belaran@999 10807 </para>
belaran@999 10808 <programlisting format="linespecific">[web]
belaran@999 10809 baseurl = http://hg.domain.com/</programlisting>
belaran@999 10810
belaran@999 10811 <para id="x_261">Here is an example set of <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook config information.
belaran@999 10812 </para>
belaran@999 10813
belaran@999 10814 <!-- BEGIN ch10/bugzilla-config.lst -->
belaran@999 10815 <programlisting format="linespecific">[bugzilla]
belaran@999 10816 host = bugzilla.example.com
belaran@999 10817 password = mypassword version = 2.16
belaran@999 10818 # server-side repos live in /home/hg/repos, so strip 4 leading
belaran@999 10819 # separators
belaran@999 10820 strip = 4
belaran@999 10821 hgweb = http://hg.example.com/
belaran@999 10822 usermap = /home/hg/repos/notify/bugzilla.conf
belaran@999 10823 template = Changeset {node|short}, made by {author} in the {webroot}
belaran@999 10824 repo, refers to this bug.\n
belaran@999 10825 For complete details, see
belaran@999 10826 {hgweb}{webroot}?cmd=changeset;node={node|short}\n
belaran@999 10827 Changeset description:\n
belaran@999 10828 \t{desc|tabindent}</programlisting>
belaran@999 10829 <!-- END ch10/bugzilla-config.lst -->
belaran@999 10830
belaran@999 10831
belaran@999 10832 </sect3>
belaran@999 10833 <sect3>
belaran@999 10834 <title>Testing and troubleshooting</title>
belaran@999 10835
belaran@999 10836 <para id="x_262">The most common problems with configuring the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook relate to running
belaran@999 10837 Bugzilla's <filename moreinfo="none">processmail</filename> script and
belaran@999 10838 mapping committer names to user names.
belaran@999 10839 </para>
belaran@999 10840
belaran@999 10841 <para id="x_263">Recall from <xref linkend="sec:hook:bugzilla:config"/> above that the user
belaran@999 10842 that runs the Mercurial process on the server is also the
belaran@999 10843 one that will run the <filename moreinfo="none">processmail</filename>
belaran@999 10844 script. The <filename moreinfo="none">processmail</filename> script
belaran@999 10845 sometimes causes Bugzilla to write to files in its
belaran@999 10846 configuration directory, and Bugzilla's configuration files
belaran@999 10847 are usually owned by the user that your web server runs
belaran@999 10848 under.
belaran@999 10849 </para>
belaran@999 10850
belaran@999 10851 <para id="x_264">You can cause <filename moreinfo="none">processmail</filename> to be run
belaran@999 10852 with the suitable user's identity using the
belaran@999 10853 <command moreinfo="none">sudo</command> command. Here is an example entry
belaran@999 10854 for a <filename moreinfo="none">sudoers</filename> file.
belaran@999 10855 </para>
belaran@999 10856 <programlisting format="linespecific">hg_user = (httpd_user)
belaran@999 10857 NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting>
belaran@999 10858 <para id="x_265">This allows the <literal moreinfo="none">hg_user</literal> user to run a
belaran@999 10859 <filename moreinfo="none">processmail-wrapper</filename> program under the
belaran@999 10860 identity of <literal moreinfo="none">httpd_user</literal>.
belaran@999 10861 </para>
belaran@999 10862
belaran@999 10863 <para id="x_266">This indirection through a wrapper script is necessary,
belaran@999 10864 because <filename moreinfo="none">processmail</filename> expects to be run
belaran@999 10865 with its current directory set to wherever you installed
belaran@999 10866 Bugzilla; you can't specify that kind of constraint in a
belaran@999 10867 <filename moreinfo="none">sudoers</filename> file. The contents of the
belaran@999 10868 wrapper script are simple:
belaran@999 10869 </para>
belaran@999 10870 <programlisting format="linespecific">#!/bin/sh
belaran@999 10871 cd `dirname $0` &amp;&amp; ./processmail "$1" nobody@example.com</programlisting>
belaran@999 10872 <para id="x_267">It doesn't seem to matter what email address you pass to
belaran@999 10873 <filename moreinfo="none">processmail</filename>.
belaran@999 10874 </para>
belaran@999 10875
belaran@999 10876 <para id="x_268">If your <literal role="rc-usermap" moreinfo="none">usermap</literal> is
belaran@999 10877 not set up correctly, users will see an error message from
belaran@999 10878 the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook when they
belaran@999 10879 push changes to the server. The error message will look
belaran@999 10880 like this:
belaran@999 10881 </para>
belaran@999 10882 <programlisting format="linespecific">cannot find bugzilla user id for john.q.public@example.com</programlisting>
belaran@999 10883 <para id="x_269">What this means is that the committer's address,
belaran@999 10884 <literal moreinfo="none">john.q.public@example.com</literal>, is not a valid
belaran@999 10885 Bugzilla user name, nor does it have an entry in your
belaran@999 10886 <literal role="rc-usermap" moreinfo="none">usermap</literal> that maps it to
belaran@999 10887 a valid Bugzilla user name.
belaran@999 10888 </para>
belaran@999 10889
belaran@999 10890 </sect3> </sect2>
belaran@999 10891
belaran@999 10892 <sect2>
belaran@999 10893 <title><literal role="hg-ext" moreinfo="none">notify</literal>—send email
belaran@999 10894 notifications</title>
belaran@999 10895
belaran@999 10896 <para id="x_26a">Although Mercurial's built-in web server provides RSS
belaran@999 10897 feeds of changes in every repository, many people prefer to
belaran@999 10898 receive change notifications via email. The <literal role="hg-ext" moreinfo="none">notify</literal> hook lets you send out
belaran@999 10899 notifications to a set of email addresses whenever changesets
belaran@999 10900 arrive that those subscribers are interested in.
belaran@999 10901 </para>
belaran@999 10902
belaran@999 10903 <para id="x_26b">As with the <literal role="hg-ext" moreinfo="none">bugzilla</literal>
belaran@999 10904 hook, the <literal role="hg-ext" moreinfo="none">notify</literal> hook is
belaran@999 10905 template-driven, so you can customise the contents of the
belaran@999 10906 notification messages that it sends.
belaran@999 10907 </para>
belaran@999 10908
belaran@999 10909 <para id="x_26c">By default, the <literal role="hg-ext" moreinfo="none">notify</literal>
belaran@999 10910 hook includes a diff of every changeset that it sends out; you
belaran@999 10911 can limit the size of the diff, or turn this feature off
belaran@999 10912 entirely. It is useful for letting subscribers review changes
belaran@999 10913 immediately, rather than clicking to follow a URL.
belaran@999 10914 </para>
belaran@999 10915
belaran@999 10916 <sect3>
belaran@999 10917 <title>Configuring the <literal role="hg-ext" moreinfo="none">notify</literal>
belaran@999 10918 hook</title>
belaran@999 10919
belaran@999 10920 <para id="x_26d">You can set up the <literal role="hg-ext" moreinfo="none">notify</literal> hook to send one email
belaran@999 10921 message per incoming changeset, or one per incoming group of
belaran@999 10922 changesets (all those that arrived in a single pull or
belaran@999 10923 push).
belaran@999 10924 </para>
belaran@999 10925 <programlisting format="linespecific">[hooks]
belaran@999 10926 # send one email per group of changes
belaran@999 10927 changegroup.notify = python:hgext.notify.hook
belaran@999 10928 # send one email per change
belaran@999 10929 incoming.notify = python:hgext.notify.hook</programlisting>
belaran@999 10930
belaran@999 10931 <para id="x_26e">Configuration information for this hook lives in the
belaran@999 10932 <literal role="rc-notify" moreinfo="none">notify</literal> section of a
belaran@999 10933 <filename role="special" moreinfo="none">~/.hgrc</filename> file.
belaran@999 10934 </para>
belaran@999 10935 <itemizedlist>
belaran@999 10936 <listitem><para id="x_26f"><envar role="rc-item-notify">test</envar>:
belaran@999 10937 By default, this hook does not send out email at all;
belaran@999 10938 instead, it prints the message that it
belaran@999 10939 <emphasis>would</emphasis> send. Set this item to
belaran@999 10940 <literal moreinfo="none">false</literal> to allow email to be sent. The
belaran@999 10941 reason that sending of email is turned off by default is
belaran@999 10942 that it takes several tries to configure this extension
belaran@999 10943 exactly as you would like, and it would be bad form to
belaran@999 10944 spam subscribers with a number of <quote>broken</quote>
belaran@999 10945 notifications while you debug your configuration.
belaran@999 10946 </para>
belaran@999 10947 </listitem>
belaran@999 10948 <listitem><para id="x_270"><envar role="rc-item-notify">config</envar>:
belaran@999 10949 The path to a configuration file that contains
belaran@999 10950 subscription information. This is kept separate from
belaran@999 10951 the main <filename role="special" moreinfo="none">~/.hgrc</filename> so
belaran@999 10952 that you can maintain it in a repository of its own.
belaran@999 10953 People can then clone that repository, update their
belaran@999 10954 subscriptions, and push the changes back to your server.
belaran@999 10955 </para>
belaran@999 10956 </listitem>
belaran@999 10957 <listitem><para id="x_271"><envar role="rc-item-notify">strip</envar>:
belaran@999 10958 The number of leading path separator characters to strip
belaran@999 10959 from a repository's path, when deciding whether a
belaran@999 10960 repository has subscribers. For example, if the
belaran@999 10961 repositories on your server live in <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and
belaran@999 10962 <literal role="hg-ext" moreinfo="none">notify</literal> is considering a
belaran@999 10963 repository named <filename class="directory" moreinfo="none">/home/hg/repos/shared/test</filename>,
belaran@999 10964 setting <envar role="rc-item-notify">strip</envar> to
belaran@999 10965 <literal moreinfo="none">4</literal> will cause <literal role="hg-ext" moreinfo="none">notify</literal> to trim the path it
belaran@999 10966 considers down to <filename class="directory" moreinfo="none">shared/test</filename>, and it will
belaran@999 10967 match subscribers against that.
belaran@999 10968 </para>
belaran@999 10969 </listitem>
belaran@999 10970 <listitem><para id="x_272"><envar role="rc-item-notify">template</envar>: The template
belaran@999 10971 text to use when sending messages. This specifies both
belaran@999 10972 the contents of the message header and its body.
belaran@999 10973 </para>
belaran@999 10974 </listitem>
belaran@999 10975 <listitem><para id="x_273"><envar role="rc-item-notify">maxdiff</envar>: The maximum
belaran@999 10976 number of lines of diff data to append to the end of a
belaran@999 10977 message. If a diff is longer than this, it is
belaran@999 10978 truncated. By default, this is set to 300. Set this to
belaran@999 10979 <literal moreinfo="none">0</literal> to omit diffs from notification
belaran@999 10980 emails.
belaran@999 10981 </para>
belaran@999 10982 </listitem>
belaran@999 10983 <listitem><para id="x_274"><envar role="rc-item-notify">sources</envar>: A list of
belaran@999 10984 sources of changesets to consider. This lets you limit
belaran@999 10985 <literal role="hg-ext" moreinfo="none">notify</literal> to only sending
belaran@999 10986 out email about changes that remote users pushed into
belaran@999 10987 this repository via a server, for example. See
belaran@999 10988 <xref linkend="sec:hook:sources"/> for the sources you
belaran@999 10989 can specify here.
belaran@999 10990 </para>
belaran@999 10991 </listitem></itemizedlist>
belaran@999 10992
belaran@999 10993 <para id="x_275">If you set the <envar role="rc-item-web">baseurl</envar>
belaran@999 10994 item in the <literal role="rc-web" moreinfo="none">web</literal> section,
belaran@999 10995 you can use it in a template; it will be available as
belaran@999 10996 <literal moreinfo="none">webroot</literal>.
belaran@999 10997 </para>
belaran@999 10998
belaran@999 10999 <para id="x_276">Here is an example set of <literal role="hg-ext" moreinfo="none">notify</literal> configuration information.
belaran@999 11000 </para>
belaran@999 11001
belaran@999 11002 <!-- BEGIN ch10/notify-config.lst -->
belaran@999 11003 <programlisting format="linespecific">[notify]
belaran@999 11004 # really send email
belaran@999 11005 test = false
belaran@999 11006 # subscriber data lives in the notify repo
belaran@999 11007 config = /home/hg/repos/notify/notify.conf
belaran@999 11008 # repos live in /home/hg/repos on server, so strip 4 "/" chars
belaran@999 11009 strip = 4
belaran@999 11010 template = X-Hg-Repo: {webroot}\n
belaran@999 11011 Subject: {webroot}: {desc|firstline|strip}\n
belaran@999 11012 From: {author}
belaran@999 11013 \n\n
belaran@999 11014 changeset {node|short} in {root}
belaran@999 11015 \n\ndetails:
belaran@999 11016 {baseurl}{webroot}?cmd=changeset;node={node|short}
belaran@999 11017 description: {desc|tabindent|strip}
belaran@999 11018
belaran@999 11019 [web]
belaran@999 11020 baseurl =
belaran@999 11021 http://hg.example.com/</programlisting>
belaran@999 11022 <!-- END ch10/notify-config.lst -->
belaran@999 11023
belaran@999 11024
belaran@999 11025 <para id="x_277">This will produce a message that looks like the
belaran@999 11026 following:
belaran@999 11027 </para>
belaran@999 11028
belaran@999 11029 <!-- BEGIN ch10/notify-config-mail.lst -->
belaran@999 11030 <programlisting format="linespecific">X-Hg-Repo: tests/slave
belaran@999 11031 Subject: tests/slave: Handle error case when slave has no buffers
belaran@999 11032 Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT)
belaran@999 11033
belaran@999 11034 changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
belaran@999 11035
belaran@999 11036 details:
belaran@999 11037 http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
belaran@999 11038
belaran@999 11039 description: Handle error case when slave has no buffers
belaran@999 11040
belaran@999 11041 diffs (54 lines):
belaran@999 11042 diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
belaran@999 11043 --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700
belaran@999 11044 +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700
belaran@999 11045 @@ -212,6 +212,15 @@ static __inline__
belaran@999 11046 void test_headers(void *h)
belaran@999 11047 [...snip...]</programlisting>
belaran@999 11048 <!-- END ch10/notify-config-mail.lst -->
belaran@999 11049
belaran@999 11050
belaran@999 11051 </sect3>
belaran@999 11052 <sect3>
belaran@999 11053 <title>Testing and troubleshooting</title>
belaran@999 11054
belaran@999 11055 <para id="x_278">Do not forget that by default, the <literal role="hg-ext" moreinfo="none">notify</literal> extension <emphasis>will not
belaran@999 11056 send any mail</emphasis> until you explicitly configure it to do so,
belaran@999 11057 by setting <envar role="rc-item-notify">test</envar> to
belaran@999 11058 <literal moreinfo="none">false</literal>. Until you do that, it simply
belaran@999 11059 prints the message it <emphasis>would</emphasis> send.
belaran@999 11060 </para>
belaran@999 11061
belaran@999 11062 </sect3>
belaran@999 11063 </sect2>
belaran@999 11064 </sect1>
belaran@999 11065 <sect1 id="sec:hook:ref">
belaran@999 11066 <title>Information for writers of hooks</title>
belaran@999 11067
belaran@999 11068 <sect2>
belaran@999 11069 <title>In-process hook execution</title>
belaran@999 11070
belaran@999 11071 <para id="x_279">An in-process hook is called with arguments of the
belaran@999 11072 following form:
belaran@999 11073 </para>
belaran@999 11074 <programlisting format="linespecific">def myhook(ui, repo, **kwargs): pass</programlisting>
belaran@999 11075 <para id="x_27a">The <literal moreinfo="none">ui</literal> parameter is a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object. The
belaran@999 11076 <literal moreinfo="none">repo</literal> parameter is a <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>
belaran@999 11077 object. The names and values of the
belaran@999 11078 <literal moreinfo="none">**kwargs</literal> parameters depend on the hook
belaran@999 11079 being invoked, with the following common features:
belaran@999 11080 </para>
belaran@999 11081 <itemizedlist>
belaran@999 11082 <listitem><para id="x_27b">If a parameter is named
belaran@999 11083 <literal moreinfo="none">node</literal> or <literal moreinfo="none">parentN</literal>, it
belaran@999 11084 will contain a hexadecimal changeset ID. The empty string
belaran@999 11085 is used to represent <quote>null changeset ID</quote>
belaran@999 11086 instead of a string of zeroes.
belaran@999 11087 </para>
belaran@999 11088 </listitem>
belaran@999 11089 <listitem><para id="x_27c">If a parameter is named
belaran@999 11090 <literal moreinfo="none">url</literal>, it will contain the URL of a
belaran@999 11091 remote repository, if that can be determined.
belaran@999 11092 </para>
belaran@999 11093 </listitem>
belaran@999 11094 <listitem><para id="x_27d">Boolean-valued parameters are represented as
belaran@999 11095 Python <literal moreinfo="none">bool</literal> objects.
belaran@999 11096 </para>
belaran@999 11097 </listitem></itemizedlist>
belaran@999 11098
belaran@999 11099 <para id="x_27e">An in-process hook is called without a change to the
belaran@999 11100 process's working directory (unlike external hooks, which are
belaran@999 11101 run in the root of the repository). It must not change the
belaran@999 11102 process's working directory, or it will cause any calls it
belaran@999 11103 makes into the Mercurial API to fail.
belaran@999 11104 </para>
belaran@999 11105
belaran@999 11106 <para id="x_27f">If a hook returns a boolean <quote>false</quote> value, it
belaran@999 11107 is considered to have succeeded. If it returns a boolean
belaran@999 11108 <quote>true</quote> value or raises an exception, it is
belaran@999 11109 considered to have failed. A useful way to think of the
belaran@999 11110 calling convention is <quote>tell me if you fail</quote>.
belaran@999 11111 </para>
belaran@999 11112
belaran@999 11113 <para id="x_280">Note that changeset IDs are passed into Python hooks as
belaran@999 11114 hexadecimal strings, not the binary hashes that Mercurial's
belaran@999 11115 APIs normally use. To convert a hash from hex to binary, use
belaran@999 11116 the <literal moreinfo="none">bin</literal> function.
belaran@999 11117 </para>
belaran@999 11118 </sect2>
belaran@999 11119
belaran@999 11120 <sect2>
belaran@999 11121 <title>External hook execution</title>
belaran@999 11122
belaran@999 11123 <para id="x_281">An external hook is passed to the shell of the user
belaran@999 11124 running Mercurial. Features of that shell, such as variable
belaran@999 11125 substitution and command redirection, are available. The hook
belaran@999 11126 is run in the root directory of the repository (unlike
belaran@999 11127 in-process hooks, which are run in the same directory that
belaran@999 11128 Mercurial was run in).
belaran@999 11129 </para>
belaran@999 11130
belaran@999 11131 <para id="x_282">Hook parameters are passed to the hook as environment
belaran@999 11132 variables. Each environment variable's name is converted in
belaran@999 11133 upper case and prefixed with the string
belaran@999 11134 <quote><literal moreinfo="none">HG_</literal></quote>. For example, if the
belaran@999 11135 name of a parameter is <quote><literal moreinfo="none">node</literal></quote>,
belaran@999 11136 the name of the environment variable representing that
belaran@999 11137 parameter will be <quote><literal moreinfo="none">HG_NODE</literal></quote>.
belaran@999 11138 </para>
belaran@999 11139
belaran@999 11140 <para id="x_283">A boolean parameter is represented as the string
belaran@999 11141 <quote><literal moreinfo="none">1</literal></quote> for <quote>true</quote>,
belaran@999 11142 <quote><literal moreinfo="none">0</literal></quote> for <quote>false</quote>.
belaran@999 11143 If an environment variable is named <envar>HG_NODE</envar>,
belaran@999 11144 <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it
belaran@999 11145 contains a changeset ID represented as a hexadecimal string.
belaran@999 11146 The empty string is used to represent <quote>null changeset
belaran@999 11147 ID</quote> instead of a string of zeroes. If an environment
belaran@999 11148 variable is named <envar>HG_URL</envar>, it will contain the
belaran@999 11149 URL of a remote repository, if that can be determined.
belaran@999 11150 </para>
belaran@999 11151
belaran@999 11152 <para id="x_284">If a hook exits with a status of zero, it is considered to
belaran@999 11153 have succeeded. If it exits with a non-zero status, it is
belaran@999 11154 considered to have failed.
belaran@999 11155 </para>
belaran@999 11156 </sect2>
belaran@999 11157
belaran@999 11158 <sect2>
belaran@999 11159 <title>Finding out where changesets come from</title>
belaran@999 11160
belaran@999 11161 <para id="x_285">A hook that involves the transfer of changesets between a
belaran@999 11162 local repository and another may be able to find out
belaran@999 11163 information about the <quote>far side</quote>. Mercurial
belaran@999 11164 knows <emphasis>how</emphasis> changes are being transferred,
belaran@999 11165 and in many cases <emphasis>where</emphasis> they are being
belaran@999 11166 transferred to or from.
belaran@999 11167 </para>
belaran@999 11168
belaran@999 11169 <sect3 id="sec:hook:sources">
belaran@999 11170 <title>Sources of changesets</title>
belaran@999 11171
belaran@999 11172 <para id="x_286">Mercurial will tell a hook what means are, or were, used
belaran@999 11173 to transfer changesets between repositories. This is
belaran@999 11174 provided by Mercurial in a Python parameter named
belaran@999 11175 <literal moreinfo="none">source</literal>, or an environment variable named
belaran@999 11176 <envar>HG_SOURCE</envar>.
belaran@999 11177 </para>
belaran@999 11178
belaran@999 11179 <itemizedlist>
belaran@999 11180 <listitem><para id="x_287"><literal moreinfo="none">serve</literal>: Changesets are
belaran@999 11181 transferred to or from a remote repository over http or
belaran@999 11182 ssh.
belaran@999 11183 </para>
belaran@999 11184 </listitem>
belaran@999 11185 <listitem><para id="x_288"><literal moreinfo="none">pull</literal>: Changesets are
belaran@999 11186 being transferred via a pull from one repository into
belaran@999 11187 another.
belaran@999 11188 </para>
belaran@999 11189 </listitem>
belaran@999 11190 <listitem><para id="x_289"><literal moreinfo="none">push</literal>: Changesets are
belaran@999 11191 being transferred via a push from one repository into
belaran@999 11192 another.
belaran@999 11193 </para>
belaran@999 11194 </listitem>
belaran@999 11195 <listitem><para id="x_28a"><literal moreinfo="none">bundle</literal>: Changesets are
belaran@999 11196 being transferred to or from a bundle.
belaran@999 11197 </para>
belaran@999 11198 </listitem></itemizedlist>
belaran@999 11199 </sect3>
belaran@999 11200
belaran@999 11201 <sect3 id="sec:hook:url">
belaran@999 11202 <title>Where changes are going—remote repository
belaran@999 11203 URLs</title>
belaran@999 11204
belaran@999 11205 <para id="x_28b">When possible, Mercurial will tell a hook the location
belaran@999 11206 of the <quote>far side</quote> of an activity that transfers
belaran@999 11207 changeset data between repositories. This is provided by
belaran@999 11208 Mercurial in a Python parameter named
belaran@999 11209 <literal moreinfo="none">url</literal>, or an environment variable named
belaran@999 11210 <envar>HG_URL</envar>.
belaran@999 11211 </para>
belaran@999 11212
belaran@999 11213 <para id="x_28c">This information is not always known. If a hook is
belaran@999 11214 invoked in a repository that is being served via http or
belaran@999 11215 ssh, Mercurial cannot tell where the remote repository is,
belaran@999 11216 but it may know where the client is connecting from. In
belaran@999 11217 such cases, the URL will take one of the following forms:
belaran@999 11218 </para>
belaran@999 11219 <itemizedlist>
belaran@999 11220 <listitem><para id="x_28d"><literal moreinfo="none">remote:ssh:1.2.3.4</literal>—remote
belaran@999 11221 ssh client, at the IP address
belaran@999 11222 <literal moreinfo="none">1.2.3.4</literal>.
belaran@999 11223 </para>
belaran@999 11224 </listitem>
belaran@999 11225 <listitem><para id="x_28e"><literal moreinfo="none">remote:http:1.2.3.4</literal>—remote
belaran@999 11226 http client, at the IP address
belaran@999 11227 <literal moreinfo="none">1.2.3.4</literal>. If the client is using SSL,
belaran@999 11228 this will be of the form
belaran@999 11229 <literal moreinfo="none">remote:https:1.2.3.4</literal>.
belaran@999 11230 </para>
belaran@999 11231 </listitem>
belaran@999 11232 <listitem><para id="x_28f">Empty—no information could be
belaran@999 11233 discovered about the remote client.
belaran@999 11234 </para>
belaran@999 11235 </listitem></itemizedlist>
belaran@999 11236 </sect3>
belaran@999 11237 </sect2>
belaran@999 11238 </sect1>
belaran@999 11239 <sect1>
belaran@999 11240 <title>Hook reference</title>
belaran@999 11241
belaran@999 11242 <sect2 id="sec:hook:changegroup">
belaran@999 11243 <title><literal role="hook" moreinfo="none">changegroup</literal>—after
belaran@999 11244 remote changesets added</title>
belaran@999 11245
belaran@999 11246 <para id="x_290">This hook is run after a group of pre-existing changesets
belaran@999 11247 has been added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg
belaran@999 11248 unbundle</command>. This hook is run once per operation
belaran@999 11249 that added one or more changesets. This is in contrast to the
belaran@999 11250 <literal role="hook" moreinfo="none">incoming</literal> hook, which is run
belaran@999 11251 once per changeset, regardless of whether the changesets
belaran@999 11252 arrive in a group.
belaran@999 11253 </para>
belaran@999 11254
belaran@999 11255 <para id="x_291">Some possible uses for this hook include kicking off an
belaran@999 11256 automated build or test of the added changesets, updating a
belaran@999 11257 bug database, or notifying subscribers that a repository
belaran@999 11258 contains new changes.
belaran@999 11259 </para>
belaran@999 11260
belaran@999 11261 <para id="x_292">Parameters to this hook:
belaran@999 11262 </para>
belaran@999 11263 <itemizedlist>
belaran@999 11264 <listitem><para id="x_293"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11265 changeset ID of the first changeset in the group that was
belaran@999 11266 added. All changesets between this and
belaran@999 11267 <literal role="tag" moreinfo="none">tip</literal>, inclusive, were added by a single
belaran@999 11268 <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>.
belaran@999 11269 </para>
belaran@999 11270 </listitem>
belaran@999 11271 <listitem><para id="x_294"><literal moreinfo="none">source</literal>: A
belaran@999 11272 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details.
belaran@999 11273 </para>
belaran@999 11274 </listitem>
belaran@999 11275 <listitem><para id="x_295"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11276 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11277 </para>
belaran@999 11278 </listitem></itemizedlist>
belaran@999 11279
belaran@999 11280 <para id="x_296">See also: <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
belaran@999 11281 </para>
belaran@999 11282 </sect2>
belaran@999 11283
belaran@999 11284 <sect2 id="sec:hook:commit">
belaran@999 11285 <title><literal role="hook" moreinfo="none">commit</literal>—after a new
belaran@999 11286 changeset is created</title>
belaran@999 11287
belaran@999 11288 <para id="x_297">This hook is run after a new changeset has been created.
belaran@999 11289 </para>
belaran@999 11290
belaran@999 11291 <para id="x_298">Parameters to this hook:
belaran@999 11292 </para>
belaran@999 11293 <itemizedlist>
belaran@999 11294 <listitem><para id="x_299"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11295 changeset ID of the newly committed changeset.
belaran@999 11296 </para>
belaran@999 11297 </listitem>
belaran@999 11298 <listitem><para id="x_29a"><literal moreinfo="none">parent1</literal>: A changeset ID.
belaran@999 11299 The changeset ID of the first parent of the newly
belaran@999 11300 committed changeset.
belaran@999 11301 </para>
belaran@999 11302 </listitem>
belaran@999 11303 <listitem><para id="x_29b"><literal moreinfo="none">parent2</literal>: A changeset ID.
belaran@999 11304 The changeset ID of the second parent of the newly
belaran@999 11305 committed changeset.
belaran@999 11306 </para>
belaran@999 11307 </listitem></itemizedlist>
belaran@999 11308
belaran@999 11309 <para id="x_29c">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>)
belaran@999 11310 </para>
belaran@999 11311 </sect2>
belaran@999 11312
belaran@999 11313 <sect2 id="sec:hook:incoming">
belaran@999 11314 <title><literal role="hook" moreinfo="none">incoming</literal>—after one
belaran@999 11315 remote changeset is added</title>
belaran@999 11316
belaran@999 11317 <para id="x_29d">This hook is run after a pre-existing changeset has been
belaran@999 11318 added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg push</command>. If a group of changesets
belaran@999 11319 was added in a single operation, this hook is called once for
belaran@999 11320 each added changeset.
belaran@999 11321 </para>
belaran@999 11322
belaran@999 11323 <para id="x_29e">You can use this hook for the same purposes as
belaran@999 11324 the <literal role="hook" moreinfo="none">changegroup</literal> hook (<xref linkend="sec:hook:changegroup"/>); it's simply more
belaran@999 11325 convenient sometimes to run a hook once per group of
belaran@999 11326 changesets, while other times it's handier once per changeset.
belaran@999 11327 </para>
belaran@999 11328
belaran@999 11329 <para id="x_29f">Parameters to this hook:
belaran@999 11330 </para>
belaran@999 11331 <itemizedlist>
belaran@999 11332 <listitem><para id="x_2a0"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11333 ID of the newly added changeset.
belaran@999 11334 </para>
belaran@999 11335 </listitem>
belaran@999 11336 <listitem><para id="x_2a1"><literal moreinfo="none">source</literal>: A
belaran@999 11337 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details.
belaran@999 11338 </para>
belaran@999 11339 </listitem>
belaran@999 11340 <listitem><para id="x_2a2"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11341 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11342 </para>
belaran@999 11343 </listitem></itemizedlist>
belaran@999 11344
belaran@999 11345 <para id="x_2a3">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>) <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
belaran@999 11346 </para>
belaran@999 11347 </sect2>
belaran@999 11348
belaran@999 11349 <sect2 id="sec:hook:outgoing">
belaran@999 11350 <title><literal role="hook" moreinfo="none">outgoing</literal>—after
belaran@999 11351 changesets are propagated</title>
belaran@999 11352
belaran@999 11353 <para id="x_2a4">This hook is run after a group of changesets has been
belaran@999 11354 propagated out of this repository, for example by a <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg
belaran@999 11355 bundle</command> command.
belaran@999 11356 </para>
belaran@999 11357
belaran@999 11358 <para id="x_2a5">One possible use for this hook is to notify administrators
belaran@999 11359 that changes have been pulled.
belaran@999 11360 </para>
belaran@999 11361
belaran@999 11362 <para id="x_2a6">Parameters to this hook:
belaran@999 11363 </para>
belaran@999 11364 <itemizedlist>
belaran@999 11365 <listitem><para id="x_2a7"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11366 changeset ID of the first changeset of the group that was
belaran@999 11367 sent.
belaran@999 11368 </para>
belaran@999 11369 </listitem>
belaran@999 11370 <listitem><para id="x_2a8"><literal moreinfo="none">source</literal>: A string. The
belaran@999 11371 source of the of the operation (see <xref linkend="sec:hook:sources"/>). If a remote
belaran@999 11372 client pulled changes from this repository,
belaran@999 11373 <literal moreinfo="none">source</literal> will be
belaran@999 11374 <literal moreinfo="none">serve</literal>. If the client that obtained
belaran@999 11375 changes from this repository was local,
belaran@999 11376 <literal moreinfo="none">source</literal> will be
belaran@999 11377 <literal moreinfo="none">bundle</literal>, <literal moreinfo="none">pull</literal>, or
belaran@999 11378 <literal moreinfo="none">push</literal>, depending on the operation the
belaran@999 11379 client performed.
belaran@999 11380 </para>
belaran@999 11381 </listitem>
belaran@999 11382 <listitem><para id="x_2a9"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11383 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11384 </para>
belaran@999 11385 </listitem></itemizedlist>
belaran@999 11386
belaran@999 11387 <para id="x_2aa">See also: <literal role="hook" moreinfo="none">preoutgoing</literal> (<xref linkend="sec:hook:preoutgoing"/>)
belaran@999 11388 </para>
belaran@999 11389 </sect2>
belaran@999 11390
belaran@999 11391 <sect2 id="sec:hook:prechangegroup">
belaran@999 11392 <title><literal role="hook" moreinfo="none">prechangegroup</literal>—before starting
belaran@999 11393 to add remote changesets</title>
belaran@999 11394
belaran@999 11395 <para id="x_2ab">This controlling hook is run before Mercurial begins to
belaran@999 11396 add a group of changesets from another repository.
belaran@999 11397 </para>
belaran@999 11398
belaran@999 11399 <para id="x_2ac">This hook does not have any information about the
belaran@999 11400 changesets to be added, because it is run before transmission
belaran@999 11401 of those changesets is allowed to begin. If this hook fails,
belaran@999 11402 the changesets will not be transmitted.
belaran@999 11403 </para>
belaran@999 11404
belaran@999 11405 <para id="x_2ad">One use for this hook is to prevent external changes from
belaran@999 11406 being added to a repository. For example, you could use this
belaran@999 11407 to <quote>freeze</quote> a server-hosted branch temporarily or
belaran@999 11408 permanently so that users cannot push to it, while still
belaran@999 11409 allowing a local administrator to modify the repository.
belaran@999 11410 </para>
belaran@999 11411
belaran@999 11412 <para id="x_2ae">Parameters to this hook:
belaran@999 11413 </para>
belaran@999 11414 <itemizedlist>
belaran@999 11415 <listitem><para id="x_2af"><literal moreinfo="none">source</literal>: A string. The
belaran@999 11416 source of these changes. See <xref linkend="sec:hook:sources"/> for details.
belaran@999 11417 </para>
belaran@999 11418 </listitem>
belaran@999 11419 <listitem><para id="x_2b0"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11420 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11421 </para>
belaran@999 11422 </listitem></itemizedlist>
belaran@999 11423
belaran@999 11424 <para id="x_2b1">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
belaran@999 11425 </para>
belaran@999 11426 </sect2>
belaran@999 11427
belaran@999 11428 <sect2 id="sec:hook:precommit">
belaran@999 11429 <title><literal role="hook" moreinfo="none">precommit</literal>—before
belaran@999 11430 starting to commit a changeset</title>
belaran@999 11431
belaran@999 11432 <para id="x_2b2">This hook is run before Mercurial begins to commit a new
belaran@999 11433 changeset. It is run before Mercurial has any of the metadata
belaran@999 11434 for the commit, such as the files to be committed, the commit
belaran@999 11435 message, or the commit date.
belaran@999 11436 </para>
belaran@999 11437
belaran@999 11438 <para id="x_2b3">One use for this hook is to disable the ability to commit
belaran@999 11439 new changesets, while still allowing incoming changesets.
belaran@999 11440 Another is to run a build or test, and only allow the commit
belaran@999 11441 to begin if the build or test succeeds.
belaran@999 11442 </para>
belaran@999 11443
belaran@999 11444 <para id="x_2b4">Parameters to this hook:
belaran@999 11445 </para>
belaran@999 11446 <itemizedlist>
belaran@999 11447 <listitem><para id="x_2b5"><literal moreinfo="none">parent1</literal>: A changeset ID.
belaran@999 11448 The changeset ID of the first parent of the working
belaran@999 11449 directory.
belaran@999 11450 </para>
belaran@999 11451 </listitem>
belaran@999 11452 <listitem><para id="x_2b6"><literal moreinfo="none">parent2</literal>: A changeset ID.
belaran@999 11453 The changeset ID of the second parent of the working
belaran@999 11454 directory.
belaran@999 11455 </para>
belaran@999 11456 </listitem></itemizedlist>
belaran@999 11457 <para id="x_2b7">If the commit proceeds, the parents of the working
belaran@999 11458 directory will become the parents of the new changeset.
belaran@999 11459 </para>
belaran@999 11460
belaran@999 11461 <para id="x_2b8">See also: <literal role="hook" moreinfo="none">commit</literal>
belaran@999 11462 (<xref linkend="sec:hook:commit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>)
belaran@999 11463 </para>
belaran@999 11464 </sect2>
belaran@999 11465
belaran@999 11466 <sect2 id="sec:hook:preoutgoing">
belaran@999 11467 <title><literal role="hook" moreinfo="none">preoutgoing</literal>—before
belaran@999 11468 starting to propagate changesets</title>
belaran@999 11469
belaran@999 11470 <para id="x_2b9">This hook is invoked before Mercurial knows the identities
belaran@999 11471 of the changesets to be transmitted.
belaran@999 11472 </para>
belaran@999 11473
belaran@999 11474 <para id="x_2ba">One use for this hook is to prevent changes from being
belaran@999 11475 transmitted to another repository.
belaran@999 11476 </para>
belaran@999 11477
belaran@999 11478 <para id="x_2bb">Parameters to this hook:
belaran@999 11479 </para>
belaran@999 11480 <itemizedlist>
belaran@999 11481 <listitem><para id="x_2bc"><literal moreinfo="none">source</literal>: A
belaran@999 11482 string. The source of the operation that is attempting to
belaran@999 11483 obtain changes from this repository (see <xref linkend="sec:hook:sources"/>). See the documentation
belaran@999 11484 for the <literal moreinfo="none">source</literal> parameter to the
belaran@999 11485 <literal role="hook" moreinfo="none">outgoing</literal> hook, in
belaran@999 11486 <xref linkend="sec:hook:outgoing"/>, for possible values
belaran@999 11487 of this parameter.
belaran@999 11488 </para>
belaran@999 11489 </listitem>
belaran@999 11490 <listitem><para id="x_2bd"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11491 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11492 </para>
belaran@999 11493 </listitem></itemizedlist>
belaran@999 11494
belaran@999 11495 <para id="x_2be">See also: <literal role="hook" moreinfo="none">outgoing</literal> (<xref linkend="sec:hook:outgoing"/>)
belaran@999 11496 </para>
belaran@999 11497 </sect2>
belaran@999 11498
belaran@999 11499 <sect2 id="sec:hook:pretag">
belaran@999 11500 <title><literal role="hook" moreinfo="none">pretag</literal>—before
belaran@999 11501 tagging a changeset</title>
belaran@999 11502
belaran@999 11503 <para id="x_2bf">This controlling hook is run before a tag is created. If
belaran@999 11504 the hook succeeds, creation of the tag proceeds. If the hook
belaran@999 11505 fails, the tag is not created.
belaran@999 11506 </para>
belaran@999 11507
belaran@999 11508 <para id="x_2c0">Parameters to this hook:
belaran@999 11509 </para>
belaran@999 11510 <itemizedlist>
belaran@999 11511 <listitem><para id="x_2c1"><literal moreinfo="none">local</literal>: A boolean. Whether
belaran@999 11512 the tag is local to this repository instance (i.e. stored
belaran@999 11513 in <filename role="special" moreinfo="none">.hg/localtags</filename>) or
belaran@999 11514 managed by Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>).
belaran@999 11515 </para>
belaran@999 11516 </listitem>
belaran@999 11517 <listitem><para id="x_2c2"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11518 ID of the changeset to be tagged.
belaran@999 11519 </para>
belaran@999 11520 </listitem>
belaran@999 11521 <listitem><para id="x_2c3"><literal moreinfo="none">tag</literal>: A string. The name of
belaran@999 11522 the tag to be created.
belaran@999 11523 </para>
belaran@999 11524 </listitem></itemizedlist>
belaran@999 11525
belaran@999 11526 <para id="x_2c4">If the tag to be created is
belaran@999 11527 revision-controlled, the <literal role="hook" moreinfo="none">precommit</literal> and <literal role="hook" moreinfo="none">pretxncommit</literal> hooks (<xref linkend="sec:hook:commit"/> and <xref linkend="sec:hook:pretxncommit"/>) will also be run.
belaran@999 11528 </para>
belaran@999 11529
belaran@999 11530 <para id="x_2c5">See also: <literal role="hook" moreinfo="none">tag</literal>
belaran@999 11531 (<xref linkend="sec:hook:tag"/>)
belaran@999 11532 </para>
belaran@999 11533 </sect2>
belaran@999 11534
belaran@999 11535 <sect2 id="sec:hook:pretxnchangegroup">
belaran@999 11536 <title><literal role="hook" moreinfo="none">pretxnchangegroup</literal>—before
belaran@999 11537 completing addition of remote changesets</title>
belaran@999 11538
belaran@999 11539 <para id="x_2c6">This controlling hook is run before a
belaran@999 11540 transaction—that manages the addition of a group of new
belaran@999 11541 changesets from outside the repository—completes. If
belaran@999 11542 the hook succeeds, the transaction completes, and all of the
belaran@999 11543 changesets become permanent within this repository. If the
belaran@999 11544 hook fails, the transaction is rolled back, and the data for
belaran@999 11545 the changesets is erased.
belaran@999 11546 </para>
belaran@999 11547
belaran@999 11548 <para id="x_2c7">This hook can access the metadata associated with the
belaran@999 11549 almost-added changesets, but it should not do anything
belaran@999 11550 permanent with this data. It must also not modify the working
belaran@999 11551 directory.
belaran@999 11552 </para>
belaran@999 11553
belaran@999 11554 <para id="x_2c8">While this hook is running, if other Mercurial processes
belaran@999 11555 access this repository, they will be able to see the
belaran@999 11556 almost-added changesets as if they are permanent. This may
belaran@999 11557 lead to race conditions if you do not take steps to avoid
belaran@999 11558 them.
belaran@999 11559 </para>
belaran@999 11560
belaran@999 11561 <para id="x_2c9">This hook can be used to automatically vet a group of
belaran@999 11562 changesets. If the hook fails, all of the changesets are
belaran@999 11563 <quote>rejected</quote> when the transaction rolls back.
belaran@999 11564 </para>
belaran@999 11565
belaran@999 11566 <para id="x_2ca">Parameters to this hook:
belaran@999 11567 </para>
belaran@999 11568 <itemizedlist>
belaran@999 11569 <listitem><para id="x_2cb"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11570 changeset ID of the first changeset in the group that was
belaran@999 11571 added. All changesets between this and
belaran@999 11572 <literal role="tag" moreinfo="none">tip</literal>,
belaran@999 11573 inclusive, were added by a single <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>.
belaran@999 11574 </para>
belaran@999 11575 </listitem>
belaran@999 11576 <listitem><para id="x_2cc"><literal moreinfo="none">source</literal>: A
belaran@999 11577 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details.
belaran@999 11578 </para>
belaran@999 11579 </listitem>
belaran@999 11580 <listitem><para id="x_2cd"><literal moreinfo="none">url</literal>: A URL. The
belaran@999 11581 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information.
belaran@999 11582 </para>
belaran@999 11583 </listitem></itemizedlist>
belaran@999 11584
belaran@999 11585 <para id="x_2ce">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>)
belaran@999 11586 </para>
belaran@999 11587 </sect2>
belaran@999 11588
belaran@999 11589 <sect2 id="sec:hook:pretxncommit">
belaran@999 11590 <title><literal role="hook" moreinfo="none">pretxncommit</literal>—before
belaran@999 11591 completing commit of new changeset</title>
belaran@999 11592
belaran@999 11593 <para id="x_2cf">This controlling hook is run before a
belaran@999 11594 transaction—that manages a new commit—completes.
belaran@999 11595 If the hook succeeds, the transaction completes and the
belaran@999 11596 changeset becomes permanent within this repository. If the
belaran@999 11597 hook fails, the transaction is rolled back, and the commit
belaran@999 11598 data is erased.
belaran@999 11599 </para>
belaran@999 11600
belaran@999 11601 <para id="x_2d0">This hook can access the metadata associated with the
belaran@999 11602 almost-new changeset, but it should not do anything permanent
belaran@999 11603 with this data. It must also not modify the working
belaran@999 11604 directory.
belaran@999 11605 </para>
belaran@999 11606
belaran@999 11607 <para id="x_2d1">While this hook is running, if other Mercurial processes
belaran@999 11608 access this repository, they will be able to see the
belaran@999 11609 almost-new changeset as if it is permanent. This may lead to
belaran@999 11610 race conditions if you do not take steps to avoid them.
belaran@999 11611 </para>
belaran@999 11612
belaran@999 11613 <para id="x_2d2">Parameters to this hook:</para>
belaran@999 11614
belaran@999 11615 <itemizedlist>
belaran@999 11616 <listitem><para id="x_2d3"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11617 changeset ID of the newly committed changeset.
belaran@999 11618 </para>
belaran@999 11619 </listitem>
belaran@999 11620 <listitem><para id="x_2d4"><literal moreinfo="none">parent1</literal>: A changeset ID.
belaran@999 11621 The changeset ID of the first parent of the newly
belaran@999 11622 committed changeset.
belaran@999 11623 </para>
belaran@999 11624 </listitem>
belaran@999 11625 <listitem><para id="x_2d5"><literal moreinfo="none">parent2</literal>: A changeset ID.
belaran@999 11626 The changeset ID of the second parent of the newly
belaran@999 11627 committed changeset.
belaran@999 11628 </para>
belaran@999 11629 </listitem></itemizedlist>
belaran@999 11630
belaran@999 11631 <para id="x_2d6">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>)
belaran@999 11632 </para>
belaran@999 11633 </sect2>
belaran@999 11634
belaran@999 11635 <sect2 id="sec:hook:preupdate">
belaran@999 11636 <title><literal role="hook" moreinfo="none">preupdate</literal>—before
belaran@999 11637 updating or merging working directory</title>
belaran@999 11638
belaran@999 11639 <para id="x_2d7">This controlling hook is run before an update
belaran@999 11640 or merge of the working directory begins. It is run only if
belaran@999 11641 Mercurial's normal pre-update checks determine that the update
belaran@999 11642 or merge can proceed. If the hook succeeds, the update or
belaran@999 11643 merge may proceed; if it fails, the update or merge does not
belaran@999 11644 start.
belaran@999 11645 </para>
belaran@999 11646
belaran@999 11647 <para id="x_2d8">Parameters to this hook:
belaran@999 11648 </para>
belaran@999 11649 <itemizedlist>
belaran@999 11650 <listitem><para id="x_2d9"><literal moreinfo="none">parent1</literal>: A
belaran@999 11651 changeset ID. The ID of the parent that the working
belaran@999 11652 directory is to be updated to. If the working directory
belaran@999 11653 is being merged, it will not change this parent.
belaran@999 11654 </para>
belaran@999 11655 </listitem>
belaran@999 11656 <listitem><para id="x_2da"><literal moreinfo="none">parent2</literal>: A
belaran@999 11657 changeset ID. Only set if the working directory is being
belaran@999 11658 merged. The ID of the revision that the working directory
belaran@999 11659 is being merged with.
belaran@999 11660 </para>
belaran@999 11661 </listitem></itemizedlist>
belaran@999 11662
belaran@999 11663 <para id="x_2db">See also: <literal role="hook" moreinfo="none">update</literal>
belaran@999 11664 (<xref linkend="sec:hook:update"/>)</para>
belaran@999 11665 </sect2>
belaran@999 11666
belaran@999 11667 <sect2 id="sec:hook:tag">
belaran@999 11668 <title><literal role="hook" moreinfo="none">tag</literal>—after tagging a
belaran@999 11669 changeset</title>
belaran@999 11670
belaran@999 11671 <para id="x_2dc">This hook is run after a tag has been created.
belaran@999 11672 </para>
belaran@999 11673
belaran@999 11674 <para id="x_2dd">Parameters to this hook:
belaran@999 11675 </para>
belaran@999 11676 <itemizedlist>
belaran@999 11677 <listitem><para id="x_2de"><literal moreinfo="none">local</literal>: A boolean. Whether
belaran@999 11678 the new tag is local to this repository instance (i.e.
belaran@999 11679 stored in <filename role="special" moreinfo="none">.hg/localtags</filename>) or managed by
belaran@999 11680 Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>).
belaran@999 11681 </para>
belaran@999 11682 </listitem>
belaran@999 11683 <listitem><para id="x_2df"><literal moreinfo="none">node</literal>: A changeset ID. The
belaran@999 11684 ID of the changeset that was tagged.
belaran@999 11685 </para>
belaran@999 11686 </listitem>
belaran@999 11687 <listitem><para id="x_2e0"><literal moreinfo="none">tag</literal>: A string. The name of
belaran@999 11688 the tag that was created.
belaran@999 11689 </para>
belaran@999 11690 </listitem></itemizedlist>
belaran@999 11691
belaran@999 11692 <para id="x_2e1">If the created tag is revision-controlled, the <literal role="hook" moreinfo="none">commit</literal> hook (section <xref linkend="sec:hook:commit"/>) is run before this hook.
belaran@999 11693 </para>
belaran@999 11694
belaran@999 11695 <para id="x_2e2">See also: <literal role="hook" moreinfo="none">pretag</literal>
belaran@999 11696 (<xref linkend="sec:hook:pretag"/>)
belaran@999 11697 </para>
belaran@999 11698 </sect2>
belaran@999 11699
belaran@999 11700 <sect2 id="sec:hook:update">
belaran@999 11701 <title><literal role="hook" moreinfo="none">update</literal>—after
belaran@999 11702 updating or merging working directory</title>
belaran@999 11703
belaran@999 11704 <para id="x_2e3">This hook is run after an update or merge of the working
belaran@999 11705 directory completes. Since a merge can fail (if the external
belaran@999 11706 <command moreinfo="none">hgmerge</command> command fails to resolve conflicts
belaran@999 11707 in a file), this hook communicates whether the update or merge
belaran@999 11708 completed cleanly.
belaran@999 11709 </para>
belaran@999 11710
belaran@999 11711 <itemizedlist>
belaran@999 11712 <listitem><para id="x_2e4"><literal moreinfo="none">error</literal>: A boolean.
belaran@999 11713 Indicates whether the update or merge completed
belaran@999 11714 successfully.
belaran@999 11715 </para>
belaran@999 11716 </listitem>
belaran@999 11717 <listitem><para id="x_2e5"><literal moreinfo="none">parent1</literal>: A changeset ID.
belaran@999 11718 The ID of the parent that the working directory was
belaran@999 11719 updated to. If the working directory was merged, it will
belaran@999 11720 not have changed this parent.
belaran@999 11721 </para>
belaran@999 11722 </listitem>
belaran@999 11723 <listitem><para id="x_2e6"><literal moreinfo="none">parent2</literal>: A changeset ID.
belaran@999 11724 Only set if the working directory was merged. The ID of
belaran@999 11725 the revision that the working directory was merged with.
belaran@999 11726 </para>
belaran@999 11727 </listitem></itemizedlist>
belaran@999 11728
belaran@999 11729 <para id="x_2e7">See also: <literal role="hook" moreinfo="none">preupdate</literal>
belaran@999 11730 (<xref linkend="sec:hook:preupdate"/>)
belaran@999 11731 </para>
belaran@999 11732
belaran@999 11733 </sect2>
belaran@999 11734 </sect1>
belaran@999 11735 </chapter>
belaran@999 11736
belaran@999 11737 <!--
belaran@999 11738 local variables:
belaran@999 11739 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 11740 end:
belaran@999 11741 -->
belaran@999 11742
belaran@999 11743 <!-- BEGIN ch11 -->
belaran@999 11744 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 11745
belaran@999 11746 <chapter id="chap:template">
belaran@999 11747 <?dbhtml filename="customizing-the-output-of-mercurial.html"?>
belaran@999 11748 <title>Customizing the output of Mercurial</title>
belaran@999 11749
belaran@999 11750 <para id="x_578">Mercurial provides a powerful mechanism to let you control how
belaran@999 11751 it displays information. The mechanism is based on templates.
belaran@999 11752 You can use templates to generate specific output for a single
belaran@999 11753 command, or to customize the entire appearance of the built-in web
belaran@999 11754 interface.</para>
belaran@999 11755
belaran@999 11756 <sect1 id="sec:style">
belaran@999 11757 <title>Using precanned output styles</title>
belaran@999 11758
belaran@999 11759 <para id="x_579">Packaged with Mercurial are some output styles that you can
belaran@999 11760 use immediately. A style is simply a precanned template that
belaran@999 11761 someone wrote and installed somewhere that Mercurial can
belaran@999 11762 find.</para>
belaran@999 11763
belaran@999 11764 <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's
belaran@999 11765 review its normal output.</para>
belaran@999 11766
belaran@999 11767 <!-- BEGIN template.simple.normal -->
belaran@999 11768 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput>
belaran@999 11769 changeset: 1:e3d2468ca47c
belaran@999 11770 tag: mytag
belaran@999 11771 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 11772 date: Sun Aug 16 14:05:17 2009 +0000
belaran@999 11773 summary: added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 11774
belaran@999 11775 </screen>
belaran@999 11776 <!-- END template.simple.normal -->
belaran@999 11777
belaran@999 11778
belaran@999 11779 <para id="x_57b">This is somewhat informative, but it takes up a lot of
belaran@999 11780 space—five lines of output per changeset. The
belaran@999 11781 <literal moreinfo="none">compact</literal> style reduces this to three lines,
belaran@999 11782 presented in a sparse manner.</para>
belaran@999 11783
belaran@999 11784 <!-- BEGIN template.simple.compact -->
belaran@999 11785 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
belaran@999 11786 3[tip] d3cc7424d32c 2009-08-16 14:05 +0000 bos
belaran@999 11787 Added tag v0.1 for changeset a5dd5392119b
belaran@999 11788
belaran@999 11789 2[v0.1] a5dd5392119b 2009-08-16 14:05 +0000 bos
belaran@999 11790 Added tag mytag for changeset e3d2468ca47c
belaran@999 11791
belaran@999 11792 1[mytag] e3d2468ca47c 2009-08-16 14:05 +0000 bos
belaran@999 11793 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 11794
belaran@999 11795 0 1cf727e9fc61 2009-08-16 14:05 +0000 bos
belaran@999 11796 added hello
belaran@999 11797
belaran@999 11798 </screen>
belaran@999 11799 <!-- END template.simple.compact -->
belaran@999 11800
belaran@999 11801
belaran@999 11802 <para id="x_57c">The <literal moreinfo="none">changelog</literal> style hints at the
belaran@999 11803 expressive power of Mercurial's templating engine. This style
belaran@999 11804 attempts to follow the GNU Project's changelog
belaran@999 11805 guidelines<citation>web:changelog</citation>.</para>
belaran@999 11806
belaran@999 11807 <!-- BEGIN template.simple.changelog -->
belaran@999 11808 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style changelog</userinput>
belaran@999 11809 2009-08-16 Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 11810
belaran@999 11811 * .hgtags:
belaran@999 11812 Added tag v0.1 for changeset a5dd5392119b
belaran@999 11813 [d3cc7424d32c] [tip]
belaran@999 11814
belaran@999 11815 * .hgtags:
belaran@999 11816 Added tag mytag for changeset e3d2468ca47c
belaran@999 11817 [a5dd5392119b] [v0.1]
belaran@999 11818
belaran@999 11819 * goodbye, hello:
belaran@999 11820 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 11821
belaran@999 11822 in addition, added a file with the helpful name (at least i hope
belaran@999 11823 that some might consider it so) of goodbye.
belaran@999 11824 [e3d2468ca47c] [mytag]
belaran@999 11825
belaran@999 11826 * hello:
belaran@999 11827 added hello
belaran@999 11828 [1cf727e9fc61]
belaran@999 11829
belaran@999 11830 </screen>
belaran@999 11831 <!-- END template.simple.changelog -->
belaran@999 11832
belaran@999 11833
belaran@999 11834 <para id="x_57d">You will not be shocked to learn that Mercurial's default
belaran@999 11835 output style is named <literal moreinfo="none">default</literal>.</para>
belaran@999 11836
belaran@999 11837 <sect2>
belaran@999 11838 <title>Setting a default style</title>
belaran@999 11839
belaran@999 11840 <para id="x_57e">You can modify the output style that Mercurial will use
belaran@999 11841 for every command by editing your <filename role="special" moreinfo="none">~/.hgrc</filename> file, naming the style
belaran@999 11842 you would prefer to use.</para>
belaran@999 11843
belaran@999 11844 <programlisting format="linespecific">[ui]
belaran@999 11845 style = compact</programlisting>
belaran@999 11846
belaran@999 11847 <para id="x_57f">If you write a style of your own, you can use it by either
belaran@999 11848 providing the path to your style file, or copying your style
belaran@999 11849 file into a location where Mercurial can find it (typically
belaran@999 11850 the <literal moreinfo="none">templates</literal> subdirectory of your
belaran@999 11851 Mercurial install directory).</para>
belaran@999 11852 </sect2>
belaran@999 11853 </sect1>
belaran@999 11854
belaran@999 11855 <sect1>
belaran@999 11856 <title>Commands that support styles and templates</title>
belaran@999 11857
belaran@999 11858 <para id="x_580">All of Mercurial's
belaran@999 11859 <quote><literal moreinfo="none">log</literal>-like</quote> commands let you use
belaran@999 11860 styles and templates: <command role="hg-cmd" moreinfo="none">hg
belaran@999 11861 incoming</command>, <command role="hg-cmd" moreinfo="none">hg log</command>,
belaran@999 11862 <command role="hg-cmd" moreinfo="none">hg outgoing</command>, and <command role="hg-cmd" moreinfo="none">hg tip</command>.</para>
belaran@999 11863
belaran@999 11864 <para id="x_581">As I write this manual, these are so far the only commands
belaran@999 11865 that support styles and templates. Since these are the most
belaran@999 11866 important commands that need customizable output, there has been
belaran@999 11867 little pressure from the Mercurial user community to add style
belaran@999 11868 and template support to other commands.</para>
belaran@999 11869 </sect1>
belaran@999 11870
belaran@999 11871 <sect1>
belaran@999 11872 <title>The basics of templating</title>
belaran@999 11873
belaran@999 11874 <para id="x_582">At its simplest, a Mercurial template is a piece of text.
belaran@999 11875 Some of the text never changes, while other parts are
belaran@999 11876 <emphasis>expanded</emphasis>, or replaced with new text, when
belaran@999 11877 necessary.</para>
belaran@999 11878
belaran@999 11879 <para id="x_583">Before we continue, let's look again at a simple example of
belaran@999 11880 Mercurial's normal output.</para>
belaran@999 11881
belaran@999 11882 <!-- BEGIN template.simple.normal -->
belaran@999 11883 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput>
belaran@999 11884 changeset: 1:e3d2468ca47c
belaran@999 11885 tag: mytag
belaran@999 11886 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 11887 date: Sun Aug 16 14:05:17 2009 +0000
belaran@999 11888 summary: added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 11889
belaran@999 11890 </screen>
belaran@999 11891 <!-- END template.simple.normal -->
belaran@999 11892
belaran@999 11893
belaran@999 11894 <para id="x_584">Now, let's run the same command, but using a template to
belaran@999 11895 change its output.</para>
belaran@999 11896
belaran@999 11897 <!-- BEGIN template.simple.simplest -->
belaran@999 11898 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'i saw a changeset\n'</userinput>
belaran@999 11899 i saw a changeset
belaran@999 11900 </screen>
belaran@999 11901 <!-- END template.simple.simplest -->
belaran@999 11902
belaran@999 11903
belaran@999 11904 <para id="x_585">The example above illustrates the simplest possible
belaran@999 11905 template; it's just a piece of static text, printed once for
belaran@999 11906 each changeset. The <option role="hg-opt-log">--template</option> option to the <command role="hg-cmd" moreinfo="none">hg log</command> command tells Mercurial to use
belaran@999 11907 the given text as the template when printing each
belaran@999 11908 changeset.</para>
belaran@999 11909
belaran@999 11910 <para id="x_586">Notice that the template string above ends with the text
belaran@999 11911 <quote><literal moreinfo="none">\n</literal></quote>. This is an
belaran@999 11912 <emphasis>escape sequence</emphasis>, telling Mercurial to print
belaran@999 11913 a newline at the end of each template item. If you omit this
belaran@999 11914 newline, Mercurial will run each piece of output together. See
belaran@999 11915 <xref linkend="sec:template:escape"/> for more details
belaran@999 11916 of escape sequences.</para>
belaran@999 11917
belaran@999 11918 <para id="x_587">A template that prints a fixed string of text all the time
belaran@999 11919 isn't very useful; let's try something a bit more
belaran@999 11920 complex.</para>
belaran@999 11921
belaran@999 11922 <!-- BEGIN template.simple.simplesub -->
belaran@999 11923 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --template 'i saw a changeset: {desc}\n'</userinput>
belaran@999 11924 i saw a changeset: Added tag v0.1 for changeset a5dd5392119b
belaran@999 11925 i saw a changeset: Added tag mytag for changeset e3d2468ca47c
belaran@999 11926 i saw a changeset: added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 11927
belaran@999 11928 in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
belaran@999 11929 i saw a changeset: added hello
belaran@999 11930 </screen>
belaran@999 11931 <!-- END template.simple.simplesub -->
belaran@999 11932
belaran@999 11933
belaran@999 11934 <para id="x_588">As you can see, the string
belaran@999 11935 <quote><literal moreinfo="none">{desc}</literal></quote> in the template has
belaran@999 11936 been replaced in the output with the description of each
belaran@999 11937 changeset. Every time Mercurial finds text enclosed in curly
belaran@999 11938 braces (<quote><literal moreinfo="none">{</literal></quote> and
belaran@999 11939 <quote><literal moreinfo="none">}</literal></quote>), it will try to replace the
belaran@999 11940 braces and text with the expansion of whatever is inside. To
belaran@999 11941 print a literal curly brace, you must escape it, as described in
belaran@999 11942 <xref linkend="sec:template:escape"/>.</para>
belaran@999 11943 </sect1>
belaran@999 11944
belaran@999 11945 <sect1 id="sec:template:keyword">
belaran@999 11946 <title>Common template keywords</title>
belaran@999 11947
belaran@999 11948 <para id="x_589">You can start writing simple templates immediately using the
belaran@999 11949 keywords below.</para>
belaran@999 11950
belaran@999 11951 <itemizedlist>
belaran@999 11952 <listitem><para id="x_58a"><literal role="template-keyword" moreinfo="none">author</literal>: String. The
belaran@999 11953 unmodified author of the changeset.</para>
belaran@999 11954 </listitem>
belaran@999 11955 <listitem><para id="x_58b"><literal role="template-keyword" moreinfo="none">branches</literal>: String. The
belaran@999 11956 name of the branch on which the changeset was committed.
belaran@999 11957 Will be empty if the branch name was
belaran@999 11958 <literal moreinfo="none">default</literal>.</para>
belaran@999 11959 </listitem>
belaran@999 11960 <listitem><para id="x_58c"><literal role="template-keyword" moreinfo="none">date</literal>:
belaran@999 11961 Date information. The date when the changeset was
belaran@999 11962 committed. This is <emphasis>not</emphasis> human-readable;
belaran@999 11963 you must pass it through a filter that will render it
belaran@999 11964 appropriately. See <xref linkend="sec:template:filter"/> for more information
belaran@999 11965 on filters. The date is expressed as a pair of numbers. The
belaran@999 11966 first number is a Unix UTC timestamp (seconds since January
belaran@999 11967 1, 1970); the second is the offset of the committer's
belaran@999 11968 timezone from UTC, in seconds.</para>
belaran@999 11969 </listitem>
belaran@999 11970 <listitem><para id="x_58d"><literal role="template-keyword" moreinfo="none">desc</literal>:
belaran@999 11971 String. The text of the changeset description.</para>
belaran@999 11972 </listitem>
belaran@999 11973 <listitem><para id="x_58e"><literal role="template-keyword" moreinfo="none">files</literal>: List of strings.
belaran@999 11974 All files modified, added, or removed by this
belaran@999 11975 changeset.</para>
belaran@999 11976 </listitem>
belaran@999 11977 <listitem><para id="x_58f"><literal role="template-keyword" moreinfo="none">file_adds</literal>: List of
belaran@999 11978 strings. Files added by this changeset.</para>
belaran@999 11979 </listitem>
belaran@999 11980 <listitem><para id="x_590"><literal role="template-keyword" moreinfo="none">file_dels</literal>: List of
belaran@999 11981 strings. Files removed by this changeset.</para>
belaran@999 11982 </listitem>
belaran@999 11983 <listitem><para id="x_591"><literal role="template-keyword" moreinfo="none">node</literal>:
belaran@999 11984 String. The changeset identification hash, as a
belaran@999 11985 40-character hexadecimal string.</para>
belaran@999 11986 </listitem>
belaran@999 11987 <listitem><para id="x_592"><literal role="template-keyword" moreinfo="none">parents</literal>: List of
belaran@999 11988 strings. The parents of the changeset.</para>
belaran@999 11989 </listitem>
belaran@999 11990 <listitem><para id="x_593"><literal role="template-keyword" moreinfo="none">rev</literal>:
belaran@999 11991 Integer. The repository-local changeset revision
belaran@999 11992 number.</para>
belaran@999 11993 </listitem>
belaran@999 11994 <listitem><para id="x_594"><literal role="template-keyword" moreinfo="none">tags</literal>:
belaran@999 11995 List of strings. Any tags associated with the
belaran@999 11996 changeset.</para>
belaran@999 11997 </listitem>
belaran@999 11998 </itemizedlist>
belaran@999 11999
belaran@999 12000 <para id="x_595">A few simple experiments will show us what to expect when we
belaran@999 12001 use these keywords; you can see the results below.</para>
belaran@999 12002
belaran@999 12003 <!-- BEGIN template.simple.keywords -->
belaran@999 12004 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'author: {author}\n'</userinput>
belaran@999 12005 author: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 12006 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'desc:\n{desc}\n'</userinput>
belaran@999 12007 desc:
belaran@999 12008 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12009
belaran@999 12010 in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
belaran@999 12011 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'files: {files}\n'</userinput>
belaran@999 12012 files: goodbye hello
belaran@999 12013 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_adds: {file_adds}\n'</userinput>
belaran@999 12014 file_adds: goodbye
belaran@999 12015 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_dels: {file_dels}\n'</userinput>
belaran@999 12016 file_dels:
belaran@999 12017 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'node: {node}\n'</userinput>
belaran@999 12018 node: e3d2468ca47c10bdfbbb41b367a0c84509862197
belaran@999 12019 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'parents: {parents}\n'</userinput>
belaran@999 12020 parents:
belaran@999 12021 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'rev: {rev}\n'</userinput>
belaran@999 12022 rev: 1
belaran@999 12023 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'tags: {tags}\n'</userinput>
belaran@999 12024 tags: mytag
belaran@999 12025 </screen>
belaran@999 12026 <!-- END template.simple.keywords -->
belaran@999 12027
belaran@999 12028
belaran@999 12029 <para id="x_596">As we noted above, the date keyword does not produce
belaran@999 12030 human-readable output, so we must treat it specially. This
belaran@999 12031 involves using a <emphasis>filter</emphasis>, about which more
belaran@999 12032 in <xref linkend="sec:template:filter"/>.</para>
belaran@999 12033
belaran@999 12034 <!-- BEGIN template.simple.datekeyword -->
belaran@999 12035 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date}\n'</userinput>
belaran@999 12036 date: 1250431517.00
belaran@999 12037 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date|isodate}\n'</userinput>
belaran@999 12038 date: 2009-08-16 14:05 +0000
belaran@999 12039 </screen>
belaran@999 12040 <!-- END template.simple.datekeyword -->
belaran@999 12041
belaran@999 12042 </sect1>
belaran@999 12043
belaran@999 12044 <sect1 id="sec:template:escape">
belaran@999 12045 <title>Escape sequences</title>
belaran@999 12046
belaran@999 12047 <para id="x_597">Mercurial's templating engine recognises the most commonly
belaran@999 12048 used escape sequences in strings. When it sees a backslash
belaran@999 12049 (<quote><literal moreinfo="none">\</literal></quote>) character, it looks at the
belaran@999 12050 following character and substitutes the two characters with a
belaran@999 12051 single replacement, as described below.</para>
belaran@999 12052
belaran@999 12053 <itemizedlist>
belaran@999 12054 <listitem><para id="x_598"><literal moreinfo="none">\</literal>:
belaran@999 12055 Backslash, <quote><literal moreinfo="none">\</literal></quote>, ASCII
belaran@999 12056 134.</para>
belaran@999 12057 </listitem>
belaran@999 12058 <listitem><para id="x_599"><literal moreinfo="none">\n</literal>: Newline,
belaran@999 12059 ASCII 12.</para>
belaran@999 12060 </listitem>
belaran@999 12061 <listitem><para id="x_59a"><literal moreinfo="none">\r</literal>: Carriage
belaran@999 12062 return, ASCII 15.</para>
belaran@999 12063 </listitem>
belaran@999 12064 <listitem><para id="x_59b"><literal moreinfo="none">\t</literal>: Tab, ASCII
belaran@999 12065 11.</para>
belaran@999 12066 </listitem>
belaran@999 12067 <listitem><para id="x_59c"><literal moreinfo="none">\v</literal>: Vertical
belaran@999 12068 tab, ASCII 13.</para>
belaran@999 12069 </listitem>
belaran@999 12070 <listitem><para id="x_59d"><literal moreinfo="none">\{</literal>: Open curly
belaran@999 12071 brace, <quote><literal moreinfo="none">{</literal></quote>, ASCII
belaran@999 12072 173.</para>
belaran@999 12073 </listitem>
belaran@999 12074 <listitem><para id="x_59e"><literal moreinfo="none">\}</literal>: Close curly
belaran@999 12075 brace, <quote><literal moreinfo="none">}</literal></quote>, ASCII
belaran@999 12076 175.</para>
belaran@999 12077 </listitem></itemizedlist>
belaran@999 12078
belaran@999 12079 <para id="x_59f">As indicated above, if you want the expansion of a template
belaran@999 12080 to contain a literal <quote><literal moreinfo="none">\</literal></quote>,
belaran@999 12081 <quote><literal moreinfo="none">{</literal></quote>, or
belaran@999 12082 <quote><literal moreinfo="none">{</literal></quote> character, you must escape
belaran@999 12083 it.</para>
belaran@999 12084 </sect1>
belaran@999 12085
belaran@999 12086 <sect1 id="sec:template:filter">
belaran@999 12087 <title>Filtering keywords to change their results</title>
belaran@999 12088
belaran@999 12089 <para id="x_5a0">Some of the results of template expansion are not
belaran@999 12090 immediately easy to use. Mercurial lets you specify an optional
belaran@999 12091 chain of <emphasis>filters</emphasis> to modify the result of
belaran@999 12092 expanding a keyword. You have already seen a common filter,
belaran@999 12093 <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>, in
belaran@999 12094 action above, to make a date readable.</para>
belaran@999 12095
belaran@999 12096 <para id="x_5a1">Below is a list of the most commonly used filters that
belaran@999 12097 Mercurial supports. While some filters can be applied to any
belaran@999 12098 text, others can only be used in specific circumstances. The
belaran@999 12099 name of each filter is followed first by an indication of where
belaran@999 12100 it can be used, then a description of its effect.</para>
belaran@999 12101
belaran@999 12102 <itemizedlist>
belaran@999 12103 <listitem><para id="x_5a2"><literal role="template-filter" moreinfo="none">addbreaks</literal>: Any text. Add
belaran@999 12104 an XHTML <quote><literal moreinfo="none">&lt;br/&gt;</literal></quote> tag
belaran@999 12105 before the end of every line except the last. For example,
belaran@999 12106 <quote><literal moreinfo="none">foo\nbar</literal></quote> becomes
belaran@999 12107 <quote><literal moreinfo="none">foo&lt;br/&gt;\nbar</literal></quote>.</para>
belaran@999 12108 </listitem>
belaran@999 12109 <listitem><para id="x_5a3"><literal role="template-kw-filt-date" moreinfo="none">age</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render
belaran@999 12110 the age of the date, relative to the current time. Yields a
belaran@999 12111 string like <quote><literal moreinfo="none">10
belaran@999 12112 minutes</literal></quote>.</para>
belaran@999 12113 </listitem>
belaran@999 12114 <listitem><para id="x_5a4"><literal role="template-filter" moreinfo="none">basename</literal>: Any text, but
belaran@999 12115 most useful for the <literal role="template-keyword" moreinfo="none">files</literal> keyword and its
belaran@999 12116 relatives. Treat the text as a path, and return the
belaran@999 12117 basename. For example,
belaran@999 12118 <quote><literal moreinfo="none">foo/bar/baz</literal></quote> becomes
belaran@999 12119 <quote><literal moreinfo="none">baz</literal></quote>.</para>
belaran@999 12120 </listitem>
belaran@999 12121 <listitem><para id="x_5a5"><literal role="template-kw-filt-date" moreinfo="none">date</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render a
belaran@999 12122 date in a similar format to the Unix <literal role="template-keyword" moreinfo="none">date</literal> command, but with
belaran@999 12123 timezone included. Yields a string like <quote><literal moreinfo="none">Mon
belaran@999 12124 Sep 04 15:13:13 2006 -0700</literal></quote>.</para>
belaran@999 12125 </listitem>
belaran@999 12126 <listitem><para id="x_5a6"><literal role="template-kw-filt-author" moreinfo="none">domain</literal>: Any text,
belaran@999 12127 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Finds
belaran@999 12128 the first string that looks like an email address, and
belaran@999 12129 extract just the domain component. For example,
belaran@999 12130 <quote><literal moreinfo="none">Bryan O'Sullivan
belaran@999 12131 &lt;bos@serpentine.com&gt;</literal></quote> becomes
belaran@999 12132 <quote><literal moreinfo="none">serpentine.com</literal></quote>.</para>
belaran@999 12133 </listitem>
belaran@999 12134 <listitem><para id="x_5a7"><literal role="template-kw-filt-author" moreinfo="none">email</literal>: Any text,
belaran@999 12135 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Extract
belaran@999 12136 the first string that looks like an email address. For
belaran@999 12137 example, <quote><literal moreinfo="none">Bryan O'Sullivan
belaran@999 12138 &lt;bos@serpentine.com&gt;</literal></quote> becomes
belaran@999 12139 <quote><literal moreinfo="none">bos@serpentine.com</literal></quote>.</para>
belaran@999 12140 </listitem>
belaran@999 12141 <listitem><para id="x_5a8"><literal role="template-filter" moreinfo="none">escape</literal>: Any text.
belaran@999 12142 Replace the special XML/XHTML characters
belaran@999 12143 <quote><literal moreinfo="none">&amp;</literal></quote>,
belaran@999 12144 <quote><literal moreinfo="none">&lt;</literal></quote> and
belaran@999 12145 <quote><literal moreinfo="none">&gt;</literal></quote> with XML
belaran@999 12146 entities.</para>
belaran@999 12147 </listitem>
belaran@999 12148 <listitem><para id="x_5a9"><literal role="template-filter" moreinfo="none">fill68</literal>: Any text. Wrap
belaran@999 12149 the text to fit in 68 columns. This is useful before you
belaran@999 12150 pass text through the <literal role="template-filter" moreinfo="none">tabindent</literal> filter, and
belaran@999 12151 still want it to fit in an 80-column fixed-font
belaran@999 12152 window.</para>
belaran@999 12153 </listitem>
belaran@999 12154 <listitem><para id="x_5aa"><literal role="template-filter" moreinfo="none">fill76</literal>: Any text. Wrap
belaran@999 12155 the text to fit in 76 columns.</para>
belaran@999 12156 </listitem>
belaran@999 12157 <listitem><para id="x_5ab"><literal role="template-filter" moreinfo="none">firstline</literal>: Any text.
belaran@999 12158 Yield the first line of text, without any trailing
belaran@999 12159 newlines.</para>
belaran@999 12160 </listitem>
belaran@999 12161 <listitem><para id="x_5ac"><literal role="template-kw-filt-date" moreinfo="none">hgdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render
belaran@999 12162 the date as a pair of readable numbers. Yields a string
belaran@999 12163 like <quote><literal moreinfo="none">1157407993
belaran@999 12164 25200</literal></quote>.</para>
belaran@999 12165 </listitem>
belaran@999 12166 <listitem><para id="x_5ad"><literal role="template-kw-filt-date" moreinfo="none">isodate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render
belaran@999 12167 the date as a text string in ISO 8601 format. Yields a
belaran@999 12168 string like <quote><literal moreinfo="none">2006-09-04 15:13:13
belaran@999 12169 -0700</literal></quote>.</para>
belaran@999 12170 </listitem>
belaran@999 12171 <listitem><para id="x_5ae"><literal role="template-filter" moreinfo="none">obfuscate</literal>: Any text, but
belaran@999 12172 most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield
belaran@999 12173 the input text rendered as a sequence of XML entities. This
belaran@999 12174 helps to defeat some particularly stupid screen-scraping
belaran@999 12175 email harvesting spambots.</para>
belaran@999 12176 </listitem>
belaran@999 12177 <listitem><para id="x_5af"><literal role="template-kw-filt-author" moreinfo="none">person</literal>: Any text,
belaran@999 12178 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield
belaran@999 12179 the text before an email address. For example,
belaran@999 12180 <quote><literal moreinfo="none">Bryan O'Sullivan
belaran@999 12181 &lt;bos@serpentine.com&gt;</literal></quote> becomes
belaran@999 12182 <quote><literal moreinfo="none">Bryan O'Sullivan</literal></quote>.</para>
belaran@999 12183 </listitem>
belaran@999 12184 <listitem><para id="x_5b0"><literal role="template-kw-filt-date" moreinfo="none">rfc822date</literal>:
belaran@999 12185 <literal role="template-keyword" moreinfo="none">date</literal> keyword.
belaran@999 12186 Render a date using the same format used in email headers.
belaran@999 12187 Yields a string like <quote><literal moreinfo="none">Mon, 04 Sep 2006
belaran@999 12188 15:13:13 -0700</literal></quote>.</para>
belaran@999 12189 </listitem>
belaran@999 12190 <listitem><para id="x_5b1"><literal role="template-kw-filt-node" moreinfo="none">short</literal>: Changeset
belaran@999 12191 hash. Yield the short form of a changeset hash, i.e. a
belaran@999 12192 12-character hexadecimal string.</para>
belaran@999 12193 </listitem>
belaran@999 12194 <listitem><para id="x_5b2"><literal role="template-kw-filt-date" moreinfo="none">shortdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render
belaran@999 12195 the year, month, and day of the date. Yields a string like
belaran@999 12196 <quote><literal moreinfo="none">2006-09-04</literal></quote>.</para>
belaran@999 12197 </listitem>
belaran@999 12198 <listitem><para id="x_5b3"><literal role="template-filter" moreinfo="none">strip</literal>:
belaran@999 12199 Any text. Strip all leading and trailing whitespace from
belaran@999 12200 the string.</para>
belaran@999 12201 </listitem>
belaran@999 12202 <listitem><para id="x_5b4"><literal role="template-filter" moreinfo="none">tabindent</literal>: Any text.
belaran@999 12203 Yield the text, with every line except the first starting
belaran@999 12204 with a tab character.</para>
belaran@999 12205 </listitem>
belaran@999 12206 <listitem><para id="x_5b5"><literal role="template-filter" moreinfo="none">urlescape</literal>: Any text.
belaran@999 12207 Escape all characters that are considered
belaran@999 12208 <quote>special</quote> by URL parsers. For example,
belaran@999 12209 <literal moreinfo="none">foo bar</literal> becomes
belaran@999 12210 <literal moreinfo="none">foo%20bar</literal>.</para>
belaran@999 12211 </listitem>
belaran@999 12212 <listitem><para id="x_5b6"><literal role="template-kw-filt-author" moreinfo="none">user</literal>: Any text,
belaran@999 12213 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Return
belaran@999 12214 the <quote>user</quote> portion of an email address. For
belaran@999 12215 example, <quote><literal moreinfo="none">Bryan O'Sullivan
belaran@999 12216 &lt;bos@serpentine.com&gt;</literal></quote> becomes
belaran@999 12217 <quote><literal moreinfo="none">bos</literal></quote>.</para>
belaran@999 12218 </listitem>
belaran@999 12219 </itemizedlist>
belaran@999 12220
belaran@999 12221 <!-- BEGIN template.simple.manyfilters -->
belaran@999 12222 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author}\n'</userinput>
belaran@999 12223 Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 12224 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|domain}\n'</userinput>
belaran@999 12225 serpentine.com
belaran@999 12226 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|email}\n'</userinput>
belaran@999 12227 bos@serpentine.com
belaran@999 12228 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</userinput>
belaran@999 12229 &amp;#66;&amp;#114;&amp;#121;&amp;#97;&amp;#110;&amp;#32;&amp;#79;&amp;#39;&amp;#83;&amp;#117;&amp;#108;&amp;#108;&amp;#105;&amp;#11
belaran@999 12230 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|person}\n'</userinput>
belaran@999 12231 Bryan O'Sullivan
belaran@999 12232 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|user}\n'</userinput>
belaran@999 12233 bos
belaran@999 12234 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</userinput>
belaran@999 12235 looks almost right, but actually garbage: 1250431517.00
belaran@999 12236 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|age}\n'</userinput>
belaran@999 12237 3 seconds
belaran@999 12238 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|date}\n'</userinput>
belaran@999 12239 Sun Aug 16 14:05:17 2009 +0000
belaran@999 12240 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|hgdate}\n'</userinput>
belaran@999 12241 1250431517 0
belaran@999 12242 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|isodate}\n'</userinput>
belaran@999 12243 2009-08-16 14:05 +0000
belaran@999 12244 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|rfc822date}\n'</userinput>
belaran@999 12245 Sun, 16 Aug 2009 14:05:17 +0000
belaran@999 12246 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|shortdate}\n'</userinput>
belaran@999 12247 2009-08-16
belaran@999 12248 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc}\n' | cut -c-76</userinput>
belaran@999 12249 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12250
belaran@999 12251 in addition, added a file with the helpful name (at least i hope that some m
belaran@999 12252 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</userinput>
belaran@999 12253 added line to end of &lt;&lt;hello&gt;&gt; file.&lt;br/&gt;
belaran@999 12254 &lt;br/&gt;
belaran@999 12255 in addition, added a file with the helpful name (at least i hope that some m
belaran@999 12256 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|escape}\n' | cut -c-76</userinput>
belaran@999 12257 added line to end of &amp;lt;&amp;lt;hello&amp;gt;&amp;gt; file.
belaran@999 12258
belaran@999 12259 in addition, added a file with the helpful name (at least i hope that some m
belaran@999 12260 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill68}\n'</userinput>
belaran@999 12261 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12262
belaran@999 12263 in addition, added a file with the helpful name (at least i hope
belaran@999 12264 that some might consider it so) of goodbye.
belaran@999 12265 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill76}\n'</userinput>
belaran@999 12266 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12267
belaran@999 12268 in addition, added a file with the helpful name (at least i hope that some
belaran@999 12269 might consider it so) of goodbye.
belaran@999 12270 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|firstline}\n'</userinput>
belaran@999 12271 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12272 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|strip}\n' | cut -c-76</userinput>
belaran@999 12273 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12274
belaran@999 12275 in addition, added a file with the helpful name (at least i hope that some m
belaran@999 12276 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</userinput>
belaran@999 12277 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12278
belaran@999 12279 in addition, added a file with the helpful name (at least i hope tha
belaran@999 12280 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node}\n'</userinput>
belaran@999 12281 e3d2468ca47c10bdfbbb41b367a0c84509862197
belaran@999 12282 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node|short}\n'</userinput>
belaran@999 12283 e3d2468ca47c
belaran@999 12284 </screen>
belaran@999 12285 <!-- END template.simple.manyfilters -->
belaran@999 12286
belaran@999 12287
belaran@999 12288 <note>
belaran@999 12289 <para id="x_5b7"> If you try to apply a filter to a piece of data that it
belaran@999 12290 cannot process, Mercurial will fail and print a Python
belaran@999 12291 exception. For example, trying to run the output of the
belaran@999 12292 <literal role="template-keyword" moreinfo="none">desc</literal> keyword into
belaran@999 12293 the <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>
belaran@999 12294 filter is not a good idea.</para>
belaran@999 12295 </note>
belaran@999 12296
belaran@999 12297 <sect2>
belaran@999 12298 <title>Combining filters</title>
belaran@999 12299
belaran@999 12300 <para id="x_5b8">It is easy to combine filters to yield output in the form
belaran@999 12301 you would like. The following chain of filters tidies up a
belaran@999 12302 description, then makes sure that it fits cleanly into 68
belaran@999 12303 columns, then indents it by a further 8 characters (at least
belaran@999 12304 on Unix-like systems, where a tab is conventionally 8
belaran@999 12305 characters wide).</para>
belaran@999 12306
belaran@999 12307 <!-- BEGIN template.simple.combine -->
belaran@999 12308 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</userinput>
belaran@999 12309 description:
belaran@999 12310 added line to end of &lt;&lt;hello&gt;&gt; file.
belaran@999 12311
belaran@999 12312 in addition, added a file with the helpful name (at least i hope
belaran@999 12313 that some might consider it so) of goodbye.
belaran@999 12314 </screen>
belaran@999 12315 <!-- END template.simple.combine -->
belaran@999 12316
belaran@999 12317
belaran@999 12318 <para id="x_5b9">Note the use of <quote><literal moreinfo="none">\t</literal></quote> (a
belaran@999 12319 tab character) in the template to force the first line to be
belaran@999 12320 indented; this is necessary since <literal role="template-keyword" moreinfo="none">tabindent</literal> indents all
belaran@999 12321 lines <emphasis>except</emphasis> the first.</para>
belaran@999 12322
belaran@999 12323 <para id="x_5ba">Keep in mind that the order of filters in a chain is
belaran@999 12324 significant. The first filter is applied to the result of the
belaran@999 12325 keyword; the second to the result of the first filter; and so
belaran@999 12326 on. For example, using <literal moreinfo="none">fill68|tabindent</literal>
belaran@999 12327 gives very different results from
belaran@999 12328 <literal moreinfo="none">tabindent|fill68</literal>.</para>
belaran@999 12329 </sect2>
belaran@999 12330 </sect1>
belaran@999 12331
belaran@999 12332 <sect1>
belaran@999 12333 <title>From templates to styles</title>
belaran@999 12334
belaran@999 12335 <para id="x_5bb">A command line template provides a quick and simple way to
belaran@999 12336 format some output. Templates can become verbose, though, and
belaran@999 12337 it's useful to be able to give a template a name. A style file
belaran@999 12338 is a template with a name, stored in a file.</para>
belaran@999 12339
belaran@999 12340 <para id="x_5bc">More than that, using a style file unlocks the power of
belaran@999 12341 Mercurial's templating engine in ways that are not possible
belaran@999 12342 using the command line <option role="hg-opt-log">--template</option> option.</para>
belaran@999 12343
belaran@999 12344 <sect2>
belaran@999 12345 <title>The simplest of style files</title>
belaran@999 12346
belaran@999 12347 <para id="x_5bd">Our simple style file contains just one line:</para>
belaran@999 12348
belaran@999 12349 <!-- BEGIN template.simple.rev -->
belaran@999 12350 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'changeset = "rev: {rev}\n"' &gt; rev</userinput>
belaran@999 12351 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -l1 --style ./rev</userinput>
belaran@999 12352 rev: 3
belaran@999 12353 </screen>
belaran@999 12354 <!-- END template.simple.rev -->
belaran@999 12355
belaran@999 12356
belaran@999 12357 <para id="x_5be">This tells Mercurial, <quote>if you're printing a
belaran@999 12358 changeset, use the text on the right as the
belaran@999 12359 template</quote>.</para>
belaran@999 12360 </sect2>
belaran@999 12361
belaran@999 12362 <sect2>
belaran@999 12363 <title>Style file syntax</title>
belaran@999 12364
belaran@999 12365 <para id="x_5bf">The syntax rules for a style file are simple.</para>
belaran@999 12366
belaran@999 12367 <itemizedlist>
belaran@999 12368 <listitem><para id="x_5c0">The file is processed one line at a
belaran@999 12369 time.</para>
belaran@999 12370 </listitem>
belaran@999 12371 <listitem><para id="x_5c1">Leading and trailing white space are
belaran@999 12372 ignored.</para>
belaran@999 12373 </listitem>
belaran@999 12374 <listitem><para id="x_5c2">Empty lines are skipped.</para>
belaran@999 12375 </listitem>
belaran@999 12376 <listitem><para id="x_5c3">If a line starts with either of the characters
belaran@999 12377 <quote><literal moreinfo="none">#</literal></quote> or
belaran@999 12378 <quote><literal moreinfo="none">;</literal></quote>, the entire line is
belaran@999 12379 treated as a comment, and skipped as if empty.</para>
belaran@999 12380 </listitem>
belaran@999 12381 <listitem><para id="x_5c4">A line starts with a keyword. This must start
belaran@999 12382 with an alphabetic character or underscore, and can
belaran@999 12383 subsequently contain any alphanumeric character or
belaran@999 12384 underscore. (In regexp notation, a keyword must match
belaran@999 12385 <literal moreinfo="none">[A-Za-z_][A-Za-z0-9_]*</literal>.)</para>
belaran@999 12386 </listitem>
belaran@999 12387 <listitem><para id="x_5c5">The next element must be an
belaran@999 12388 <quote><literal moreinfo="none">=</literal></quote> character, which can
belaran@999 12389 be preceded or followed by an arbitrary amount of white
belaran@999 12390 space.</para>
belaran@999 12391 </listitem>
belaran@999 12392 <listitem><para id="x_5c6">If the rest of the line starts and ends with
belaran@999 12393 matching quote characters (either single or double quote),
belaran@999 12394 it is treated as a template body.</para>
belaran@999 12395 </listitem>
belaran@999 12396 <listitem><para id="x_5c7">If the rest of the line <emphasis>does
belaran@999 12397 not</emphasis> start with a quote character, it is
belaran@999 12398 treated as the name of a file; the contents of this file
belaran@999 12399 will be read and used as a template body.</para>
belaran@999 12400 </listitem></itemizedlist>
belaran@999 12401 </sect2>
belaran@999 12402 </sect1>
belaran@999 12403
belaran@999 12404 <sect1>
belaran@999 12405 <title>Style files by example</title>
belaran@999 12406
belaran@999 12407 <para id="x_5c8">To illustrate how to write a style file, we will construct a
belaran@999 12408 few by example. Rather than provide a complete style file and
belaran@999 12409 walk through it, we'll mirror the usual process of developing a
belaran@999 12410 style file by starting with something very simple, and walking
belaran@999 12411 through a series of successively more complete examples.</para>
belaran@999 12412
belaran@999 12413 <sect2>
belaran@999 12414 <title>Identifying mistakes in style files</title>
belaran@999 12415
belaran@999 12416 <para id="x_5c9">If Mercurial encounters a problem in a style file you are
belaran@999 12417 working on, it prints a terse error message that, once you
belaran@999 12418 figure out what it means, is actually quite useful.</para>
belaran@999 12419
belaran@999 12420 <!-- BEGIN template.svnstyle.syntax.input -->
belaran@999 12421 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat broken.style</userinput>
belaran@999 12422 changeset =
belaran@999 12423 </screen>
belaran@999 12424 <!-- END template.svnstyle.syntax.input -->
belaran@999 12425
belaran@999 12426
belaran@999 12427 <para id="x_5ca">Notice that <filename moreinfo="none">broken.style</filename> attempts to
belaran@999 12428 define a <literal moreinfo="none">changeset</literal> keyword, but forgets to
belaran@999 12429 give any content for it. When instructed to use this style
belaran@999 12430 file, Mercurial promptly complains.</para>
belaran@999 12431
belaran@999 12432 <!-- BEGIN template.svnstyle.syntax.error -->
belaran@999 12433 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --style broken.style</userinput>
belaran@999 12434 abort: broken.style:1: parse error
belaran@999 12435 </screen>
belaran@999 12436 <!-- END template.svnstyle.syntax.error -->
belaran@999 12437
belaran@999 12438
belaran@999 12439 <para id="x_5cb">This error message looks intimidating, but it is not too
belaran@999 12440 hard to follow.</para>
belaran@999 12441
belaran@999 12442 <itemizedlist>
belaran@999 12443 <listitem><para id="x_5cc">The first component is simply Mercurial's way
belaran@999 12444 of saying <quote>I am giving up</quote>.</para>
belaran@999 12445 <programlisting format="linespecific">___abort___: broken.style:1: parse error</programlisting>
belaran@999 12446 </listitem>
belaran@999 12447 <listitem><para id="x_5cd">Next comes the name of the style file that
belaran@999 12448 contains the error.</para>
belaran@999 12449 <programlisting format="linespecific">abort: ___broken.style___:1: parse error</programlisting>
belaran@999 12450 </listitem>
belaran@999 12451 <listitem><para id="x_5ce">Following the file name is the line number
belaran@999 12452 where the error was encountered.</para>
belaran@999 12453 <programlisting format="linespecific">abort: broken.style:___1___: parse error</programlisting>
belaran@999 12454 </listitem>
belaran@999 12455 <listitem><para id="x_5cf">Finally, a description of what went
belaran@999 12456 wrong.</para>
belaran@999 12457 <programlisting format="linespecific">abort: broken.style:1: ___parse error___</programlisting>
belaran@999 12458 </listitem>
belaran@999 12459 <listitem><para id="x_5d0">The description of the problem is not always
belaran@999 12460 clear (as in this case), but even when it is cryptic, it
belaran@999 12461 is almost always trivial to visually inspect the offending
belaran@999 12462 line in the style file and see what is wrong.</para>
belaran@999 12463 </listitem>
belaran@999 12464 </itemizedlist>
belaran@999 12465 </sect2>
belaran@999 12466
belaran@999 12467 <sect2>
belaran@999 12468 <title>Uniquely identifying a repository</title>
belaran@999 12469
belaran@999 12470 <para id="x_5d1">If you would like to be able to identify a Mercurial
belaran@999 12471 repository <quote>fairly uniquely</quote> using a short string
belaran@999 12472 as an identifier, you can use the first revision in the
belaran@999 12473 repository.</para>
belaran@999 12474
belaran@999 12475 <!-- BEGIN template.svnstyle.id -->
belaran@999 12476 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r0 --template '{node}'</userinput>
belaran@999 12477 02b4f9d8a52a6da645e20fa7df0accc8aa33b650</screen>
belaran@999 12478 <!-- END template.svnstyle.id -->
belaran@999 12479
belaran@999 12480
belaran@999 12481 <para id="x_5d2">This is likely to be unique, and so it is
belaran@999 12482 useful in many cases. There are a few caveats.</para>
belaran@999 12483 <itemizedlist>
belaran@999 12484 <listitem><para id="x_5d3">It will not work in a completely empty
belaran@999 12485 repository, because such a repository does not have a
belaran@999 12486 revision zero.</para>
belaran@999 12487 </listitem>
belaran@999 12488 <listitem><para id="x_5d4">Neither will it work in the (extremely rare)
belaran@999 12489 case where a repository is a merge of two or more formerly
belaran@999 12490 independent repositories, and you still have those
belaran@999 12491 repositories around.</para>
belaran@999 12492 </listitem></itemizedlist>
belaran@999 12493 <para id="x_5d5">Here are some uses to which you could put this
belaran@999 12494 identifier:</para>
belaran@999 12495 <itemizedlist>
belaran@999 12496 <listitem><para id="x_5d6">As a key into a table for a database that
belaran@999 12497 manages repositories on a server.</para>
belaran@999 12498 </listitem>
belaran@999 12499 <listitem><para id="x_5d7">As half of a {<emphasis>repository
belaran@999 12500 ID</emphasis>, <emphasis>revision ID</emphasis>} tuple.
belaran@999 12501 Save this information away when you run an automated build
belaran@999 12502 or other activity, so that you can <quote>replay</quote>
belaran@999 12503 the build later if necessary.</para>
belaran@999 12504 </listitem>
belaran@999 12505 </itemizedlist>
belaran@999 12506 </sect2>
belaran@999 12507
belaran@999 12508 <sect2>
belaran@999 12509 <title>Listing files on multiple lines</title>
belaran@999 12510
belaran@999 12511 <para id="x_714">Suppose we want to list the files changed by a changeset,
belaran@999 12512 one per line, with a little indentation before each file
belaran@999 12513 name.</para>
belaran@999 12514
belaran@999 12515 <!-- BEGIN ch10/multiline.go -->
belaran@999 12516 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; multiline &lt;&lt; EOF</userinput>
belaran@999 12517 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">changeset = "Changed in {node|short}:\n{files}"</userinput>
belaran@999 12518 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">file = " {file}\n"</userinput>
belaran@999 12519 <prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
belaran@999 12520 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style multiline</userinput>
belaran@999 12521 Changed in badb58085712:
belaran@999 12522 .bashrc
belaran@999 12523 .hgrc
belaran@999 12524 test.c
belaran@999 12525 </screen>
belaran@999 12526 <!-- END ch10/multiline.go -->
belaran@999 12527
belaran@999 12528 </sect2>
belaran@999 12529
belaran@999 12530 <sect2>
belaran@999 12531 <title>Mimicking Subversion's output</title>
belaran@999 12532
belaran@999 12533 <para id="x_5d8">Let's try to emulate the default output format used by
belaran@999 12534 another revision control tool, Subversion.</para>
belaran@999 12535
belaran@999 12536 <!-- BEGIN template.svnstyle.short -->
belaran@999 12537 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svn log -r9653</userinput>
belaran@999 12538 ------------------------------------------------------------------------
belaran@999 12539 r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
belaran@999 12540
belaran@999 12541 On reporting a route error, also include the status for the error,
belaran@999 12542 rather than indicating a status of 0 when an error has occurred.
belaran@999 12543
belaran@999 12544 Signed-off-by: Sean Hefty &lt;sean.hefty@intel.com&gt;
belaran@999 12545
belaran@999 12546 ------------------------------------------------------------------------
belaran@999 12547 </screen>
belaran@999 12548 <!-- END template.svnstyle.short -->
belaran@999 12549
belaran@999 12550
belaran@999 12551 <para id="x_5d9">Since Subversion's output style is fairly simple, it is
belaran@999 12552 easy to copy-and-paste a hunk of its output into a file, and
belaran@999 12553 replace the text produced above by Subversion with the
belaran@999 12554 template values we'd like to see expanded.</para>
belaran@999 12555
belaran@999 12556 <!-- BEGIN template.svnstyle.template -->
belaran@999 12557 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.template</userinput>
belaran@999 12558 r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
belaran@999 12559
belaran@999 12560 {desc|strip|fill76}
belaran@999 12561
belaran@999 12562 ------------------------------------------------------------------------
belaran@999 12563 </screen>
belaran@999 12564 <!-- END template.svnstyle.template -->
belaran@999 12565
belaran@999 12566
belaran@999 12567 <para id="x_5da">There are a few small ways in which this template deviates
belaran@999 12568 from the output produced by Subversion.</para>
belaran@999 12569 <itemizedlist>
belaran@999 12570 <listitem><para id="x_5db">Subversion prints a <quote>readable</quote>
belaran@999 12571 date (the <quote><literal moreinfo="none">Wed, 27 Sep 2006</literal></quote> in the
belaran@999 12572 example output above) in parentheses. Mercurial's
belaran@999 12573 templating engine does not provide a way to display a date
belaran@999 12574 in this format without also printing the time and time
belaran@999 12575 zone.</para>
belaran@999 12576 </listitem>
belaran@999 12577 <listitem><para id="x_5dc">We emulate Subversion's printing of
belaran@999 12578 <quote>separator</quote> lines full of
belaran@999 12579 <quote><literal moreinfo="none">-</literal></quote> characters by ending
belaran@999 12580 the template with such a line. We use the templating
belaran@999 12581 engine's <literal role="template-keyword" moreinfo="none">header</literal>
belaran@999 12582 keyword to print a separator line as the first line of
belaran@999 12583 output (see below), thus achieving similar output to
belaran@999 12584 Subversion.</para>
belaran@999 12585 </listitem>
belaran@999 12586 <listitem><para id="x_5dd">Subversion's output includes a count in the
belaran@999 12587 header of the number of lines in the commit message. We
belaran@999 12588 cannot replicate this in Mercurial; the templating engine
belaran@999 12589 does not currently provide a filter that counts the number
belaran@999 12590 of lines the template generates.</para>
belaran@999 12591 </listitem></itemizedlist>
belaran@999 12592 <para id="x_5de">It took me no more than a minute or two of work to replace
belaran@999 12593 literal text from an example of Subversion's output with some
belaran@999 12594 keywords and filters to give the template above. The style
belaran@999 12595 file simply refers to the template.</para>
belaran@999 12596
belaran@999 12597 <!-- BEGIN template.svnstyle.style -->
belaran@999 12598 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.style</userinput>
belaran@999 12599 header = '------------------------------------------------------------------------\n\n'
belaran@999 12600 changeset = svn.template
belaran@999 12601 </screen>
belaran@999 12602 <!-- END template.svnstyle.style -->
belaran@999 12603
belaran@999 12604
belaran@999 12605 <para id="x_5df">We could have included the text of the template file
belaran@999 12606 directly in the style file by enclosing it in quotes and
belaran@999 12607 replacing the newlines with
belaran@999 12608 <quote><literal moreinfo="none">\n</literal></quote> sequences, but it would
belaran@999 12609 have made the style file too difficult to read. Readability
belaran@999 12610 is a good guide when you're trying to decide whether some text
belaran@999 12611 belongs in a style file, or in a template file that the style
belaran@999 12612 file points to. If the style file will look too big or
belaran@999 12613 cluttered if you insert a literal piece of text, drop it into
belaran@999 12614 a template instead.</para>
belaran@999 12615 </sect2>
belaran@999 12616 </sect1>
belaran@999 12617 </chapter>
belaran@999 12618
belaran@999 12619 <!--
belaran@999 12620 local variables:
belaran@999 12621 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 12622 end:
belaran@999 12623 -->
belaran@999 12624
belaran@999 12625 <!-- BEGIN ch12 -->
belaran@999 12626 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 12627
belaran@999 12628 <chapter id="chap:mq">
belaran@999 12629 <?dbhtml filename="managing-change-with-mercurial-queues.html"?>
belaran@999 12630 <title>Managing change with Mercurial Queues</title>
belaran@999 12631
belaran@999 12632 <sect1 id="sec:mq:patch-mgmt">
belaran@999 12633 <title>The patch management problem</title>
belaran@999 12634
belaran@999 12635 <para id="x_3ac">Here is a common scenario: you need to install a software
belaran@999 12636 package from source, but you find a bug that you must fix in the
belaran@999 12637 source before you can start using the package. You make your
belaran@999 12638 changes, forget about the package for a while, and a few months
belaran@999 12639 later you need to upgrade to a newer version of the package. If
belaran@999 12640 the newer version of the package still has the bug, you must
belaran@999 12641 extract your fix from the older source tree and apply it against
belaran@999 12642 the newer version. This is a tedious task, and it's easy to
belaran@999 12643 make mistakes.</para>
belaran@999 12644
belaran@999 12645 <para id="x_3ad">This is a simple case of the <quote>patch management</quote>
belaran@999 12646 problem. You have an <quote>upstream</quote> source tree that
belaran@999 12647 you can't change; you need to make some local changes on top of
belaran@999 12648 the upstream tree; and you'd like to be able to keep those
belaran@999 12649 changes separate, so that you can apply them to newer versions
belaran@999 12650 of the upstream source.</para>
belaran@999 12651
belaran@999 12652 <para id="x_3ae">The patch management problem arises in many situations.
belaran@999 12653 Probably the most visible is that a user of an open source
belaran@999 12654 software project will contribute a bug fix or new feature to the
belaran@999 12655 project's maintainers in the form of a patch.</para>
belaran@999 12656
belaran@999 12657 <para id="x_3af">Distributors of operating systems that include open source
belaran@999 12658 software often need to make changes to the packages they
belaran@999 12659 distribute so that they will build properly in their
belaran@999 12660 environments.</para>
belaran@999 12661
belaran@999 12662 <para id="x_3b0">When you have few changes to maintain, it is easy to manage
belaran@999 12663 a single patch using the standard <command moreinfo="none">diff</command> and
belaran@999 12664 <command moreinfo="none">patch</command> programs (see <xref linkend="sec:mq:patch"/> for a discussion of these
belaran@999 12665 tools). Once the number of changes grows, it starts to make
belaran@999 12666 sense to maintain patches as discrete <quote>chunks of
belaran@999 12667 work,</quote> so that for example a single patch will contain
belaran@999 12668 only one bug fix (the patch might modify several files, but it's
belaran@999 12669 doing <quote>only one thing</quote>), and you may have a number
belaran@999 12670 of such patches for different bugs you need fixed and local
belaran@999 12671 changes you require. In this situation, if you submit a bug fix
belaran@999 12672 patch to the upstream maintainers of a package and they include
belaran@999 12673 your fix in a subsequent release, you can simply drop that
belaran@999 12674 single patch when you're updating to the newer release.</para>
belaran@999 12675
belaran@999 12676 <para id="x_3b1">Maintaining a single patch against an upstream tree is a
belaran@999 12677 little tedious and error-prone, but not difficult. However, the
belaran@999 12678 complexity of the problem grows rapidly as the number of patches
belaran@999 12679 you have to maintain increases. With more than a tiny number of
belaran@999 12680 patches in hand, understanding which ones you have applied and
belaran@999 12681 maintaining them moves from messy to overwhelming.</para>
belaran@999 12682
belaran@999 12683 <para id="x_3b2">Fortunately, Mercurial includes a powerful extension,
belaran@999 12684 Mercurial Queues (or simply <quote>MQ</quote>), that massively
belaran@999 12685 simplifies the patch management problem.</para>
belaran@999 12686
belaran@999 12687 </sect1>
belaran@999 12688 <sect1 id="sec:mq:history">
belaran@999 12689 <title>The prehistory of Mercurial Queues</title>
belaran@999 12690
belaran@999 12691 <para id="x_3b3">During the late 1990s, several Linux kernel developers
belaran@999 12692 started to maintain <quote>patch series</quote> that modified
belaran@999 12693 the behavior of the Linux kernel. Some of these series were
belaran@999 12694 focused on stability, some on feature coverage, and others were
belaran@999 12695 more speculative.</para>
belaran@999 12696
belaran@999 12697 <para id="x_3b4">The sizes of these patch series grew rapidly. In 2002,
belaran@999 12698 Andrew Morton published some shell scripts he had been using to
belaran@999 12699 automate the task of managing his patch queues. Andrew was
belaran@999 12700 successfully using these scripts to manage hundreds (sometimes
belaran@999 12701 thousands) of patches on top of the Linux kernel.</para>
belaran@999 12702
belaran@999 12703 <sect2 id="sec:mq:quilt">
belaran@999 12704 <title>A patchwork quilt</title>
belaran@999 12705
belaran@999 12706 <para id="x_3b5">In early 2003, Andreas Gruenbacher and Martin Quinson
belaran@999 12707 borrowed the approach of Andrew's scripts and published a tool
belaran@999 12708 called <quote>patchwork quilt</quote>
belaran@999 12709 <citation>web:quilt</citation>, or simply <quote>quilt</quote>
belaran@999 12710 (see <citation>gruenbacher:2005</citation> for a paper
belaran@999 12711 describing it). Because quilt substantially automated patch
belaran@999 12712 management, it rapidly gained a large following among open
belaran@999 12713 source software developers.</para>
belaran@999 12714
belaran@999 12715 <para id="x_3b6">Quilt manages a <emphasis>stack of patches</emphasis> on
belaran@999 12716 top of a directory tree. To begin, you tell quilt to manage a
belaran@999 12717 directory tree, and tell it which files you want to manage; it
belaran@999 12718 stores away the names and contents of those files. To fix a
belaran@999 12719 bug, you create a new patch (using a single command), edit the
belaran@999 12720 files you need to fix, then <quote>refresh</quote> the
belaran@999 12721 patch.</para>
belaran@999 12722
belaran@999 12723 <para id="x_3b7">The refresh step causes quilt to scan the directory tree;
belaran@999 12724 it updates the patch with all of the changes you have made.
belaran@999 12725 You can create another patch on top of the first, which will
belaran@999 12726 track the changes required to modify the tree from <quote>tree
belaran@999 12727 with one patch applied</quote> to <quote>tree with two
belaran@999 12728 patches applied</quote>.</para>
belaran@999 12729
belaran@999 12730 <para id="x_3b8">You can <emphasis>change</emphasis> which patches are
belaran@999 12731 applied to the tree. If you <quote>pop</quote> a patch, the
belaran@999 12732 changes made by that patch will vanish from the directory
belaran@999 12733 tree. Quilt remembers which patches you have popped, though,
belaran@999 12734 so you can <quote>push</quote> a popped patch again, and the
belaran@999 12735 directory tree will be restored to contain the modifications
belaran@999 12736 in the patch. Most importantly, you can run the
belaran@999 12737 <quote>refresh</quote> command at any time, and the topmost
belaran@999 12738 applied patch will be updated. This means that you can, at
belaran@999 12739 any time, change both which patches are applied and what
belaran@999 12740 modifications those patches make.</para>
belaran@999 12741
belaran@999 12742 <para id="x_3b9">Quilt knows nothing about revision control tools, so it
belaran@999 12743 works equally well on top of an unpacked tarball or a
belaran@999 12744 Subversion working copy.</para>
belaran@999 12745 </sect2>
belaran@999 12746
belaran@999 12747 <sect2 id="sec:mq:quilt-mq">
belaran@999 12748 <title>From patchwork quilt to Mercurial Queues</title>
belaran@999 12749
belaran@999 12750 <para id="x_3ba">In mid-2005, Chris Mason took the features of quilt and
belaran@999 12751 wrote an extension that he called Mercurial Queues, which
belaran@999 12752 added quilt-like behavior to Mercurial.</para>
belaran@999 12753
belaran@999 12754 <para id="x_3bb">The key difference between quilt and MQ is that quilt
belaran@999 12755 knows nothing about revision control systems, while MQ is
belaran@999 12756 <emphasis>integrated</emphasis> into Mercurial. Each patch
belaran@999 12757 that you push is represented as a Mercurial changeset. Pop a
belaran@999 12758 patch, and the changeset goes away.</para>
belaran@999 12759
belaran@999 12760 <para id="x_3bc">Because quilt does not care about revision control tools,
belaran@999 12761 it is still a tremendously useful piece of software to know
belaran@999 12762 about for situations where you cannot use Mercurial and
belaran@999 12763 MQ.</para>
belaran@999 12764
belaran@999 12765 </sect2>
belaran@999 12766 </sect1>
belaran@999 12767 <sect1>
belaran@999 12768 <title>The huge advantage of MQ</title>
belaran@999 12769
belaran@999 12770 <para id="x_3bd">I cannot overstate the value that MQ offers through the
belaran@999 12771 unification of patches and revision control.</para>
belaran@999 12772
belaran@999 12773 <para id="x_3be">A major reason that patches have persisted in the free
belaran@999 12774 software and open source world—in spite of the
belaran@999 12775 availability of increasingly capable revision control tools over
belaran@999 12776 the years—is the <emphasis>agility</emphasis> they
belaran@999 12777 offer.</para>
belaran@999 12778
belaran@999 12779 <para id="x_3bf">Traditional revision control tools make a permanent,
belaran@999 12780 irreversible record of everything that you do. While this has
belaran@999 12781 great value, it's also somewhat stifling. If you want to
belaran@999 12782 perform a wild-eyed experiment, you have to be careful in how
belaran@999 12783 you go about it, or you risk leaving unneeded—or worse,
belaran@999 12784 misleading or destabilising—traces of your missteps and
belaran@999 12785 errors in the permanent revision record.</para>
belaran@999 12786
belaran@999 12787 <para id="x_3c0">By contrast, MQ's marriage of distributed revision control
belaran@999 12788 with patches makes it much easier to isolate your work. Your
belaran@999 12789 patches live on top of normal revision history, and you can make
belaran@999 12790 them disappear or reappear at will. If you don't like a patch,
belaran@999 12791 you can drop it. If a patch isn't quite as you want it to be,
belaran@999 12792 simply fix it—as many times as you need to, until you
belaran@999 12793 have refined it into the form you desire.</para>
belaran@999 12794
belaran@999 12795 <para id="x_3c1">As an example, the integration of patches with revision
belaran@999 12796 control makes understanding patches and debugging their
belaran@999 12797 effects—and their interplay with the code they're based
belaran@999 12798 on—<emphasis>enormously</emphasis> easier. Since every
belaran@999 12799 applied patch has an associated changeset, you can give <command role="hg-cmd" moreinfo="none">hg log</command> a file name to see which
belaran@999 12800 changesets and patches affected the file. You can use the
belaran@999 12801 <command role="hg-cmd" moreinfo="none">hg bisect</command> command to
belaran@999 12802 binary-search through all changesets and applied patches to see
belaran@999 12803 where a bug got introduced or fixed. You can use the <command role="hg-cmd" moreinfo="none">hg annotate</command> command to see which
belaran@999 12804 changeset or patch modified a particular line of a source file.
belaran@999 12805 And so on.</para>
belaran@999 12806 </sect1>
belaran@999 12807
belaran@999 12808 <sect1 id="sec:mq:patch">
belaran@999 12809 <title>Understanding patches</title>
belaran@999 12810
belaran@999 12811 <para id="x_3c2">Because MQ doesn't hide its patch-oriented nature, it is
belaran@999 12812 helpful to understand what patches are, and a little about the
belaran@999 12813 tools that work with them.</para>
belaran@999 12814
belaran@999 12815 <para id="x_3c3">The traditional Unix <command moreinfo="none">diff</command> command
belaran@999 12816 compares two files, and prints a list of differences between
belaran@999 12817 them. The <command moreinfo="none">patch</command> command understands these
belaran@999 12818 differences as <emphasis>modifications</emphasis> to make to a
belaran@999 12819 file. Take a look below for a simple example of these commands
belaran@999 12820 in action.</para>
belaran@999 12821
belaran@999 12822 <!-- BEGIN mq.dodiff.diff -->
belaran@999 12823 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'this is my original thought' &gt; oldfile</userinput>
belaran@999 12824 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'i have changed my mind' &gt; newfile</userinput>
belaran@999 12825 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diff -u oldfile newfile &gt; tiny.patch</userinput>
belaran@999 12826 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat tiny.patch</userinput>
belaran@999 12827 --- oldfile 2009-08-16 14:05:06.000000000 +0000
belaran@999 12828 +++ newfile 2009-08-16 14:05:06.000000000 +0000
belaran@999 12829 @@ -1 +1 @@
belaran@999 12830 -this is my original thought
belaran@999 12831 +i have changed my mind
belaran@999 12832 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">patch &lt; tiny.patch</userinput>
belaran@999 12833 patching file oldfile
belaran@999 12834 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat oldfile</userinput>
belaran@999 12835 i have changed my mind
belaran@999 12836 </screen>
belaran@999 12837 <!-- END mq.dodiff.diff -->
belaran@999 12838
belaran@999 12839
belaran@999 12840 <para id="x_3c4">The type of file that <command moreinfo="none">diff</command> generates (and
belaran@999 12841 <command moreinfo="none">patch</command> takes as input) is called a
belaran@999 12842 <quote>patch</quote> or a <quote>diff</quote>; there is no
belaran@999 12843 difference between a patch and a diff. (We'll use the term
belaran@999 12844 <quote>patch</quote>, since it's more commonly used.)</para>
belaran@999 12845
belaran@999 12846 <para id="x_3c5">A patch file can start with arbitrary text; the
belaran@999 12847 <command moreinfo="none">patch</command> command ignores this text, but MQ uses
belaran@999 12848 it as the commit message when creating changesets. To find the
belaran@999 12849 beginning of the patch content, <command moreinfo="none">patch</command>
belaran@999 12850 searches for the first line that starts with the string
belaran@999 12851 <quote><literal moreinfo="none">diff -</literal></quote>.</para>
belaran@999 12852
belaran@999 12853 <para id="x_3c6">MQ works with <emphasis>unified</emphasis> diffs
belaran@999 12854 (<command moreinfo="none">patch</command> can accept several other diff formats,
belaran@999 12855 but MQ doesn't). A unified diff contains two kinds of header.
belaran@999 12856 The <emphasis>file header</emphasis> describes the file being
belaran@999 12857 modified; it contains the name of the file to modify. When
belaran@999 12858 <command moreinfo="none">patch</command> sees a new file header, it looks for a
belaran@999 12859 file with that name to start modifying.</para>
belaran@999 12860
belaran@999 12861 <para id="x_3c7">After the file header comes a series of
belaran@999 12862 <emphasis>hunks</emphasis>. Each hunk starts with a header;
belaran@999 12863 this identifies the range of line numbers within the file that
belaran@999 12864 the hunk should modify. Following the header, a hunk starts and
belaran@999 12865 ends with a few (usually three) lines of text from the
belaran@999 12866 unmodified file; these are called the
belaran@999 12867 <emphasis>context</emphasis> for the hunk. If there's only a
belaran@999 12868 small amount of context between successive hunks,
belaran@999 12869 <command moreinfo="none">diff</command> doesn't print a new hunk header; it just
belaran@999 12870 runs the hunks together, with a few lines of context between
belaran@999 12871 modifications.</para>
belaran@999 12872
belaran@999 12873 <para id="x_3c8">Each line of context begins with a space character. Within
belaran@999 12874 the hunk, a line that begins with
belaran@999 12875 <quote><literal moreinfo="none">-</literal></quote> means <quote>remove this
belaran@999 12876 line,</quote> while a line that begins with
belaran@999 12877 <quote><literal moreinfo="none">+</literal></quote> means <quote>insert this
belaran@999 12878 line.</quote> For example, a line that is modified is
belaran@999 12879 represented by one deletion and one insertion.</para>
belaran@999 12880
belaran@999 12881 <para id="x_3c9">We will return to some of the more subtle aspects of patches
belaran@999 12882 later (in <xref linkend="sec:mq:adv-patch"/>), but you
belaran@999 12883 should have
belaran@999 12884 enough information now to use MQ.</para>
belaran@999 12885 </sect1>
belaran@999 12886
belaran@999 12887 <sect1 id="sec:mq:start">
belaran@999 12888 <title>Getting started with Mercurial Queues</title>
belaran@999 12889
belaran@999 12890 <para id="x_3ca">Because MQ is implemented as an extension, you must
belaran@999 12891 explicitly enable before you can use it. (You don't need to
belaran@999 12892 download anything; MQ ships with the standard Mercurial
belaran@999 12893 distribution.) To enable MQ, edit your <filename role="home" moreinfo="none">~/.hgrc</filename> file, and add the lines
belaran@999 12894 below.</para>
belaran@999 12895
belaran@999 12896 <programlisting format="linespecific">[extensions]
belaran@999 12897 hgext.mq =</programlisting>
belaran@999 12898
belaran@999 12899 <para id="x_3cb">Once the extension is enabled, it will make a number of new
belaran@999 12900 commands available. To verify that the extension is working,
belaran@999 12901 you can use <command role="hg-cmd" moreinfo="none">hg help</command> to see if
belaran@999 12902 the <command role="hg-ext-mq" moreinfo="none">qinit</command> command is now
belaran@999 12903 available.</para>
belaran@999 12904
belaran@999 12905 <!-- BEGIN mq.qinit-help.help -->
belaran@999 12906 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help qinit</userinput>
belaran@999 12907 hg qinit [-c]
belaran@999 12908
belaran@999 12909 init a new queue repository
belaran@999 12910
belaran@999 12911 The queue repository is unversioned by default. If -c is
belaran@999 12912 specified, qinit will create a separate nested repository
belaran@999 12913 for patches (qinit -c may also be run later to convert
belaran@999 12914 an unversioned patch repository into a versioned one).
belaran@999 12915 You can use qcommit to commit changes to this queue repository.
belaran@999 12916
belaran@999 12917 options:
belaran@999 12918
belaran@999 12919 -c --create-repo create queue repository
belaran@999 12920
belaran@999 12921 use "hg -v help qinit" to show global options
belaran@999 12922 </screen>
belaran@999 12923 <!-- END mq.qinit-help.help -->
belaran@999 12924
belaran@999 12925
belaran@999 12926 <para id="x_3cc">You can use MQ with <emphasis>any</emphasis> Mercurial
belaran@999 12927 repository, and its commands only operate within that
belaran@999 12928 repository. To get started, simply prepare the repository using
belaran@999 12929 the <command role="hg-ext-mq" moreinfo="none">qinit</command> command.</para>
belaran@999 12930
belaran@999 12931 <!-- BEGIN mq.tutorial.qinit -->
belaran@999 12932 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mq-sandbox</userinput>
belaran@999 12933 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mq-sandbox</userinput>
belaran@999 12934 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 1' &gt; file1</userinput>
belaran@999 12935 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'another line 1' &gt; file2</userinput>
belaran@999 12936 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file1 file2</userinput>
belaran@999 12937 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m'first change'</userinput>
belaran@999 12938 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
belaran@999 12939 </screen>
belaran@999 12940 <!-- END mq.tutorial.qinit -->
belaran@999 12941
belaran@999 12942
belaran@999 12943 <para id="x_3cd">This command creates an empty directory called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>, where
belaran@999 12944 MQ will keep its metadata. As with many Mercurial commands, the
belaran@999 12945 <command role="hg-ext-mq" moreinfo="none">qinit</command> command prints nothing
belaran@999 12946 if it succeeds.</para>
belaran@999 12947
belaran@999 12948 <sect2>
belaran@999 12949 <title>Creating a new patch</title>
belaran@999 12950
belaran@999 12951 <para id="x_3ce">To begin work on a new patch, use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command. This command takes
belaran@999 12952 one argument, the name of the patch to create.</para>
belaran@999 12953
belaran@999 12954 <para id="x_3cf">MQ will use this as the name of an actual file in the
belaran@999 12955 <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory, as you
belaran@999 12956 can see below.</para>
belaran@999 12957
belaran@999 12958 <!-- BEGIN mq.tutorial.qnew -->
belaran@999 12959 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 12960 changeset: 0:5d84c303994b
belaran@999 12961 tag: tip
belaran@999 12962 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 12963 date: Sun Aug 16 14:05:11 2009 +0000
belaran@999 12964 summary: first change
belaran@999 12965
belaran@999 12966 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew first.patch</userinput>
belaran@999 12967 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
belaran@999 12968 changeset: 1:ba4d7a3f2149
belaran@999 12969 tag: qtip
belaran@999 12970 tag: first.patch
belaran@999 12971 tag: tip
belaran@999 12972 tag: qbase
belaran@999 12973 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 12974 date: Sun Aug 16 14:05:11 2009 +0000
belaran@999 12975 summary: [mq]: first.patch
belaran@999 12976
belaran@999 12977 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls .hg/patches</userinput>
belaran@999 12978 first.patch series status
belaran@999 12979 </screen>
belaran@999 12980 <!-- END mq.tutorial.qnew -->
belaran@999 12981
belaran@999 12982
belaran@999 12983 <para id="x_3d0">Also newly present in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory are two
belaran@999 12984 other files, <filename role="special" moreinfo="none">series</filename> and
belaran@999 12985 <filename role="special" moreinfo="none">status</filename>. The <filename role="special" moreinfo="none">series</filename> file lists all of the
belaran@999 12986 patches that MQ knows about for this repository, with one
belaran@999 12987 patch per line. Mercurial uses the <filename role="special" moreinfo="none">status</filename> file for internal
belaran@999 12988 book-keeping; it tracks all of the patches that MQ has
belaran@999 12989 <emphasis>applied</emphasis> in this repository.</para>
belaran@999 12990
belaran@999 12991 <note>
belaran@999 12992 <para id="x_3d1"> You may sometimes want to edit the <filename role="special" moreinfo="none">series</filename> file by hand; for
belaran@999 12993 example, to change the sequence in which some patches are
belaran@999 12994 applied. However, manually editing the <filename role="special" moreinfo="none">status</filename> file is almost always a
belaran@999 12995 bad idea, as it's easy to corrupt MQ's idea of what is
belaran@999 12996 happening.</para>
belaran@999 12997 </note>
belaran@999 12998
belaran@999 12999 <para id="x_3d2">Once you have created your new patch, you can edit files
belaran@999 13000 in the working directory as you usually would. All of the
belaran@999 13001 normal Mercurial commands, such as <command role="hg-cmd" moreinfo="none">hg
belaran@999 13002 diff</command> and <command role="hg-cmd" moreinfo="none">hg
belaran@999 13003 annotate</command>, work exactly as they did before.</para>
belaran@999 13004 </sect2>
belaran@999 13005
belaran@999 13006 <sect2>
belaran@999 13007 <title>Refreshing a patch</title>
belaran@999 13008
belaran@999 13009 <para id="x_3d3">When you reach a point where you want to save your work,
belaran@999 13010 use the <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
belaran@999 13011 to update the patch you are working on.</para>
belaran@999 13012
belaran@999 13013 <!-- BEGIN mq.tutorial.qrefresh -->
belaran@999 13014 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 2' &gt;&gt; file1</userinput>
belaran@999 13015 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 13016 diff -r ba4d7a3f2149 file1
belaran@999 13017 --- a/file1 Sun Aug 16 14:05:11 2009 +0000
belaran@999 13018 +++ b/file1 Sun Aug 16 14:05:11 2009 +0000
belaran@999 13019 @@ -1,1 +1,2 @@
belaran@999 13020 line 1
belaran@999 13021 +line 2
belaran@999 13022 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 13023 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 13024 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
belaran@999 13025 1[qtip,first.patch,tip,qbase] 1aa236e17e55 2009-08-16 14:05 +0000 bos
belaran@999 13026 [mq]: first.patch
belaran@999 13027
belaran@999 13028 diff -r 5d84c303994b -r 1aa236e17e55 file1
belaran@999 13029 --- a/file1 Sun Aug 16 14:05:11 2009 +0000
belaran@999 13030 +++ b/file1 Sun Aug 16 14:05:11 2009 +0000
belaran@999 13031 @@ -1,1 +1,2 @@
belaran@999 13032 line 1
belaran@999 13033 +line 2
belaran@999 13034
belaran@999 13035 </screen>
belaran@999 13036 <!-- END mq.tutorial.qrefresh -->
belaran@999 13037
belaran@999 13038
belaran@999 13039 <para id="x_3d4">This command folds the changes you have made in the
belaran@999 13040 working directory into your patch, and updates its
belaran@999 13041 corresponding changeset to contain those changes.</para>
belaran@999 13042
belaran@999 13043 <para id="x_3d5">You can run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>
belaran@999 13044 as often as you like, so it's a good way to
belaran@999 13045 <quote>checkpoint</quote> your work. Refresh your patch at an
belaran@999 13046 opportune time; try an experiment; and if the experiment
belaran@999 13047 doesn't work out, <command role="hg-cmd" moreinfo="none">hg revert</command>
belaran@999 13048 your modifications back to the last time you refreshed.</para>
belaran@999 13049
belaran@999 13050 <!-- BEGIN mq.tutorial.qrefresh2 -->
belaran@999 13051 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 3' &gt;&gt; file1</userinput>
belaran@999 13052 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
belaran@999 13053 M file1
belaran@999 13054 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 13055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
belaran@999 13056 1[qtip,first.patch,tip,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos
belaran@999 13057 [mq]: first.patch
belaran@999 13058
belaran@999 13059 diff -r 5d84c303994b -r ebec7ce95e11 file1
belaran@999 13060 --- a/file1 Sun Aug 16 14:05:11 2009 +0000
belaran@999 13061 +++ b/file1 Sun Aug 16 14:05:12 2009 +0000
belaran@999 13062 @@ -1,1 +1,3 @@
belaran@999 13063 line 1
belaran@999 13064 +line 2
belaran@999 13065 +line 3
belaran@999 13066
belaran@999 13067 </screen>
belaran@999 13068 <!-- END mq.tutorial.qrefresh2 -->
belaran@999 13069
belaran@999 13070 </sect2>
belaran@999 13071
belaran@999 13072 <sect2>
belaran@999 13073 <title>Stacking and tracking patches</title>
belaran@999 13074
belaran@999 13075 <para id="x_3d6">Once you have finished working on a patch, or need to work
belaran@999 13076 on another, you can use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command again to create a
belaran@999 13077 new patch. Mercurial will apply this patch on top of your
belaran@999 13078 existing patch.</para>
belaran@999 13079
belaran@999 13080 <!-- BEGIN mq.tutorial.qnew2 -->
belaran@999 13081 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew second.patch</userinput>
belaran@999 13082 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style=compact --limit=2</userinput>
belaran@999 13083 2[qtip,second.patch,tip] dffbc4265523 2009-08-16 14:05 +0000 bos
belaran@999 13084 [mq]: second.patch
belaran@999 13085
belaran@999 13086 1[first.patch,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos
belaran@999 13087 [mq]: first.patch
belaran@999 13088
belaran@999 13089 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 4' &gt;&gt; file1</userinput>
belaran@999 13090 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 13091 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
belaran@999 13092 2[qtip,second.patch,tip] fdacb9b232ac 2009-08-16 14:05 +0000 bos
belaran@999 13093 [mq]: second.patch
belaran@999 13094
belaran@999 13095 diff -r ebec7ce95e11 -r fdacb9b232ac file1
belaran@999 13096 --- a/file1 Sun Aug 16 14:05:12 2009 +0000
belaran@999 13097 +++ b/file1 Sun Aug 16 14:05:12 2009 +0000
belaran@999 13098 @@ -1,3 +1,4 @@
belaran@999 13099 line 1
belaran@999 13100 line 2
belaran@999 13101 line 3
belaran@999 13102 +line 4
belaran@999 13103
belaran@999 13104 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg annotate file1</userinput>
belaran@999 13105 0: line 1
belaran@999 13106 1: line 2
belaran@999 13107 1: line 3
belaran@999 13108 2: line 4
belaran@999 13109 </screen>
belaran@999 13110 <!-- END mq.tutorial.qnew2 -->
belaran@999 13111
belaran@999 13112
belaran@999 13113 <para id="x_3d7">Notice that the patch contains the changes in our prior
belaran@999 13114 patch as part of its context (you can see this more clearly in
belaran@999 13115 the output of <command role="hg-cmd" moreinfo="none">hg
belaran@999 13116 annotate</command>).</para>
belaran@999 13117
belaran@999 13118 <para id="x_3d8">So far, with the exception of <command role="hg-ext-mq" moreinfo="none">qnew</command> and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>, we've been careful to
belaran@999 13119 only use regular Mercurial commands. However, MQ provides
belaran@999 13120 many commands that are easier to use when you are thinking
belaran@999 13121 about patches, as illustrated below.</para>
belaran@999 13122
belaran@999 13123 <!-- BEGIN mq.tutorial.qseries -->
belaran@999 13124 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput>
belaran@999 13125 first.patch
belaran@999 13126 second.patch
belaran@999 13127 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13128 first.patch
belaran@999 13129 second.patch
belaran@999 13130 </screen>
belaran@999 13131 <!-- END mq.tutorial.qseries -->
belaran@999 13132
belaran@999 13133
belaran@999 13134 <itemizedlist>
belaran@999 13135 <listitem><para id="x_3d9">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command lists every
belaran@999 13136 patch that MQ knows about in this repository, from oldest
belaran@999 13137 to newest (most recently
belaran@999 13138 <emphasis>created</emphasis>).</para>
belaran@999 13139 </listitem>
belaran@999 13140 <listitem><para id="x_3da">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command lists every
belaran@999 13141 patch that MQ has <emphasis>applied</emphasis> in this
belaran@999 13142 repository, again from oldest to newest (most recently
belaran@999 13143 applied).</para>
belaran@999 13144 </listitem></itemizedlist>
belaran@999 13145 </sect2>
belaran@999 13146
belaran@999 13147 <sect2>
belaran@999 13148 <title>Manipulating the patch stack</title>
belaran@999 13149
belaran@999 13150 <para id="x_3db">The previous discussion implied that there must be a
belaran@999 13151 difference between <quote>known</quote> and
belaran@999 13152 <quote>applied</quote> patches, and there is. MQ can manage a
belaran@999 13153 patch without it being applied in the repository.</para>
belaran@999 13154
belaran@999 13155 <para id="x_3dc">An <emphasis>applied</emphasis> patch has a corresponding
belaran@999 13156 changeset in the repository, and the effects of the patch and
belaran@999 13157 changeset are visible in the working directory. You can undo
belaran@999 13158 the application of a patch using the <command role="hg-ext-mq" moreinfo="none">qpop</command> command. MQ still
belaran@999 13159 <emphasis>knows about</emphasis>, or manages, a popped patch,
belaran@999 13160 but the patch no longer has a corresponding changeset in the
belaran@999 13161 repository, and the working directory does not contain the
belaran@999 13162 changes made by the patch. <xref linkend="fig:mq:stack"/> illustrates
belaran@999 13163 the difference between applied and tracked patches.</para>
belaran@999 13164
belaran@999 13165 <figure id="fig:mq:stack" float="0">
belaran@999 13166 <title>Applied and unapplied patches in the MQ patch
belaran@999 13167 stack</title>
belaran@999 13168 <mediaobject>
belaran@999 13169 <imageobject><imagedata fileref="figs/mq-stack.png"/></imageobject>
belaran@999 13170 <textobject><phrase>XXX add text</phrase></textobject>
belaran@999 13171 </mediaobject>
belaran@999 13172 </figure>
belaran@999 13173
belaran@999 13174 <para id="x_3de">You can reapply an unapplied, or popped, patch using the
belaran@999 13175 <command role="hg-ext-mq" moreinfo="none">qpush</command> command. This
belaran@999 13176 creates a new changeset to correspond to the patch, and the
belaran@999 13177 patch's changes once again become present in the working
belaran@999 13178 directory. See below for examples of <command role="hg-ext-mq" moreinfo="none">qpop</command> and <command role="hg-ext-mq" moreinfo="none">qpush</command> in action.</para>
belaran@999 13179
belaran@999 13180 <!-- BEGIN mq.tutorial.qpop -->
belaran@999 13181 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13182 first.patch
belaran@999 13183 second.patch
belaran@999 13184 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput>
belaran@999 13185 now at: first.patch
belaran@999 13186 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput>
belaran@999 13187 first.patch
belaran@999 13188 second.patch
belaran@999 13189 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13190 first.patch
belaran@999 13191 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput>
belaran@999 13192 line 1
belaran@999 13193 line 2
belaran@999 13194 line 3
belaran@999 13195 </screen>
belaran@999 13196 <!-- END mq.tutorial.qpop -->
belaran@999 13197
belaran@999 13198
belaran@999 13199 <para id="x_3df">Notice that once we have popped a patch or two patches,
belaran@999 13200 the output of <command role="hg-ext-mq" moreinfo="none">qseries</command>
belaran@999 13201 remains the same, while that of <command role="hg-ext-mq" moreinfo="none">qapplied</command> has changed.</para>
belaran@999 13202
belaran@999 13203 </sect2>
belaran@999 13204
belaran@999 13205 <sect2>
belaran@999 13206 <title>Pushing and popping many patches</title>
belaran@999 13207
belaran@999 13208 <para id="x_3e0">While <command role="hg-ext-mq" moreinfo="none">qpush</command> and
belaran@999 13209 <command role="hg-ext-mq" moreinfo="none">qpop</command> each operate on a
belaran@999 13210 single patch at a time by default, you can push and pop many
belaran@999 13211 patches in one go. The <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to
belaran@999 13212 <command role="hg-ext-mq" moreinfo="none">qpush</command> causes it to push
belaran@999 13213 all unapplied patches, while the <option role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command role="hg-ext-mq" moreinfo="none">qpop</command> causes it to pop all applied
belaran@999 13214 patches. (For some more ways to push and pop many patches,
belaran@999 13215 see <xref linkend="sec:mq:perf"/> below.)</para>
belaran@999 13216
belaran@999 13217 <!-- BEGIN mq.tutorial.qpush-a -->
belaran@999 13218 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
belaran@999 13219 applying second.patch
belaran@999 13220 now at: second.patch
belaran@999 13221 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput>
belaran@999 13222 line 1
belaran@999 13223 line 2
belaran@999 13224 line 3
belaran@999 13225 line 4
belaran@999 13226 </screen>
belaran@999 13227 <!-- END mq.tutorial.qpush-a -->
belaran@999 13228
belaran@999 13229 </sect2>
belaran@999 13230
belaran@999 13231 <sect2>
belaran@999 13232 <title>Safety checks, and overriding them</title>
belaran@999 13233
belaran@999 13234 <para id="x_3e1">Several MQ commands check the working directory before
belaran@999 13235 they do anything, and fail if they find any modifications.
belaran@999 13236 They do this to ensure that you won't lose any changes that
belaran@999 13237 you have made, but not yet incorporated into a patch. The
belaran@999 13238 example below illustrates this; the <command role="hg-ext-mq" moreinfo="none">qnew</command> command will not create a
belaran@999 13239 new patch if there are outstanding changes, caused in this
belaran@999 13240 case by the <command role="hg-cmd" moreinfo="none">hg add</command> of
belaran@999 13241 <filename moreinfo="none">file3</filename>.</para>
belaran@999 13242
belaran@999 13243 <!-- BEGIN mq.tutorial.add -->
belaran@999 13244 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'file 3, line 1' &gt;&gt; file3</userinput>
belaran@999 13245 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew add-file3.patch</userinput>
belaran@999 13246 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -f add-file3.patch</userinput>
belaran@999 13247 abort: patch "add-file3.patch" already exists
belaran@999 13248 </screen>
belaran@999 13249 <!-- END mq.tutorial.add -->
belaran@999 13250
belaran@999 13251
belaran@999 13252 <para id="x_3e2">Commands that check the working directory all take an
belaran@999 13253 <quote>I know what I'm doing</quote> option, which is always
belaran@999 13254 named <option>-f</option>. The exact meaning of
belaran@999 13255 <option>-f</option> depends on the command. For example,
belaran@999 13256 <command role="hg-cmd" moreinfo="none">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command>
belaran@999 13257 will incorporate any outstanding changes into the new patch it
belaran@999 13258 creates, but <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command>
belaran@999 13259 will revert modifications to any files affected by the patch
belaran@999 13260 that it is popping. Be sure to read the documentation for a
belaran@999 13261 command's <option>-f</option> option before you use it!</para>
belaran@999 13262 </sect2>
belaran@999 13263
belaran@999 13264 <sect2>
belaran@999 13265 <title>Working on several patches at once</title>
belaran@999 13266
belaran@999 13267 <para id="x_3e3">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
belaran@999 13268 always refreshes the <emphasis>topmost</emphasis> applied
belaran@999 13269 patch. This means that you can suspend work on one patch (by
belaran@999 13270 refreshing it), pop or push to make a different patch the top,
belaran@999 13271 and work on <emphasis>that</emphasis> patch for a
belaran@999 13272 while.</para>
belaran@999 13273
belaran@999 13274 <para id="x_3e4">Here's an example that illustrates how you can use this
belaran@999 13275 ability. Let's say you're developing a new feature as two
belaran@999 13276 patches. The first is a change to the core of your software,
belaran@999 13277 and the second—layered on top of the
belaran@999 13278 first—changes the user interface to use the code you
belaran@999 13279 just added to the core. If you notice a bug in the core while
belaran@999 13280 you're working on the UI patch, it's easy to fix the core.
belaran@999 13281 Simply <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the UI
belaran@999 13282 patch to save your in-progress changes, and <command role="hg-ext-mq" moreinfo="none">qpop</command> down to the core patch. Fix
belaran@999 13283 the core bug, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the
belaran@999 13284 core patch, and <command role="hg-ext-mq" moreinfo="none">qpush</command> back
belaran@999 13285 to the UI patch to continue where you left off.</para>
belaran@999 13286 </sect2>
belaran@999 13287 </sect1>
belaran@999 13288
belaran@999 13289 <sect1 id="sec:mq:adv-patch">
belaran@999 13290 <title>More about patches</title>
belaran@999 13291
belaran@999 13292 <para id="x_3e5">MQ uses the GNU <command moreinfo="none">patch</command> command to apply
belaran@999 13293 patches, so it's helpful to know a few more detailed aspects of
belaran@999 13294 how <command moreinfo="none">patch</command> works, and about patches
belaran@999 13295 themselves.</para>
belaran@999 13296
belaran@999 13297 <sect2>
belaran@999 13298 <title>The strip count</title>
belaran@999 13299
belaran@999 13300 <para id="x_3e6">If you look at the file headers in a patch, you will
belaran@999 13301 notice that the pathnames usually have an extra component on
belaran@999 13302 the front that isn't present in the actual path name. This is
belaran@999 13303 a holdover from the way that people used to generate patches
belaran@999 13304 (people still do this, but it's somewhat rare with modern
belaran@999 13305 revision control tools).</para>
belaran@999 13306
belaran@999 13307 <para id="x_3e7">Alice would unpack a tarball, edit her files, then decide
belaran@999 13308 that she wanted to create a patch. So she'd rename her
belaran@999 13309 working directory, unpack the tarball again (hence the need
belaran@999 13310 for the rename), and use the <option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to
belaran@999 13311 <command moreinfo="none">diff</command> to recursively generate a patch
belaran@999 13312 between the unmodified directory and the modified one. The
belaran@999 13313 result would be that the name of the unmodified directory
belaran@999 13314 would be at the front of the left-hand path in every file
belaran@999 13315 header, and the name of the modified directory would be at the
belaran@999 13316 front of the right-hand path.</para>
belaran@999 13317
belaran@999 13318 <para id="x_3e8">Since someone receiving a patch from the Alices of the net
belaran@999 13319 would be unlikely to have unmodified and modified directories
belaran@999 13320 with exactly the same names, the <command moreinfo="none">patch</command>
belaran@999 13321 command has a <option role="cmd-opt-patch">-p</option> option
belaran@999 13322 that indicates the number of leading path name components to
belaran@999 13323 strip when trying to apply a patch. This number is called the
belaran@999 13324 <emphasis>strip count</emphasis>.</para>
belaran@999 13325
belaran@999 13326 <para id="x_3e9">An option of <quote><literal moreinfo="none">-p1</literal></quote> means
belaran@999 13327 <quote>use a strip count of one</quote>. If
belaran@999 13328 <command moreinfo="none">patch</command> sees a file name
belaran@999 13329 <filename moreinfo="none">foo/bar/baz</filename> in a file header, it will
belaran@999 13330 strip <filename moreinfo="none">foo</filename> and try to patch a file named
belaran@999 13331 <filename moreinfo="none">bar/baz</filename>. (Strictly speaking, the strip
belaran@999 13332 count refers to the number of <emphasis>path
belaran@999 13333 separators</emphasis> (and the components that go with them
belaran@999 13334 ) to strip. A strip count of one will turn
belaran@999 13335 <filename moreinfo="none">foo/bar</filename> into <filename moreinfo="none">bar</filename>,
belaran@999 13336 but <filename moreinfo="none">/foo/bar</filename> (notice the extra leading
belaran@999 13337 slash) into <filename moreinfo="none">foo/bar</filename>.)</para>
belaran@999 13338
belaran@999 13339 <para id="x_3ea">The <quote>standard</quote> strip count for patches is
belaran@999 13340 one; almost all patches contain one leading path name
belaran@999 13341 component that needs to be stripped. Mercurial's <command role="hg-cmd" moreinfo="none">hg diff</command> command generates path names
belaran@999 13342 in this form, and the <command role="hg-cmd" moreinfo="none">hg
belaran@999 13343 import</command> command and MQ expect patches to have a
belaran@999 13344 strip count of one.</para>
belaran@999 13345
belaran@999 13346 <para id="x_3eb">If you receive a patch from someone that you want to add
belaran@999 13347 to your patch queue, and the patch needs a strip count other
belaran@999 13348 than one, you cannot just <command role="hg-ext-mq" moreinfo="none">qimport</command> the patch, because
belaran@999 13349 <command role="hg-ext-mq" moreinfo="none">qimport</command> does not yet have
belaran@999 13350 a <literal moreinfo="none">-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue
belaran@999 13351 311</ulink>). Your best bet is to <command role="hg-ext-mq" moreinfo="none">qnew</command> a patch of your own, then
belaran@999 13352 use <command moreinfo="none">patch -pN</command> to apply their patch,
belaran@999 13353 followed by <command role="hg-cmd" moreinfo="none">hg addremove</command> to
belaran@999 13354 pick up any files added or removed by the patch, followed by
belaran@999 13355 <command role="hg-ext-mq" moreinfo="none">hg qrefresh</command>. This
belaran@999 13356 complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue
belaran@999 13357 311</ulink> for details.
belaran@999 13358 </para>
belaran@999 13359 </sect2>
belaran@999 13360
belaran@999 13361 <sect2>
belaran@999 13362 <title>Strategies for applying a patch</title>
belaran@999 13363
belaran@999 13364 <para id="x_3ec">When <command moreinfo="none">patch</command> applies a hunk, it tries a
belaran@999 13365 handful of successively less accurate strategies to try to
belaran@999 13366 make the hunk apply. This falling-back technique often makes
belaran@999 13367 it possible to take a patch that was generated against an old
belaran@999 13368 version of a file, and apply it against a newer version of
belaran@999 13369 that file.</para>
belaran@999 13370
belaran@999 13371 <para id="x_3ed">First, <command moreinfo="none">patch</command> tries an exact match,
belaran@999 13372 where the line numbers, the context, and the text to be
belaran@999 13373 modified must apply exactly. If it cannot make an exact
belaran@999 13374 match, it tries to find an exact match for the context,
belaran@999 13375 without honouring the line numbering information. If this
belaran@999 13376 succeeds, it prints a line of output saying that the hunk was
belaran@999 13377 applied, but at some <emphasis>offset</emphasis> from the
belaran@999 13378 original line number.</para>
belaran@999 13379
belaran@999 13380 <para id="x_3ee">If a context-only match fails, <command moreinfo="none">patch</command>
belaran@999 13381 removes the first and last lines of the context, and tries a
belaran@999 13382 <emphasis>reduced</emphasis> context-only match. If the hunk
belaran@999 13383 with reduced context succeeds, it prints a message saying that
belaran@999 13384 it applied the hunk with a <emphasis>fuzz factor</emphasis>
belaran@999 13385 (the number after the fuzz factor indicates how many lines of
belaran@999 13386 context <command moreinfo="none">patch</command> had to trim before the patch
belaran@999 13387 applied).</para>
belaran@999 13388
belaran@999 13389 <para id="x_3ef">When neither of these techniques works,
belaran@999 13390 <command moreinfo="none">patch</command> prints a message saying that the hunk
belaran@999 13391 in question was rejected. It saves rejected hunks (also
belaran@999 13392 simply called <quote>rejects</quote>) to a file with the same
belaran@999 13393 name, and an added <filename role="special" moreinfo="none">.rej</filename>
belaran@999 13394 extension. It also saves an unmodified copy of the file with
belaran@999 13395 a <filename role="special" moreinfo="none">.orig</filename> extension; the
belaran@999 13396 copy of the file without any extensions will contain any
belaran@999 13397 changes made by hunks that <emphasis>did</emphasis> apply
belaran@999 13398 cleanly. If you have a patch that modifies
belaran@999 13399 <filename moreinfo="none">foo</filename> with six hunks, and one of them fails
belaran@999 13400 to apply, you will have: an unmodified
belaran@999 13401 <filename moreinfo="none">foo.orig</filename>, a <filename moreinfo="none">foo.rej</filename>
belaran@999 13402 containing one hunk, and <filename moreinfo="none">foo</filename>, containing
belaran@999 13403 the changes made by the five successful hunks.</para>
belaran@999 13404 </sect2>
belaran@999 13405
belaran@999 13406 <sect2>
belaran@999 13407 <title>Some quirks of patch representation</title>
belaran@999 13408
belaran@999 13409 <para id="x_3f0">There are a few useful things to know about how
belaran@999 13410 <command moreinfo="none">patch</command> works with files.</para>
belaran@999 13411 <itemizedlist>
belaran@999 13412 <listitem><para id="x_3f1">This should already be obvious, but
belaran@999 13413 <command moreinfo="none">patch</command> cannot handle binary
belaran@999 13414 files.</para>
belaran@999 13415 </listitem>
belaran@999 13416 <listitem><para id="x_3f2">Neither does it care about the executable bit;
belaran@999 13417 it creates new files as readable, but not
belaran@999 13418 executable.</para>
belaran@999 13419 </listitem>
belaran@999 13420 <listitem><para id="x_3f3"><command moreinfo="none">patch</command> treats the removal of
belaran@999 13421 a file as a diff between the file to be removed and the
belaran@999 13422 empty file. So your idea of <quote>I deleted this
belaran@999 13423 file</quote> looks like <quote>every line of this file
belaran@999 13424 was deleted</quote> in a patch.</para>
belaran@999 13425 </listitem>
belaran@999 13426 <listitem><para id="x_3f4">It treats the addition of a file as a diff
belaran@999 13427 between the empty file and the file to be added. So in a
belaran@999 13428 patch, your idea of <quote>I added this file</quote> looks
belaran@999 13429 like <quote>every line of this file was
belaran@999 13430 added</quote>.</para>
belaran@999 13431 </listitem>
belaran@999 13432 <listitem><para id="x_3f5">It treats a renamed file as the removal of the
belaran@999 13433 old name, and the addition of the new name. This means
belaran@999 13434 that renamed files have a big footprint in patches. (Note
belaran@999 13435 also that Mercurial does not currently try to infer when
belaran@999 13436 files have been renamed or copied in a patch.)</para>
belaran@999 13437 </listitem>
belaran@999 13438 <listitem><para id="x_3f6"><command moreinfo="none">patch</command> cannot represent
belaran@999 13439 empty files, so you cannot use a patch to represent the
belaran@999 13440 notion <quote>I added this empty file to the
belaran@999 13441 tree</quote>.</para>
belaran@999 13442 </listitem></itemizedlist>
belaran@999 13443 </sect2>
belaran@999 13444
belaran@999 13445 <sect2>
belaran@999 13446 <title>Beware the fuzz</title>
belaran@999 13447
belaran@999 13448 <para id="x_3f7">While applying a hunk at an offset, or with a fuzz factor,
belaran@999 13449 will often be completely successful, these inexact techniques
belaran@999 13450 naturally leave open the possibility of corrupting the patched
belaran@999 13451 file. The most common cases typically involve applying a
belaran@999 13452 patch twice, or at an incorrect location in the file. If
belaran@999 13453 <command moreinfo="none">patch</command> or <command role="hg-ext-mq" moreinfo="none">qpush</command> ever mentions an offset or
belaran@999 13454 fuzz factor, you should make sure that the modified files are
belaran@999 13455 correct afterwards.</para>
belaran@999 13456
belaran@999 13457 <para id="x_3f8">It's often a good idea to refresh a patch that has applied
belaran@999 13458 with an offset or fuzz factor; refreshing the patch generates
belaran@999 13459 new context information that will make it apply cleanly. I
belaran@999 13460 say <quote>often,</quote> not <quote>always,</quote> because
belaran@999 13461 sometimes refreshing a patch will make it fail to apply
belaran@999 13462 against a different revision of the underlying files. In some
belaran@999 13463 cases, such as when you're maintaining a patch that must sit
belaran@999 13464 on top of multiple versions of a source tree, it's acceptable
belaran@999 13465 to have a patch apply with some fuzz, provided you've verified
belaran@999 13466 the results of the patching process in such cases.</para>
belaran@999 13467 </sect2>
belaran@999 13468
belaran@999 13469 <sect2>
belaran@999 13470 <title>Handling rejection</title>
belaran@999 13471
belaran@999 13472 <para id="x_3f9">If <command role="hg-ext-mq" moreinfo="none">qpush</command> fails to
belaran@999 13473 apply a patch, it will print an error message and exit. If it
belaran@999 13474 has left <filename role="special" moreinfo="none">.rej</filename> files
belaran@999 13475 behind, it is usually best to fix up the rejected hunks before
belaran@999 13476 you push more patches or do any further work.</para>
belaran@999 13477
belaran@999 13478 <para id="x_3fa">If your patch <emphasis>used to</emphasis> apply cleanly,
belaran@999 13479 and no longer does because you've changed the underlying code
belaran@999 13480 that your patches are based on, Mercurial Queues can help; see
belaran@999 13481 <xref linkend="sec:mq:merge"/> for details.</para>
belaran@999 13482
belaran@999 13483 <para id="x_3fb">Unfortunately, there aren't any great techniques for
belaran@999 13484 dealing with rejected hunks. Most often, you'll need to view
belaran@999 13485 the <filename role="special" moreinfo="none">.rej</filename> file and edit the
belaran@999 13486 target file, applying the rejected hunks by hand.</para>
belaran@999 13487
belaran@999 13488 <para id="x_3fd">A Linux kernel hacker, Chris Mason (the author
belaran@999 13489 of Mercurial Queues), wrote a tool called
belaran@999 13490 <command moreinfo="none">mpatch</command> (<ulink url="http://oss.oracle.com/~mason/mpatch/">http://oss.oracle.com/~mason/mpatch/</ulink>),
belaran@999 13491 which takes a simple approach to automating the application of
belaran@999 13492 hunks rejected by <command moreinfo="none">patch</command>. The
belaran@999 13493 <command moreinfo="none">mpatch</command> command can help with four common
belaran@999 13494 reasons that a hunk may be rejected:</para>
belaran@999 13495
belaran@999 13496 <itemizedlist>
belaran@999 13497 <listitem><para id="x_3fe">The context in the middle of a hunk has
belaran@999 13498 changed.</para>
belaran@999 13499 </listitem>
belaran@999 13500 <listitem><para id="x_3ff">A hunk is missing some context at the
belaran@999 13501 beginning or end.</para>
belaran@999 13502 </listitem>
belaran@999 13503 <listitem><para id="x_400">A large hunk might apply better—either
belaran@999 13504 entirely or in part—if it was broken up into
belaran@999 13505 smaller hunks.</para>
belaran@999 13506 </listitem>
belaran@999 13507 <listitem><para id="x_401">A hunk removes lines with slightly different
belaran@999 13508 content than those currently present in the file.</para>
belaran@999 13509 </listitem></itemizedlist>
belaran@999 13510
belaran@999 13511 <para id="x_402">If you use <command moreinfo="none">mpatch</command>, you
belaran@999 13512 should be doubly careful to check your results when you're
belaran@999 13513 done. In fact, <command moreinfo="none">mpatch</command> enforces this method
belaran@999 13514 of double-checking the tool's output, by automatically
belaran@999 13515 dropping you into a merge program when it has done its job, so
belaran@999 13516 that you can verify its work and finish off any remaining
belaran@999 13517 merges.</para>
belaran@999 13518 </sect2>
belaran@999 13519 </sect1>
belaran@999 13520
belaran@999 13521 <sect1>
belaran@999 13522 <title>More on patch management</title>
belaran@999 13523
belaran@999 13524 <para id="x_6db">As you grow familiar with MQ, you will find yourself wanting
belaran@999 13525 to perform other kinds of patch management operations.</para>
belaran@999 13526
belaran@999 13527 <sect2>
belaran@999 13528 <title>Deleting unwanted patches</title>
belaran@999 13529
belaran@999 13530 <para id="x_6dc">If you want to get rid of a patch, use the <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> command to delete the
belaran@999 13531 patch file and remove its entry from the patch series. If you
belaran@999 13532 try to delete a patch that is still applied, <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> will refuse.</para>
belaran@999 13533
belaran@999 13534 <!-- BEGIN ch11/qdelete.go -->
belaran@999 13535 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput>
belaran@999 13536 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput>
belaran@999 13537 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
belaran@999 13538 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew bad.patch</userinput>
belaran@999 13539 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 13540 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
belaran@999 13541 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 13542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput>
belaran@999 13543 abort: cannot delete applied patch bad.patch
belaran@999 13544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput>
belaran@999 13545 patch queue now empty
belaran@999 13546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput>
belaran@999 13547 </screen>
belaran@999 13548 <!-- END ch11/qdelete.go -->
belaran@999 13549
belaran@999 13550 </sect2>
belaran@999 13551
belaran@999 13552 <sect2>
belaran@999 13553 <title>Converting to and from permanent revisions</title>
belaran@999 13554
belaran@999 13555 <para id="x_6dd">Once you're done working on a patch and want to
belaran@999 13556 turn it into a permanent changeset, use the <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command. Pass a revision
belaran@999 13557 to the command to identify the patch that you want to turn into
belaran@999 13558 a regular changeset; this patch must already be applied.</para>
belaran@999 13559
belaran@999 13560 <!-- BEGIN ch11/qdelete.convert -->
belaran@999 13561 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew good.patch</userinput>
belaran@999 13562 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
belaran@999 13563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
belaran@999 13564 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh -m 'Good change'</userinput>
belaran@999 13565 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qfinish tip</userinput>
belaran@999 13566 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13567 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact</userinput>
belaran@999 13568 0[tip] 32fc5ce6b092 2009-08-16 14:04 +0000 bos
belaran@999 13569 Good change
belaran@999 13570
belaran@999 13571 </screen>
belaran@999 13572 <!-- END ch11/qdelete.convert -->
belaran@999 13573
belaran@999 13574
belaran@999 13575 <para id="x_6e0">The <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command
belaran@999 13576 accepts an <option>--all</option> or <option>-a</option>
belaran@999 13577 option, which turns all applied patches into regular
belaran@999 13578 changesets.</para>
belaran@999 13579
belaran@999 13580 <para id="x_6de">It is also possible to turn an existing changeset into a
belaran@999 13581 patch, by passing the <option>-r</option> option to <command role="hg-ext-mq" moreinfo="none">hg qimport</command>.</para>
belaran@999 13582
belaran@999 13583 <!-- BEGIN ch11/qdelete.import -->
belaran@999 13584 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qimport -r tip</userinput>
belaran@999 13585 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13586 0.diff
belaran@999 13587 </screen>
belaran@999 13588 <!-- END ch11/qdelete.import -->
belaran@999 13589
belaran@999 13590
belaran@999 13591 <para id="x_6df">Note that it only makes sense to convert a changeset into
belaran@999 13592 a patch if you have not propagated that changeset into any
belaran@999 13593 other repositories. The imported changeset's ID will change
belaran@999 13594 every time you refresh the patch, which will make Mercurial
belaran@999 13595 treat it as unrelated to the original changeset if you have
belaran@999 13596 pushed it somewhere else.</para>
belaran@999 13597 </sect2>
belaran@999 13598 </sect1>
belaran@999 13599
belaran@999 13600 <sect1 id="sec:mq:perf">
belaran@999 13601 <title>Getting the best performance out of MQ</title>
belaran@999 13602
belaran@999 13603 <para id="x_403">MQ is very efficient at handling a large number
belaran@999 13604 of patches. I ran some performance experiments in mid-2006 for a
belaran@999 13605 talk that I gave at the 2006 EuroPython conference (on modern
belaran@999 13606 hardware, you should expect better performance than you'll see
belaran@999 13607 below). I used as my data set the Linux 2.6.17-mm1 patch
belaran@999 13608 series, which consists of 1,738 patches. I applied these on top
belaran@999 13609 of a Linux kernel repository containing all 27,472 revisions
belaran@999 13610 between Linux 2.6.12-rc2 and Linux 2.6.17.</para>
belaran@999 13611
belaran@999 13612 <para id="x_404">On my old, slow laptop, I was able to <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all
belaran@999 13613 1,738 patches in 3.5 minutes, and <command role="hg-cmd" moreinfo="none">hg qpop
belaran@999 13614 <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command>
belaran@999 13615 them all in 30 seconds. (On a newer laptop, the time to push
belaran@999 13616 all patches dropped to two minutes.) I could <command role="hg-ext-mq" moreinfo="none">qrefresh</command> one of the biggest patches
belaran@999 13617 (which made 22,779 lines of changes to 287 files) in 6.6
belaran@999 13618 seconds.</para>
belaran@999 13619
belaran@999 13620 <para id="x_405">Clearly, MQ is well suited to working in large trees, but
belaran@999 13621 there are a few tricks you can use to get the best performance
belaran@999 13622 of it.</para>
belaran@999 13623
belaran@999 13624 <para id="x_406">First of all, try to <quote>batch</quote> operations
belaran@999 13625 together. Every time you run <command role="hg-ext-mq" moreinfo="none">qpush</command> or <command role="hg-ext-mq" moreinfo="none">qpop</command>, these commands scan the
belaran@999 13626 working directory once to make sure you haven't made some
belaran@999 13627 changes and then forgotten to run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>. On a small tree, the
belaran@999 13628 time that this scan takes is unnoticeable. However, on a
belaran@999 13629 medium-sized tree (containing tens of thousands of files), it
belaran@999 13630 can take a second or more.</para>
belaran@999 13631
belaran@999 13632 <para id="x_407">The <command role="hg-ext-mq" moreinfo="none">qpush</command> and <command role="hg-ext-mq" moreinfo="none">qpop</command> commands allow you to push and
belaran@999 13633 pop multiple patches at a time. You can identify the
belaran@999 13634 <quote>destination patch</quote> that you want to end up at.
belaran@999 13635 When you <command role="hg-ext-mq" moreinfo="none">qpush</command> with a
belaran@999 13636 destination specified, it will push patches until that patch is
belaran@999 13637 at the top of the applied stack. When you <command role="hg-ext-mq" moreinfo="none">qpop</command> to a destination, MQ will pop
belaran@999 13638 patches until the destination patch is at the top.</para>
belaran@999 13639
belaran@999 13640 <para id="x_408">You can identify a destination patch using either the name
belaran@999 13641 of the patch, or by number. If you use numeric addressing,
belaran@999 13642 patches are counted from zero; this means that the first patch
belaran@999 13643 is zero, the second is one, and so on.</para>
belaran@999 13644 </sect1>
belaran@999 13645
belaran@999 13646 <sect1 id="sec:mq:merge">
belaran@999 13647 <title>Updating your patches when the underlying code
belaran@999 13648 changes</title>
belaran@999 13649
belaran@999 13650 <para id="x_409">It's common to have a stack of patches on top of an
belaran@999 13651 underlying repository that you don't modify directly. If you're
belaran@999 13652 working on changes to third-party code, or on a feature that is
belaran@999 13653 taking longer to develop than the rate of change of the code
belaran@999 13654 beneath, you will often need to sync up with the underlying
belaran@999 13655 code, and fix up any hunks in your patches that no longer apply.
belaran@999 13656 This is called <emphasis>rebasing</emphasis> your patch
belaran@999 13657 series.</para>
belaran@999 13658
belaran@999 13659 <para id="x_40a">The simplest way to do this is to <command role="hg-cmd" moreinfo="none">hg
belaran@999 13660 qpop <option role="hg-ext-mq-cmd-qpop-opt">hg
belaran@999 13661 -a</option></command> your patches, then <command role="hg-cmd" moreinfo="none">hg pull</command> changes into the underlying
belaran@999 13662 repository, and finally <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your
belaran@999 13663 patches again. MQ will stop pushing any time it runs across a
belaran@999 13664 patch that fails to apply during conflicts, allowing you to fix
belaran@999 13665 your conflicts, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the
belaran@999 13666 affected patch, and continue pushing until you have fixed your
belaran@999 13667 entire stack.</para>
belaran@999 13668
belaran@999 13669 <para id="x_40b">This approach is easy to use and works well if you don't
belaran@999 13670 expect changes to the underlying code to affect how well your
belaran@999 13671 patches apply. If your patch stack touches code that is modified
belaran@999 13672 frequently or invasively in the underlying repository, however,
belaran@999 13673 fixing up rejected hunks by hand quickly becomes
belaran@999 13674 tiresome.</para>
belaran@999 13675
belaran@999 13676 <para id="x_40c">It's possible to partially automate the rebasing process.
belaran@999 13677 If your patches apply cleanly against some revision of the
belaran@999 13678 underlying repo, MQ can use this information to help you to
belaran@999 13679 resolve conflicts between your patches and a different
belaran@999 13680 revision.</para>
belaran@999 13681
belaran@999 13682 <para id="x_40d">The process is a little involved.</para>
belaran@999 13683 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 13684 <listitem><para id="x_40e">To begin, <command role="hg-cmd" moreinfo="none">hg qpush
belaran@999 13685 -a</command> all of your patches on top of the revision
belaran@999 13686 where you know that they apply cleanly.</para>
belaran@999 13687 </listitem>
belaran@999 13688 <listitem><para id="x_40f">Save a backup copy of your patch directory using
belaran@999 13689 <command role="hg-cmd" moreinfo="none">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>.
belaran@999 13690 This prints the name of the directory that it has saved the
belaran@999 13691 patches in. It will save the patches to a directory called
belaran@999 13692 <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>, where
belaran@999 13693 <literal moreinfo="none">N</literal> is a small integer. It also commits a
belaran@999 13694 <quote>save changeset</quote> on top of your applied
belaran@999 13695 patches; this is for internal book-keeping, and records the
belaran@999 13696 states of the <filename role="special" moreinfo="none">series</filename> and
belaran@999 13697 <filename role="special" moreinfo="none">status</filename> files.</para>
belaran@999 13698 </listitem>
belaran@999 13699 <listitem><para id="x_410">Use <command role="hg-cmd" moreinfo="none">hg pull</command> to
belaran@999 13700 bring new changes into the underlying repository. (Don't
belaran@999 13701 run <command role="hg-cmd" moreinfo="none">hg pull -u</command>; see below
belaran@999 13702 for why.)</para>
belaran@999 13703 </listitem>
belaran@999 13704 <listitem><para id="x_411">Update to the new tip revision, using <command role="hg-cmd" moreinfo="none">hg update <option role="hg-opt-update">-C</option></command> to override
belaran@999 13705 the patches you have pushed.</para>
belaran@999 13706 </listitem>
belaran@999 13707 <listitem><para id="x_412">Merge all patches using <command moreinfo="none">hg qpush -m
belaran@999 13708 -a</command>. The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to
belaran@999 13709 <command role="hg-ext-mq" moreinfo="none">qpush</command> tells MQ to
belaran@999 13710 perform a three-way merge if the patch fails to
belaran@999 13711 apply.</para>
belaran@999 13712 </listitem></orderedlist>
belaran@999 13713
belaran@999 13714 <para id="x_413">During the <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>,
belaran@999 13715 each patch in the <filename role="special" moreinfo="none">series</filename>
belaran@999 13716 file is applied normally. If a patch applies with fuzz or
belaran@999 13717 rejects, MQ looks at the queue you <command role="hg-ext-mq" moreinfo="none">qsave</command>d, and performs a three-way
belaran@999 13718 merge with the corresponding changeset. This merge uses
belaran@999 13719 Mercurial's normal merge machinery, so it may pop up a GUI merge
belaran@999 13720 tool to help you to resolve problems.</para>
belaran@999 13721
belaran@999 13722 <para id="x_414">When you finish resolving the effects of a patch, MQ
belaran@999 13723 refreshes your patch based on the result of the merge.</para>
belaran@999 13724
belaran@999 13725 <para id="x_415">At the end of this process, your repository will have one
belaran@999 13726 extra head from the old patch queue, and a copy of the old patch
belaran@999 13727 queue will be in <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>. You can remove the
belaran@999 13728 extra head using <command role="hg-cmd" moreinfo="none">hg qpop -a -n
belaran@999 13729 patches.N</command> or <command role="hg-cmd" moreinfo="none">hg
belaran@999 13730 strip</command>. You can delete <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename> once you are sure
belaran@999 13731 that you no longer need it as a backup.</para>
belaran@999 13732 </sect1>
belaran@999 13733
belaran@999 13734 <sect1>
belaran@999 13735 <title>Identifying patches</title>
belaran@999 13736
belaran@999 13737 <para id="x_416">MQ commands that work with patches let you refer to a patch
belaran@999 13738 either by using its name or by a number. By name is obvious
belaran@999 13739 enough; pass the name <filename moreinfo="none">foo.patch</filename> to <command role="hg-ext-mq" moreinfo="none">qpush</command>, for example, and it will
belaran@999 13740 push patches until <filename moreinfo="none">foo.patch</filename> is
belaran@999 13741 applied.</para>
belaran@999 13742
belaran@999 13743 <para id="x_417">As a shortcut, you can refer to a patch using both a name
belaran@999 13744 and a numeric offset; <literal moreinfo="none">foo.patch-2</literal> means
belaran@999 13745 <quote>two patches before <literal moreinfo="none">foo.patch</literal></quote>,
belaran@999 13746 while <literal moreinfo="none">bar.patch+4</literal> means <quote>four patches
belaran@999 13747 after <literal moreinfo="none">bar.patch</literal></quote>.</para>
belaran@999 13748
belaran@999 13749 <para id="x_418">Referring to a patch by index isn't much different. The
belaran@999 13750 first patch printed in the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> is patch zero (yes, it's
belaran@999 13751 one of those start-at-zero counting systems); the second is
belaran@999 13752 patch one; and so on.</para>
belaran@999 13753
belaran@999 13754 <para id="x_419">MQ also makes it easy to work with patches when you are
belaran@999 13755 using normal Mercurial commands. Every command that accepts a
belaran@999 13756 changeset ID will also accept the name of an applied patch. MQ
belaran@999 13757 augments the tags normally in the repository with an eponymous
belaran@999 13758 one for each applied patch. In addition, the special tags
belaran@999 13759 <literal role="tag" moreinfo="none">qbase</literal> and
belaran@999 13760 <literal role="tag" moreinfo="none">qtip</literal> identify
belaran@999 13761 the <quote>bottom-most</quote> and topmost applied patches,
belaran@999 13762 respectively.</para>
belaran@999 13763
belaran@999 13764 <para id="x_41a">These additions to Mercurial's normal tagging capabilities
belaran@999 13765 make dealing with patches even more of a breeze.</para>
belaran@999 13766 <itemizedlist>
belaran@999 13767 <listitem><para id="x_41b">Want to patchbomb a mailing list with your
belaran@999 13768 latest series of changes?</para>
belaran@999 13769 <programlisting format="linespecific">hg email qbase:qtip</programlisting>
belaran@999 13770 <para id="x_41c"> (Don't know what <quote>patchbombing</quote> is? See
belaran@999 13771 <xref linkend="sec:hgext:patchbomb"/>.)</para>
belaran@999 13772 </listitem>
belaran@999 13773 <listitem><para id="x_41d">Need to see all of the patches since
belaran@999 13774 <literal moreinfo="none">foo.patch</literal> that have touched files in a
belaran@999 13775 subdirectory of your tree?</para>
belaran@999 13776 <programlisting format="linespecific">hg log -r foo.patch:qtip subdir</programlisting>
belaran@999 13777 </listitem>
belaran@999 13778 </itemizedlist>
belaran@999 13779
belaran@999 13780 <para id="x_41e">Because MQ makes the names of patches available to the rest
belaran@999 13781 of Mercurial through its normal internal tag machinery, you
belaran@999 13782 don't need to type in the entire name of a patch when you want
belaran@999 13783 to identify it by name.</para>
belaran@999 13784
belaran@999 13785 <para id="x_41f">Another nice consequence of representing patch names as tags
belaran@999 13786 is that when you run the <command role="hg-cmd" moreinfo="none">hg log</command>
belaran@999 13787 command, it will display a patch's name as a tag, simply as part
belaran@999 13788 of its normal output. This makes it easy to visually
belaran@999 13789 distinguish applied patches from underlying
belaran@999 13790 <quote>normal</quote> revisions. The following example shows a
belaran@999 13791 few normal Mercurial commands in use with applied
belaran@999 13792 patches.</para>
belaran@999 13793
belaran@999 13794 <!-- BEGIN mq.id.output -->
belaran@999 13795 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
belaran@999 13796 first.patch
belaran@999 13797 second.patch
belaran@999 13798 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r qbase:qtip</userinput>
belaran@999 13799 changeset: 1:c3bcf3b7335a
belaran@999 13800 tag: first.patch
belaran@999 13801 tag: qbase
belaran@999 13802 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 13803 date: Sun Aug 16 14:05:08 2009 +0000
belaran@999 13804 summary: [mq]: first.patch
belaran@999 13805
belaran@999 13806 changeset: 2:d189ba63b5f7
belaran@999 13807 tag: qtip
belaran@999 13808 tag: second.patch
belaran@999 13809 tag: tip
belaran@999 13810 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 13811 date: Sun Aug 16 14:05:09 2009 +0000
belaran@999 13812 summary: [mq]: second.patch
belaran@999 13813
belaran@999 13814 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg export second.patch</userinput>
belaran@999 13815 # HG changeset patch
belaran@999 13816 # User Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 13817 # Date 1250431509 0
belaran@999 13818 # Node ID d189ba63b5f7427f9644663c01fc16fe80399c65
belaran@999 13819 # Parent c3bcf3b7335afc0a250e85c51a1266d35d43a545
belaran@999 13820 [mq]: second.patch
belaran@999 13821
belaran@999 13822 diff -r c3bcf3b7335a -r d189ba63b5f7 other.c
belaran@999 13823 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
belaran@999 13824 +++ b/other.c Sun Aug 16 14:05:09 2009 +0000
belaran@999 13825 @@ -0,0 +1,1 @@
belaran@999 13826 +double u;
belaran@999 13827 </screen>
belaran@999 13828 <!-- END mq.id.output -->
belaran@999 13829
belaran@999 13830 </sect1>
belaran@999 13831
belaran@999 13832 <sect1>
belaran@999 13833 <title>Useful things to know about</title>
belaran@999 13834
belaran@999 13835 <para id="x_420">There are a number of aspects of MQ usage that don't fit
belaran@999 13836 tidily into sections of their own, but that are good to know.
belaran@999 13837 Here they are, in one place.</para>
belaran@999 13838
belaran@999 13839 <itemizedlist>
belaran@999 13840 <listitem><para id="x_421">Normally, when you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the changeset
belaran@999 13841 that represents the patch after the pop/push will have a
belaran@999 13842 <emphasis>different identity</emphasis> than the changeset
belaran@999 13843 that represented the hash beforehand. See <xref linkend="sec:mqref:cmd:qpush"/> for
belaran@999 13844 information as to why this is.</para>
belaran@999 13845 </listitem>
belaran@999 13846 <listitem><para id="x_422">It's not a good idea to <command role="hg-cmd" moreinfo="none">hg merge</command> changes from another
belaran@999 13847 branch with a patch changeset, at least if you want to
belaran@999 13848 maintain the <quote>patchiness</quote> of that changeset and
belaran@999 13849 changesets below it on the patch stack. If you try to do
belaran@999 13850 this, it will appear to succeed, but MQ will become
belaran@999 13851 confused.</para>
belaran@999 13852 </listitem></itemizedlist>
belaran@999 13853 </sect1>
belaran@999 13854
belaran@999 13855 <sect1 id="sec:mq:repo">
belaran@999 13856 <title>Managing patches in a repository</title>
belaran@999 13857
belaran@999 13858 <para id="x_423">Because MQ's <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory resides
belaran@999 13859 outside a Mercurial repository's working directory, the
belaran@999 13860 <quote>underlying</quote> Mercurial repository knows nothing
belaran@999 13861 about the management or presence of patches.</para>
belaran@999 13862
belaran@999 13863 <para id="x_424">This presents the interesting possibility of managing the
belaran@999 13864 contents of the patch directory as a Mercurial repository in its
belaran@999 13865 own right. This can be a useful way to work. For example, you
belaran@999 13866 can work on a patch for a while, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> it, then <command role="hg-cmd" moreinfo="none">hg commit</command> the current state of the
belaran@999 13867 patch. This lets you <quote>roll back</quote> to that version
belaran@999 13868 of the patch later on.</para>
belaran@999 13869
belaran@999 13870 <para id="x_425">You can then share different versions of the same patch
belaran@999 13871 stack among multiple underlying repositories. I use this when I
belaran@999 13872 am developing a Linux kernel feature. I have a pristine copy of
belaran@999 13873 my kernel sources for each of several CPU architectures, and a
belaran@999 13874 cloned repository under each that contains the patches I am
belaran@999 13875 working on. When I want to test a change on a different
belaran@999 13876 architecture, I push my current patches to the patch repository
belaran@999 13877 associated with that kernel tree, pop and push all of my
belaran@999 13878 patches, and build and test that kernel.</para>
belaran@999 13879
belaran@999 13880 <para id="x_426">Managing patches in a repository makes it possible for
belaran@999 13881 multiple developers to work on the same patch series without
belaran@999 13882 colliding with each other, all on top of an underlying source
belaran@999 13883 base that they may or may not control.</para>
belaran@999 13884
belaran@999 13885 <sect2>
belaran@999 13886 <title>MQ support for patch repositories</title>
belaran@999 13887
belaran@999 13888 <para id="x_427">MQ helps you to work with the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a
belaran@999 13889 repository; when you prepare a repository for working with
belaran@999 13890 patches using <command role="hg-ext-mq" moreinfo="none">qinit</command>, you
belaran@999 13891 can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg
belaran@999 13892 -c</option> option to create the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a
belaran@999 13893 Mercurial repository.</para>
belaran@999 13894
belaran@999 13895 <note>
belaran@999 13896 <para id="x_428"> If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you
belaran@999 13897 can simply go into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory at any
belaran@999 13898 time and run <command role="hg-cmd" moreinfo="none">hg init</command>.
belaran@999 13899 Don't forget to add an entry for the <filename role="special" moreinfo="none">status</filename> file to the <filename role="special" moreinfo="none">.hgignore</filename> file, though</para>
belaran@999 13900
belaran@999 13901 <para id="x_429"> (<command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command>
belaran@999 13902 does this for you automatically); you
belaran@999 13903 <emphasis>really</emphasis> don't want to manage the
belaran@999 13904 <filename role="special" moreinfo="none">status</filename> file.</para>
belaran@999 13905 </note>
belaran@999 13906
belaran@999 13907 <para id="x_42a">As a convenience, if MQ notices that the <filename class="directory" moreinfo="none">.hg/patches</filename> directory is a
belaran@999 13908 repository, it will automatically <command role="hg-cmd" moreinfo="none">hg
belaran@999 13909 add</command> every patch that you create and import.</para>
belaran@999 13910
belaran@999 13911 <para id="x_42b">MQ provides a shortcut command, <command role="hg-ext-mq" moreinfo="none">qcommit</command>, that runs <command role="hg-cmd" moreinfo="none">hg commit</command> in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
belaran@999 13912 directory. This saves some bothersome typing.</para>
belaran@999 13913
belaran@999 13914 <para id="x_42c">Finally, as a convenience to manage the patch directory,
belaran@999 13915 you can define the alias <command moreinfo="none">mq</command> on Unix
belaran@999 13916 systems. For example, on Linux systems using the
belaran@999 13917 <command moreinfo="none">bash</command> shell, you can include the following
belaran@999 13918 snippet in your <filename role="home" moreinfo="none">~/.bashrc</filename>.</para>
belaran@999 13919
belaran@999 13920 <programlisting format="linespecific">alias mq=`hg -R $(hg root)/.hg/patches'</programlisting>
belaran@999 13921
belaran@999 13922 <para id="x_42d">You can then issue commands of the form <command moreinfo="none">mq
belaran@999 13923 pull</command> from the main repository.</para>
belaran@999 13924 </sect2>
belaran@999 13925
belaran@999 13926 <sect2>
belaran@999 13927 <title>A few things to watch out for</title>
belaran@999 13928
belaran@999 13929 <para id="x_42e">MQ's support for working with a repository full of patches
belaran@999 13930 is limited in a few small respects.</para>
belaran@999 13931
belaran@999 13932 <para id="x_42f">MQ cannot automatically detect changes that you make to
belaran@999 13933 the patch directory. If you <command role="hg-cmd" moreinfo="none">hg
belaran@999 13934 pull</command>, manually edit, or <command role="hg-cmd" moreinfo="none">hg
belaran@999 13935 update</command> changes to patches or the <filename role="special" moreinfo="none">series</filename> file, you will have to
belaran@999 13936 <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and
belaran@999 13937 then <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in
belaran@999 13938 the underlying repository to see those changes show up there.
belaran@999 13939 If you forget to do this, you can confuse MQ's idea of which
belaran@999 13940 patches are applied.</para>
belaran@999 13941
belaran@999 13942 </sect2>
belaran@999 13943 </sect1>
belaran@999 13944 <sect1 id="sec:mq:tools">
belaran@999 13945 <title>Third party tools for working with patches</title>
belaran@999 13946
belaran@999 13947 <para id="x_430">Once you've been working with patches for a while, you'll
belaran@999 13948 find yourself hungry for tools that will help you to understand
belaran@999 13949 and manipulate the patches you're dealing with.</para>
belaran@999 13950
belaran@999 13951 <para id="x_431">The <command moreinfo="none">diffstat</command> command
belaran@999 13952 <citation>web:diffstat</citation> generates a histogram of the
belaran@999 13953 modifications made to each file in a patch. It provides a good
belaran@999 13954 way to <quote>get a sense of</quote> a patch—which files
belaran@999 13955 it affects, and how much change it introduces to each file and
belaran@999 13956 as a whole. (I find that it's a good idea to use
belaran@999 13957 <command moreinfo="none">diffstat</command>'s <option role="cmd-opt-diffstat">-p</option> option as a matter of
belaran@999 13958 course, as otherwise it will try to do clever things with
belaran@999 13959 prefixes of file names that inevitably confuse at least
belaran@999 13960 me.)</para>
belaran@999 13961
belaran@999 13962 <!-- BEGIN mq.tools.tools -->
belaran@999 13963 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diffstat -p1 remove-redundant-null-checks.patch</userinput>
belaran@999 13964 drivers/char/agp/sgi-agp.c | 5 ++---
belaran@999 13965 drivers/char/hvcs.c | 11 +++++------
belaran@999 13966 drivers/message/fusion/mptfc.c | 6 ++----
belaran@999 13967 drivers/message/fusion/mptsas.c | 3 +--
belaran@999 13968 drivers/net/fs_enet/fs_enet-mii.c | 3 +--
belaran@999 13969 drivers/net/wireless/ipw2200.c | 22 ++++++----------------
belaran@999 13970 drivers/scsi/libata-scsi.c | 4 +---
belaran@999 13971 drivers/video/au1100fb.c | 3 +--
belaran@999 13972 8 files changed, 19 insertions(+), 38 deletions(-)
belaran@999 13973 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">filterdiff -i '*/video/*' remove-redundant-null-checks.patch</userinput>
belaran@999 13974 --- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers
belaran@999 13975 +++ a/drivers/video/au1100fb.c
belaran@999 13976 @@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
belaran@999 13977 {
belaran@999 13978 driver_unregister(&amp;au1100fb_driver);
belaran@999 13979
belaran@999 13980 - if (drv_info.opt_mode)
belaran@999 13981 - kfree(drv_info.opt_mode);
belaran@999 13982 + kfree(drv_info.opt_mode);
belaran@999 13983 }
belaran@999 13984
belaran@999 13985 module_init(au1100fb_init);
belaran@999 13986 </screen>
belaran@999 13987 <!-- END mq.tools.tools -->
belaran@999 13988
belaran@999 13989
belaran@999 13990 <para id="x_432">The <literal role="package" moreinfo="none">patchutils</literal> package
belaran@999 13991 <citation>web:patchutils</citation> is invaluable. It provides a
belaran@999 13992 set of small utilities that follow the <quote>Unix
belaran@999 13993 philosophy;</quote> each does one useful thing with a patch.
belaran@999 13994 The <literal role="package" moreinfo="none">patchutils</literal> command I use
belaran@999 13995 most is <command moreinfo="none">filterdiff</command>, which extracts subsets
belaran@999 13996 from a patch file. For example, given a patch that modifies
belaran@999 13997 hundreds of files across dozens of directories, a single
belaran@999 13998 invocation of <command moreinfo="none">filterdiff</command> can generate a
belaran@999 13999 smaller patch that only touches files whose names match a
belaran@999 14000 particular glob pattern. See <xref linkend="mq-collab:tips:interdiff"/> for another
belaran@999 14001 example.</para>
belaran@999 14002
belaran@999 14003 </sect1>
belaran@999 14004 <sect1>
belaran@999 14005 <title>Good ways to work with patches</title>
belaran@999 14006
belaran@999 14007 <para id="x_433">Whether you are working on a patch series to submit to a
belaran@999 14008 free software or open source project, or a series that you
belaran@999 14009 intend to treat as a sequence of regular changesets when you're
belaran@999 14010 done, you can use some simple techniques to keep your work well
belaran@999 14011 organized.</para>
belaran@999 14012
belaran@999 14013 <para id="x_434">Give your patches descriptive names. A good name for a
belaran@999 14014 patch might be <filename moreinfo="none">rework-device-alloc.patch</filename>,
belaran@999 14015 because it will immediately give you a hint what the purpose of
belaran@999 14016 the patch is. Long names shouldn't be a problem; you won't be
belaran@999 14017 typing the names often, but you <emphasis>will</emphasis> be
belaran@999 14018 running commands like <command role="hg-ext-mq" moreinfo="none">qapplied</command> and <command role="hg-ext-mq" moreinfo="none">qtop</command> over and over. Good naming
belaran@999 14019 becomes especially important when you have a number of patches
belaran@999 14020 to work with, or if you are juggling a number of different tasks
belaran@999 14021 and your patches only get a fraction of your attention.</para>
belaran@999 14022
belaran@999 14023 <para id="x_435">Be aware of what patch you're working on. Use the <command role="hg-ext-mq" moreinfo="none">qtop</command> command and skim over the text
belaran@999 14024 of your patches frequently—for example, using <command role="hg-cmd" moreinfo="none">hg tip <option role="hg-opt-tip">-p</option></command>)—to be sure
belaran@999 14025 of where you stand. I have several times worked on and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>ed a patch other than the
belaran@999 14026 one I intended, and it's often tricky to migrate changes into
belaran@999 14027 the right patch after making them in the wrong one.</para>
belaran@999 14028
belaran@999 14029 <para id="x_436">For this reason, it is very much worth investing a little
belaran@999 14030 time to learn how to use some of the third-party tools I
belaran@999 14031 described in <xref linkend="sec:mq:tools"/>,
belaran@999 14032 particularly
belaran@999 14033 <command moreinfo="none">diffstat</command> and <command moreinfo="none">filterdiff</command>.
belaran@999 14034 The former will give you a quick idea of what changes your patch
belaran@999 14035 is making, while the latter makes it easy to splice hunks
belaran@999 14036 selectively out of one patch and into another.</para>
belaran@999 14037
belaran@999 14038 </sect1>
belaran@999 14039 <sect1>
belaran@999 14040 <title>MQ cookbook</title>
belaran@999 14041
belaran@999 14042 <sect2>
belaran@999 14043 <title>Manage <quote>trivial</quote> patches</title>
belaran@999 14044
belaran@999 14045 <para id="x_437">Because the overhead of dropping files into a new
belaran@999 14046 Mercurial repository is so low, it makes a lot of sense to
belaran@999 14047 manage patches this way even if you simply want to make a few
belaran@999 14048 changes to a source tarball that you downloaded.</para>
belaran@999 14049
belaran@999 14050 <para id="x_438">Begin by downloading and unpacking the source tarball, and
belaran@999 14051 turning it into a Mercurial repository.</para>
belaran@999 14052
belaran@999 14053 <!-- BEGIN mq.tarball.download -->
belaran@999 14054 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.5.tar.bz2</userinput>
belaran@999 14055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.5.tar.bz2</userinput>
belaran@999 14056 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.5</userinput>
belaran@999 14057 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init</userinput>
belaran@999 14058 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -q --addremove --message netplug-1.2.5</userinput>
belaran@999 14059 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 14060 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug</userinput>
belaran@999 14061 updating working directory
belaran@999 14062 18 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 14063 </screen>
belaran@999 14064 <!-- END mq.tarball.download -->
belaran@999 14065
belaran@999 14066
belaran@999 14067 <para id="x_439">Continue by creating a patch stack and making your
belaran@999 14068 changes.</para>
belaran@999 14069
belaran@999 14070 <!-- BEGIN mq.tarball.qinit -->
belaran@999 14071 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug</userinput>
belaran@999 14072 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
belaran@999 14073 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -m 'fix build problem with gcc 4' build-fix.patch</userinput>
belaran@999 14074 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c</userinput>
belaran@999 14075 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 14076 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -p</userinput>
belaran@999 14077 changeset: 1:eeab56666c54
belaran@999 14078 tag: qtip
belaran@999 14079 tag: build-fix.patch
belaran@999 14080 tag: tip
belaran@999 14081 tag: qbase
belaran@999 14082 user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
belaran@999 14083 date: Sun Aug 16 14:05:10 2009 +0000
belaran@999 14084 summary: fix build problem with gcc 4
belaran@999 14085
belaran@999 14086 diff -r 1f6afe9a2d68 -r eeab56666c54 netlink.c
belaran@999 14087 --- a/netlink.c Sun Aug 16 14:05:09 2009 +0000
belaran@999 14088 +++ b/netlink.c Sun Aug 16 14:05:10 2009 +0000
belaran@999 14089 @@ -275,7 +275,7 @@
belaran@999 14090 exit(1);
belaran@999 14091 }
belaran@999 14092
belaran@999 14093 - int addr_len = sizeof(addr);
belaran@999 14094 + socklen_t addr_len = sizeof(addr);
belaran@999 14095
belaran@999 14096 if (getsockname(fd, (struct sockaddr *) &amp;addr, &amp;addr_len) == -1) {
belaran@999 14097 do_log(LOG_ERR, "Could not get socket details: %m");
belaran@999 14098
belaran@999 14099 </screen>
belaran@999 14100 <!-- END mq.tarball.qinit -->
belaran@999 14101
belaran@999 14102
belaran@999 14103 <para id="x_43a">Let's say a few weeks or months pass, and your package
belaran@999 14104 author releases a new version. First, bring their changes
belaran@999 14105 into the repository.</para>
belaran@999 14106
belaran@999 14107 <!-- BEGIN mq.tarball.newsource -->
belaran@999 14108 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
belaran@999 14109 patch queue now empty
belaran@999 14110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 14111 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.8.tar.bz2</userinput>
belaran@999 14112 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug-1.2.8</userinput>
belaran@999 14113 updating working directory
belaran@999 14114 18 files updated, 0 files merged, 0 files removed, 0 files unresolved
belaran@999 14115 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput>
belaran@999 14116 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg locate -0 | xargs -0 rm</userinput>
belaran@999 14117 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
belaran@999 14118 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.8.tar.bz2</userinput>
belaran@999 14119 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput>
belaran@999 14120 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit --addremove --message netplug-1.2.8</userinput>
belaran@999 14121 </screen>
belaran@999 14122 <!-- END mq.tarball.newsource -->
belaran@999 14123
belaran@999 14124
belaran@999 14125 <para id="x_43b">The pipeline starting with <command role="hg-cmd" moreinfo="none">hg
belaran@999 14126 locate</command> above deletes all files in the working
belaran@999 14127 directory, so that <command role="hg-cmd" moreinfo="none">hg
belaran@999 14128 commit</command>'s <option role="hg-opt-commit">--addremove</option> option can
belaran@999 14129 actually tell which files have really been removed in the
belaran@999 14130 newer version of the source.</para>
belaran@999 14131
belaran@999 14132 <para id="x_43c">Finally, you can apply your patches on top of the new
belaran@999 14133 tree.</para>
belaran@999 14134
belaran@999 14135 <!-- BEGIN mq.tarball.repush -->
belaran@999 14136 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../netplug</userinput>
belaran@999 14137 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../netplug-1.2.8</userinput>
belaran@999 14138 pulling from ../netplug-1.2.8
belaran@999 14139 searching for changes
belaran@999 14140 adding changesets
belaran@999 14141 adding manifests
belaran@999 14142 adding file changes
belaran@999 14143 added 1 changesets with 12 changes to 12 files
belaran@999 14144 (run 'hg update' to get a working copy)
belaran@999 14145 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
belaran@999 14146 (working directory not at tip)
belaran@999 14147 applying build-fix.patch
belaran@999 14148 now at: build-fix.patch
belaran@999 14149 </screen>
belaran@999 14150 <!-- END mq.tarball.repush -->
belaran@999 14151
belaran@999 14152 </sect2>
belaran@999 14153
belaran@999 14154 <sect2 id="sec:mq:combine">
belaran@999 14155 <title>Combining entire patches</title>
belaran@999 14156
belaran@999 14157 <para id="x_43d">MQ provides a command, <command role="hg-ext-mq" moreinfo="none">qfold</command> that lets you combine
belaran@999 14158 entire patches. This <quote>folds</quote> the patches you
belaran@999 14159 name, in the order you name them, into the topmost applied
belaran@999 14160 patch, and concatenates their descriptions onto the end of its
belaran@999 14161 description. The patches that you fold must be unapplied
belaran@999 14162 before you fold them.</para>
belaran@999 14163
belaran@999 14164 <para id="x_43e">The order in which you fold patches matters. If your
belaran@999 14165 topmost applied patch is <literal moreinfo="none">foo</literal>, and you
belaran@999 14166 <command role="hg-ext-mq" moreinfo="none">qfold</command>
belaran@999 14167 <literal moreinfo="none">bar</literal> and <literal moreinfo="none">quux</literal> into it,
belaran@999 14168 you will end up with a patch that has the same effect as if
belaran@999 14169 you applied first <literal moreinfo="none">foo</literal>, then
belaran@999 14170 <literal moreinfo="none">bar</literal>, followed by
belaran@999 14171 <literal moreinfo="none">quux</literal>.</para>
belaran@999 14172 </sect2>
belaran@999 14173
belaran@999 14174 <sect2>
belaran@999 14175 <title>Merging part of one patch into another</title>
belaran@999 14176
belaran@999 14177 <para id="x_43f">Merging <emphasis>part</emphasis> of one patch into
belaran@999 14178 another is more difficult than combining entire
belaran@999 14179 patches.</para>
belaran@999 14180
belaran@999 14181 <para id="x_440">If you want to move changes to entire files, you can use
belaran@999 14182 <command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">-i</option> and <option role="cmd-opt-filterdiff">-x</option> options to choose the
belaran@999 14183 modifications to snip out of one patch, concatenating its
belaran@999 14184 output onto the end of the patch you want to merge into. You
belaran@999 14185 usually won't need to modify the patch you've merged the
belaran@999 14186 changes from. Instead, MQ will report some rejected hunks
belaran@999 14187 when you <command role="hg-ext-mq" moreinfo="none">qpush</command> it (from
belaran@999 14188 the hunks you moved into the other patch), and you can simply
belaran@999 14189 <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the patch to drop
belaran@999 14190 the duplicate hunks.</para>
belaran@999 14191
belaran@999 14192 <para id="x_441">If you have a patch that has multiple hunks modifying a
belaran@999 14193 file, and you only want to move a few of those hunks, the job
belaran@999 14194 becomes more messy, but you can still partly automate it. Use
belaran@999 14195 <command moreinfo="none">lsdiff -nvv</command> to print some metadata about
belaran@999 14196 the patch.</para>
belaran@999 14197
belaran@999 14198 <!-- BEGIN mq.tools.lsdiff -->
belaran@999 14199 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">lsdiff -nvv remove-redundant-null-checks.patch</userinput>
belaran@999 14200 22 File #1 a/drivers/char/agp/sgi-agp.c
belaran@999 14201 24 Hunk #1 static int __devinit agp_sgi_init(void)
belaran@999 14202 37 File #2 a/drivers/char/hvcs.c
belaran@999 14203 39 Hunk #1 static struct tty_operations hvcs_ops =
belaran@999 14204 53 Hunk #2 static int hvcs_alloc_index_list(int n)
belaran@999 14205 69 File #3 a/drivers/message/fusion/mptfc.c
belaran@999 14206 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
belaran@999 14207 85 File #4 a/drivers/message/fusion/mptsas.c
belaran@999 14208 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
belaran@999 14209 98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c
belaran@999 14210 100 Hunk #1 static struct fs_enet_mii_bus *create_bu
belaran@999 14211 111 File #6 a/drivers/net/wireless/ipw2200.c
belaran@999 14212 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er
belaran@999 14213 126 Hunk #2 static ssize_t clear_error(struct device
belaran@999 14214 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p
belaran@999 14215 150 Hunk #4 static void ipw_pci_remove(struct pci_de
belaran@999 14216 164 File #7 a/drivers/scsi/libata-scsi.c
belaran@999 14217 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc
belaran@999 14218 178 File #8 a/drivers/video/au1100fb.c
belaran@999 14219 180 Hunk #1 void __exit au1100fb_cleanup(void)
belaran@999 14220 </screen>
belaran@999 14221 <!-- END mq.tools.lsdiff -->
belaran@999 14222
belaran@999 14223
belaran@999 14224 <para id="x_442">This command prints three different kinds of
belaran@999 14225 number:</para>
belaran@999 14226 <itemizedlist>
belaran@999 14227 <listitem><para id="x_443">(in the first column) a <emphasis>file
belaran@999 14228 number</emphasis> to identify each file modified in the
belaran@999 14229 patch;</para>
belaran@999 14230 </listitem>
belaran@999 14231 <listitem><para id="x_444">(on the next line, indented) the line number
belaran@999 14232 within a modified file where a hunk starts; and</para>
belaran@999 14233 </listitem>
belaran@999 14234 <listitem><para id="x_445">(on the same line) a <emphasis>hunk
belaran@999 14235 number</emphasis> to identify that hunk.</para>
belaran@999 14236 </listitem></itemizedlist>
belaran@999 14237
belaran@999 14238 <para id="x_446">You'll have to use some visual inspection, and reading of
belaran@999 14239 the patch, to identify the file and hunk numbers you'll want,
belaran@999 14240 but you can then pass them to to
belaran@999 14241 <command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option> and <option role="cmd-opt-filterdiff">--hunks</option> options, to
belaran@999 14242 select exactly the file and hunk you want to extract.</para>
belaran@999 14243
belaran@999 14244 <para id="x_447">Once you have this hunk, you can concatenate it onto the
belaran@999 14245 end of your destination patch and continue with the remainder
belaran@999 14246 of <xref linkend="sec:mq:combine"/>.</para>
belaran@999 14247
belaran@999 14248 </sect2>
belaran@999 14249 </sect1>
belaran@999 14250 <sect1>
belaran@999 14251 <title>Differences between quilt and MQ</title>
belaran@999 14252
belaran@999 14253 <para id="x_448">If you are already familiar with quilt, MQ provides a
belaran@999 14254 similar command set. There are a few differences in the way
belaran@999 14255 that it works.</para>
belaran@999 14256
belaran@999 14257 <para id="x_449">You will already have noticed that most quilt commands have
belaran@999 14258 MQ counterparts that simply begin with a
belaran@999 14259 <quote><literal moreinfo="none">q</literal></quote>. The exceptions are quilt's
belaran@999 14260 <literal moreinfo="none">add</literal> and <literal moreinfo="none">remove</literal> commands,
belaran@999 14261 the counterparts for which are the normal Mercurial <command role="hg-cmd" moreinfo="none">hg add</command> and <command role="hg-cmd" moreinfo="none">hg
belaran@999 14262 remove</command> commands. There is no MQ equivalent of the
belaran@999 14263 quilt <literal moreinfo="none">edit</literal> command.</para>
belaran@999 14264
belaran@999 14265 </sect1>
belaran@999 14266 </chapter>
belaran@999 14267
belaran@999 14268 <!--
belaran@999 14269 local variables:
belaran@999 14270 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 14271 end:
belaran@999 14272 -->
belaran@999 14273
belaran@999 14274 <!-- BEGIN ch13 -->
belaran@999 14275 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 14276
belaran@999 14277 <chapter id="chap:mq-collab">
belaran@999 14278 <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?>
belaran@999 14279 <title>Advanced uses of Mercurial Queues</title>
belaran@999 14280
belaran@999 14281 <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial
belaran@999 14282 Queues, use of a little discipline and some of MQ's less
belaran@999 14283 frequently used capabilities makes it possible to work in
belaran@999 14284 complicated development environments.</para>
belaran@999 14285
belaran@999 14286 <para id="x_15e">In this chapter, I will use as an example a technique I have
belaran@999 14287 used to manage the development of an Infiniband device driver for
belaran@999 14288 the Linux kernel. The driver in question is large (at least as
belaran@999 14289 drivers go), with 25,000 lines of code spread across 35 source
belaran@999 14290 files. It is maintained by a small team of developers.</para>
belaran@999 14291
belaran@999 14292 <para id="x_15f">While much of the material in this chapter is specific to
belaran@999 14293 Linux, the same principles apply to any code base for which you're
belaran@999 14294 not the primary owner, and upon which you need to do a lot of
belaran@999 14295 development.</para>
belaran@999 14296
belaran@999 14297 <sect1>
belaran@999 14298 <title>The problem of many targets</title>
belaran@999 14299
belaran@999 14300 <para id="x_160">The Linux kernel changes rapidly, and has never been
belaran@999 14301 internally stable; developers frequently make drastic changes
belaran@999 14302 between releases. This means that a version of the driver that
belaran@999 14303 works well with a particular released version of the kernel will
belaran@999 14304 not even <emphasis>compile</emphasis> correctly against,
belaran@999 14305 typically, any other version.</para>
belaran@999 14306
belaran@999 14307 <para id="x_161">To maintain a driver, we have to keep a number of distinct
belaran@999 14308 versions of Linux in mind.</para>
belaran@999 14309 <itemizedlist>
belaran@999 14310 <listitem><para id="x_162">One target is the main Linux kernel development
belaran@999 14311 tree. Maintenance of the code is in this case partly shared
belaran@999 14312 by other developers in the kernel community, who make
belaran@999 14313 <quote>drive-by</quote> modifications to the driver as they
belaran@999 14314 develop and refine kernel subsystems.</para>
belaran@999 14315 </listitem>
belaran@999 14316 <listitem><para id="x_163">We also maintain a number of
belaran@999 14317 <quote>backports</quote> to older versions of the Linux
belaran@999 14318 kernel, to support the needs of customers who are running
belaran@999 14319 older Linux distributions that do not incorporate our
belaran@999 14320 drivers. (To <emphasis>backport</emphasis> a piece of code
belaran@999 14321 is to modify it to work in an older version of its target
belaran@999 14322 environment than the version it was developed for.)</para>
belaran@999 14323 </listitem>
belaran@999 14324 <listitem><para id="x_164">Finally, we make software releases on a schedule
belaran@999 14325 that is necessarily not aligned with those used by Linux
belaran@999 14326 distributors and kernel developers, so that we can deliver
belaran@999 14327 new features to customers without forcing them to upgrade
belaran@999 14328 their entire kernels or distributions.</para>
belaran@999 14329 </listitem></itemizedlist>
belaran@999 14330
belaran@999 14331 <sect2>
belaran@999 14332 <title>Tempting approaches that don't work well</title>
belaran@999 14333
belaran@999 14334 <para id="x_165">There are two <quote>standard</quote> ways to maintain a
belaran@999 14335 piece of software that has to target many different
belaran@999 14336 environments.</para>
belaran@999 14337
belaran@999 14338 <para id="x_166">The first is to maintain a number of branches, each
belaran@999 14339 intended for a single target. The trouble with this approach
belaran@999 14340 is that you must maintain iron discipline in the flow of
belaran@999 14341 changes between repositories. A new feature or bug fix must
belaran@999 14342 start life in a <quote>pristine</quote> repository, then
belaran@999 14343 percolate out to every backport repository. Backport changes
belaran@999 14344 are more limited in the branches they should propagate to; a
belaran@999 14345 backport change that is applied to a branch where it doesn't
belaran@999 14346 belong will probably stop the driver from compiling.</para>
belaran@999 14347
belaran@999 14348 <para id="x_167">The second is to maintain a single source tree filled with
belaran@999 14349 conditional statements that turn chunks of code on or off
belaran@999 14350 depending on the intended target. Because these
belaran@999 14351 <quote>ifdefs</quote> are not allowed in the Linux kernel
belaran@999 14352 tree, a manual or automatic process must be followed to strip
belaran@999 14353 them out and yield a clean tree. A code base maintained in
belaran@999 14354 this fashion rapidly becomes a rat's nest of conditional
belaran@999 14355 blocks that are difficult to understand and maintain.</para>
belaran@999 14356
belaran@999 14357 <para id="x_168">Neither of these approaches is well suited to a situation
belaran@999 14358 where you don't <quote>own</quote> the canonical copy of a
belaran@999 14359 source tree. In the case of a Linux driver that is
belaran@999 14360 distributed with the standard kernel, Linus's tree contains
belaran@999 14361 the copy of the code that will be treated by the world as
belaran@999 14362 canonical. The upstream version of <quote>my</quote> driver
belaran@999 14363 can be modified by people I don't know, without me even
belaran@999 14364 finding out about it until after the changes show up in
belaran@999 14365 Linus's tree.</para>
belaran@999 14366
belaran@999 14367 <para id="x_169">These approaches have the added weakness of making it
belaran@999 14368 difficult to generate well-formed patches to submit
belaran@999 14369 upstream.</para>
belaran@999 14370
belaran@999 14371 <para id="x_16a">In principle, Mercurial Queues seems like a good candidate
belaran@999 14372 to manage a development scenario such as the above. While
belaran@999 14373 this is indeed the case, MQ contains a few added features that
belaran@999 14374 make the job more pleasant.</para>
belaran@999 14375
belaran@999 14376 </sect2>
belaran@999 14377 </sect1>
belaran@999 14378 <sect1>
belaran@999 14379 <title>Conditionally applying patches with guards</title>
belaran@999 14380
belaran@999 14381 <para id="x_16b">Perhaps the best way to maintain sanity with so many targets
belaran@999 14382 is to be able to choose specific patches to apply for a given
belaran@999 14383 situation. MQ provides a feature called <quote>guards</quote>
belaran@999 14384 (which originates with quilt's <literal moreinfo="none">guards</literal>
belaran@999 14385 command) that does just this. To start off, let's create a
belaran@999 14386 simple repository for experimenting in.</para>
belaran@999 14387
belaran@999 14388 <!-- BEGIN mq.guards.init -->
belaran@999 14389 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
belaran@999 14390 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew hello.patch</userinput>
belaran@999 14391 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello &gt; hello</userinput>
belaran@999 14392 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add hello</userinput>
belaran@999 14393 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 14394 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew goodbye.patch</userinput>
belaran@999 14395 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye &gt; goodbye</userinput>
belaran@999 14396 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add goodbye</userinput>
belaran@999 14397 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
belaran@999 14398 </screen>
belaran@999 14399 <!-- END mq.guards.init -->
belaran@999 14400
belaran@999 14401
belaran@999 14402 <para id="x_16c">This gives us a tiny repository that contains two patches
belaran@999 14403 that don't have any dependencies on each other, because they
belaran@999 14404 touch different files.</para>
belaran@999 14405
belaran@999 14406 <para id="x_16d">The idea behind conditional application is that you can
belaran@999 14407 <quote>tag</quote> a patch with a <emphasis>guard</emphasis>,
belaran@999 14408 which is simply a text string of your choosing, then tell MQ to
belaran@999 14409 select specific guards to use when applying patches. MQ will
belaran@999 14410 then either apply, or skip over, a guarded patch, depending on
belaran@999 14411 the guards that you have selected.</para>
belaran@999 14412
belaran@999 14413 <para id="x_16e">A patch can have an arbitrary number of guards; each one is
belaran@999 14414 <emphasis>positive</emphasis> (<quote>apply this patch if this
belaran@999 14415 guard is selected</quote>) or <emphasis>negative</emphasis>
belaran@999 14416 (<quote>skip this patch if this guard is selected</quote>). A
belaran@999 14417 patch with no guards is always applied.</para>
belaran@999 14418
belaran@999 14419 </sect1>
belaran@999 14420 <sect1>
belaran@999 14421 <title>Controlling the guards on a patch</title>
belaran@999 14422
belaran@999 14423 <para id="x_16f">The <command role="hg-ext-mq" moreinfo="none">qguard</command> command lets
belaran@999 14424 you determine which guards should apply to a patch, or display
belaran@999 14425 the guards that are already in effect. Without any arguments, it
belaran@999 14426 displays the guards on the current topmost patch.</para>
belaran@999 14427
belaran@999 14428 <!-- BEGIN mq.guards.qguard -->
belaran@999 14429 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput>
belaran@999 14430 goodbye.patch: unguarded
belaran@999 14431 </screen>
belaran@999 14432 <!-- END mq.guards.qguard -->
belaran@999 14433
belaran@999 14434
belaran@999 14435 <para id="x_170">To set a positive guard on a patch, prefix the name of the
belaran@999 14436 guard with a <quote><literal moreinfo="none">+</literal></quote>.</para>
belaran@999 14437
belaran@999 14438 <!-- BEGIN mq.guards.qguard.pos -->
belaran@999 14439 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard +foo</userinput>
belaran@999 14440 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput>
belaran@999 14441 goodbye.patch: +foo
belaran@999 14442 </screen>
belaran@999 14443 <!-- END mq.guards.qguard.pos -->
belaran@999 14444
belaran@999 14445
belaran@999 14446 <para id="x_171">To set a negative guard
belaran@999 14447 on a patch, prefix the name of the guard with a
belaran@999 14448 <quote><literal moreinfo="none">-</literal></quote>.</para>
belaran@999 14449
belaran@999 14450 <!-- BEGIN mq.guards.qguard.neg -->
belaran@999 14451 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard -- hello.patch -quux</userinput>
belaran@999 14452 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard hello.patch</userinput>
belaran@999 14453 hello.patch: -quux
belaran@999 14454 </screen>
belaran@999 14455 <!-- END mq.guards.qguard.neg -->
belaran@999 14456
belaran@999 14457
belaran@999 14458 <para id="x_74a">Notice that we prefixed the arguments to the <command moreinfo="none">hg
belaran@999 14459 qguard</command> command with a <literal moreinfo="none">--</literal> here, so
belaran@999 14460 that Mercurial would not interpret the text
belaran@999 14461 <literal moreinfo="none">-quux</literal> as an option.</para>
belaran@999 14462
belaran@999 14463 <note>
belaran@999 14464 <title>Setting vs. modifying</title>
belaran@999 14465
belaran@999 14466 <para id="x_172"> The <command role="hg-ext-mq" moreinfo="none">qguard</command> command
belaran@999 14467 <emphasis>sets</emphasis> the guards on a patch; it doesn't
belaran@999 14468 <emphasis>modify</emphasis> them. What this means is that if
belaran@999 14469 you run <command role="hg-cmd" moreinfo="none">hg qguard +a +b</command> on a
belaran@999 14470 patch, then <command role="hg-cmd" moreinfo="none">hg qguard +c</command> on
belaran@999 14471 the same patch, the <emphasis>only</emphasis> guard that will
belaran@999 14472 be set on it afterwards is <literal moreinfo="none">+c</literal>.</para>
belaran@999 14473 </note>
belaran@999 14474
belaran@999 14475 <para id="x_173">Mercurial stores guards in the <filename role="special" moreinfo="none">series</filename> file; the form in which they
belaran@999 14476 are stored is easy both to understand and to edit by hand. (In
belaran@999 14477 other words, you don't have to use the <command role="hg-ext-mq" moreinfo="none">qguard</command> command if you don't want
belaran@999 14478 to; it's okay to simply edit the <filename role="special" moreinfo="none">series</filename> file.)</para>
belaran@999 14479
belaran@999 14480 <!-- BEGIN mq.guards.series -->
belaran@999 14481 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/series</userinput>
belaran@999 14482 hello.patch #-quux
belaran@999 14483 goodbye.patch #+foo
belaran@999 14484 </screen>
belaran@999 14485 <!-- END mq.guards.series -->
belaran@999 14486
belaran@999 14487
belaran@999 14488 </sect1>
belaran@999 14489 <sect1>
belaran@999 14490 <title>Selecting the guards to use</title>
belaran@999 14491
belaran@999 14492 <para id="x_174">The <command role="hg-ext-mq" moreinfo="none">qselect</command> command
belaran@999 14493 determines which guards are active at a given time. The effect
belaran@999 14494 of this is to determine which patches MQ will apply the next
belaran@999 14495 time you run <command role="hg-ext-mq" moreinfo="none">qpush</command>. It has
belaran@999 14496 no other effect; in particular, it doesn't do anything to
belaran@999 14497 patches that are already applied.</para>
belaran@999 14498
belaran@999 14499 <para id="x_175">With no arguments, the <command role="hg-ext-mq" moreinfo="none">qselect</command> command lists the guards
belaran@999 14500 currently in effect, one per line of output. Each argument is
belaran@999 14501 treated as the name of a guard to apply.</para>
belaran@999 14502
belaran@999 14503 <!-- BEGIN mq.guards.qselect.foo -->
belaran@999 14504 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
belaran@999 14505 patch queue now empty
belaran@999 14506 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput>
belaran@999 14507 no active guards
belaran@999 14508 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo</userinput>
belaran@999 14509 number of unguarded, unapplied patches has changed from 1 to 2
belaran@999 14510 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput>
belaran@999 14511 foo
belaran@999 14512 </screen>
belaran@999 14513 <!-- END mq.guards.qselect.foo -->
belaran@999 14514
belaran@999 14515
belaran@999 14516 <para id="x_176">In case you're interested, the currently selected guards are
belaran@999 14517 stored in the <filename role="special" moreinfo="none">guards</filename> file.</para>
belaran@999 14518
belaran@999 14519 <!-- BEGIN mq.guards.qselect.cat -->
belaran@999 14520 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/guards</userinput>
belaran@999 14521 foo
belaran@999 14522 </screen>
belaran@999 14523 <!-- END mq.guards.qselect.cat -->
belaran@999 14524
belaran@999 14525
belaran@999 14526 <para id="x_177">We can see the effect the selected guards have when we run
belaran@999 14527 <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para>
belaran@999 14528
belaran@999 14529 <!-- BEGIN mq.guards.qselect.qpush -->
belaran@999 14530 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
belaran@999 14531 applying hello.patch
belaran@999 14532 applying goodbye.patch
belaran@999 14533 now at: goodbye.patch
belaran@999 14534 </screen>
belaran@999 14535 <!-- END mq.guards.qselect.qpush -->
belaran@999 14536
belaran@999 14537
belaran@999 14538 <para id="x_178">A guard cannot start with a
belaran@999 14539 <quote><literal moreinfo="none">+</literal></quote> or
belaran@999 14540 <quote><literal moreinfo="none">-</literal></quote> character. The name of a
belaran@999 14541 guard must not contain white space, but most other characters
belaran@999 14542 are acceptable. If you try to use a guard with an invalid name,
belaran@999 14543 MQ will complain:</para>
belaran@999 14544
belaran@999 14545 <!-- BEGIN mq.guards.qselect.error -->
belaran@999 14546 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect +foo</userinput>
belaran@999 14547 abort: guard '+foo' starts with invalid character: '+'
belaran@999 14548 </screen>
belaran@999 14549 <!-- END mq.guards.qselect.error -->
belaran@999 14550
belaran@999 14551
belaran@999 14552 <para id="x_179">Changing the selected guards changes the patches that are
belaran@999 14553 applied.</para>
belaran@999 14554
belaran@999 14555 <!-- BEGIN mq.guards.qselect.quux -->
belaran@999 14556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect quux</userinput>
belaran@999 14557 number of guarded, applied patches has changed from 0 to 2
belaran@999 14558 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
belaran@999 14559 patch queue now empty
belaran@999 14560 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
belaran@999 14561 patch series already fully applied
belaran@999 14562 </screen>
belaran@999 14563 <!-- END mq.guards.qselect.quux -->
belaran@999 14564
belaran@999 14565
belaran@999 14566 <para id="x_17a">You can see in the example below that negative guards take
belaran@999 14567 precedence over positive guards.</para>
belaran@999 14568
belaran@999 14569 <!-- BEGIN mq.guards.qselect.foobar -->
belaran@999 14570 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo bar</userinput>
belaran@999 14571 number of unguarded, unapplied patches has changed from 0 to 2
belaran@999 14572 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
belaran@999 14573 no patches applied
belaran@999 14574 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
belaran@999 14575 applying hello.patch
belaran@999 14576 applying goodbye.patch
belaran@999 14577 now at: goodbye.patch
belaran@999 14578 </screen>
belaran@999 14579 <!-- END mq.guards.qselect.foobar -->
belaran@999 14580
belaran@999 14581
belaran@999 14582 </sect1>
belaran@999 14583 <sect1>
belaran@999 14584 <title>MQ's rules for applying patches</title>
belaran@999 14585
belaran@999 14586 <para id="x_17b">The rules that MQ uses when deciding whether to apply a
belaran@999 14587 patch are as follows.</para>
belaran@999 14588 <itemizedlist>
belaran@999 14589 <listitem><para id="x_17c">A patch that has no guards is always
belaran@999 14590 applied.</para>
belaran@999 14591 </listitem>
belaran@999 14592 <listitem><para id="x_17d">If the patch has any negative guard that matches
belaran@999 14593 any currently selected guard, the patch is skipped.</para>
belaran@999 14594 </listitem>
belaran@999 14595 <listitem><para id="x_17e">If the patch has any positive guard that matches
belaran@999 14596 any currently selected guard, the patch is applied.</para>
belaran@999 14597 </listitem>
belaran@999 14598 <listitem><para id="x_17f">If the patch has positive or negative guards,
belaran@999 14599 but none matches any currently selected guard, the patch is
belaran@999 14600 skipped.</para>
belaran@999 14601 </listitem></itemizedlist>
belaran@999 14602
belaran@999 14603 </sect1>
belaran@999 14604 <sect1>
belaran@999 14605 <title>Trimming the work environment</title>
belaran@999 14606
belaran@999 14607 <para id="x_180">In working on the device driver I mentioned earlier, I don't
belaran@999 14608 apply the patches to a normal Linux kernel tree. Instead, I use
belaran@999 14609 a repository that contains only a snapshot of the source files
belaran@999 14610 and headers that are relevant to Infiniband development. This
belaran@999 14611 repository is 1% the size of a kernel repository, so it's easier
belaran@999 14612 to work with.</para>
belaran@999 14613
belaran@999 14614 <para id="x_181">I then choose a <quote>base</quote> version on top of which
belaran@999 14615 the patches are applied. This is a snapshot of the Linux kernel
belaran@999 14616 tree as of a revision of my choosing. When I take the snapshot,
belaran@999 14617 I record the changeset ID from the kernel repository in the
belaran@999 14618 commit message. Since the snapshot preserves the
belaran@999 14619 <quote>shape</quote> and content of the relevant parts of the
belaran@999 14620 kernel tree, I can apply my patches on top of either my tiny
belaran@999 14621 repository or a normal kernel tree.</para>
belaran@999 14622
belaran@999 14623 <para id="x_182">Normally, the base tree atop which the patches apply should
belaran@999 14624 be a snapshot of a very recent upstream tree. This best
belaran@999 14625 facilitates the development of patches that can easily be
belaran@999 14626 submitted upstream with few or no modifications.</para>
belaran@999 14627
belaran@999 14628 </sect1>
belaran@999 14629 <sect1>
belaran@999 14630 <title>Dividing up the <filename role="special" moreinfo="none">series</filename>
belaran@999 14631 file</title>
belaran@999 14632
belaran@999 14633 <para id="x_183">I categorise the patches in the <filename role="special" moreinfo="none">series</filename> file into a number of logical
belaran@999 14634 groups. Each section of like patches begins with a block of
belaran@999 14635 comments that describes the purpose of the patches that
belaran@999 14636 follow.</para>
belaran@999 14637
belaran@999 14638 <para id="x_184">The sequence of patch groups that I maintain follows. The
belaran@999 14639 ordering of these groups is important; I'll describe why after I
belaran@999 14640 introduce the groups.</para>
belaran@999 14641 <itemizedlist>
belaran@999 14642 <listitem><para id="x_185">The <quote>accepted</quote> group. Patches that
belaran@999 14643 the development team has submitted to the maintainer of the
belaran@999 14644 Infiniband subsystem, and which he has accepted, but which
belaran@999 14645 are not present in the snapshot that the tiny repository is
belaran@999 14646 based on. These are <quote>read only</quote> patches,
belaran@999 14647 present only to transform the tree into a similar state as
belaran@999 14648 it is in the upstream maintainer's repository.</para>
belaran@999 14649 </listitem>
belaran@999 14650 <listitem><para id="x_186">The <quote>rework</quote> group. Patches that I
belaran@999 14651 have submitted, but that the upstream maintainer has
belaran@999 14652 requested modifications to before he will accept
belaran@999 14653 them.</para>
belaran@999 14654 </listitem>
belaran@999 14655 <listitem><para id="x_187">The <quote>pending</quote> group. Patches that
belaran@999 14656 I have not yet submitted to the upstream maintainer, but
belaran@999 14657 which we have finished working on. These will be <quote>read
belaran@999 14658 only</quote> for a while. If the upstream maintainer
belaran@999 14659 accepts them upon submission, I'll move them to the end of
belaran@999 14660 the <quote>accepted</quote> group. If he requests that I
belaran@999 14661 modify any, I'll move them to the beginning of the
belaran@999 14662 <quote>rework</quote> group.</para>
belaran@999 14663 </listitem>
belaran@999 14664 <listitem><para id="x_188">The <quote>in progress</quote> group. Patches
belaran@999 14665 that are actively being developed, and should not be
belaran@999 14666 submitted anywhere yet.</para>
belaran@999 14667 </listitem>
belaran@999 14668 <listitem><para id="x_189">The <quote>backport</quote> group. Patches that
belaran@999 14669 adapt the source tree to older versions of the kernel
belaran@999 14670 tree.</para>
belaran@999 14671 </listitem>
belaran@999 14672 <listitem><para id="x_18a">The <quote>do not ship</quote> group. Patches
belaran@999 14673 that for some reason should never be submitted upstream.
belaran@999 14674 For example, one such patch might change embedded driver
belaran@999 14675 identification strings to make it easier to distinguish, in
belaran@999 14676 the field, between an out-of-tree version of the driver and
belaran@999 14677 a version shipped by a distribution vendor.</para>
belaran@999 14678 </listitem></itemizedlist>
belaran@999 14679
belaran@999 14680 <para id="x_18b">Now to return to the reasons for ordering groups of patches
belaran@999 14681 in this way. We would like the lowest patches in the stack to
belaran@999 14682 be as stable as possible, so that we will not need to rework
belaran@999 14683 higher patches due to changes in context. Putting patches that
belaran@999 14684 will never be changed first in the <filename role="special" moreinfo="none">series</filename> file serves this
belaran@999 14685 purpose.</para>
belaran@999 14686
belaran@999 14687 <para id="x_18c">We would also like the patches that we know we'll need to
belaran@999 14688 modify to be applied on top of a source tree that resembles the
belaran@999 14689 upstream tree as closely as possible. This is why we keep
belaran@999 14690 accepted patches around for a while.</para>
belaran@999 14691
belaran@999 14692 <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote>
belaran@999 14693 patches float at the end of the <filename role="special" moreinfo="none">series</filename> file. The backport patches
belaran@999 14694 must be applied on top of all other patches, and the <quote>do
belaran@999 14695 not ship</quote> patches might as well stay out of harm's
belaran@999 14696 way.</para>
belaran@999 14697
belaran@999 14698 </sect1>
belaran@999 14699 <sect1>
belaran@999 14700 <title>Maintaining the patch series</title>
belaran@999 14701
belaran@999 14702 <para id="x_18e">In my work, I use a number of guards to control which
belaran@999 14703 patches are to be applied.</para>
belaran@999 14704
belaran@999 14705 <itemizedlist>
belaran@999 14706 <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with
belaran@999 14707 <literal moreinfo="none">accepted</literal>. I enable this guard most of
belaran@999 14708 the time. When I'm applying the patches on top of a tree
belaran@999 14709 where the patches are already present, I can turn this patch
belaran@999 14710 off, and the patches that follow it will apply
belaran@999 14711 cleanly.</para>
belaran@999 14712 </listitem>
belaran@999 14713 <listitem><para id="x_190">Patches that are <quote>finished</quote>, but
belaran@999 14714 not yet submitted, have no guards. If I'm applying the
belaran@999 14715 patch stack to a copy of the upstream tree, I don't need to
belaran@999 14716 enable any guards in order to get a reasonably safe source
belaran@999 14717 tree.</para>
belaran@999 14718 </listitem>
belaran@999 14719 <listitem><para id="x_191">Those patches that need reworking before being
belaran@999 14720 resubmitted are guarded with
belaran@999 14721 <literal moreinfo="none">rework</literal>.</para>
belaran@999 14722 </listitem>
belaran@999 14723 <listitem><para id="x_192">For those patches that are still under
belaran@999 14724 development, I use <literal moreinfo="none">devel</literal>.</para>
belaran@999 14725 </listitem>
belaran@999 14726 <listitem><para id="x_193">A backport patch may have several guards, one
belaran@999 14727 for each version of the kernel to which it applies. For
belaran@999 14728 example, a patch that backports a piece of code to 2.6.9
belaran@999 14729 will have a <literal moreinfo="none">2.6.9</literal> guard.</para>
belaran@999 14730 </listitem></itemizedlist>
belaran@999 14731 <para id="x_194">This variety of guards gives me considerable flexibility in
belaran@999 14732 determining what kind of source tree I want to end up with. For
belaran@999 14733 most situations, the selection of appropriate guards is
belaran@999 14734 automated during the build process, but I can manually tune the
belaran@999 14735 guards to use for less common circumstances.</para>
belaran@999 14736
belaran@999 14737 <sect2>
belaran@999 14738 <title>The art of writing backport patches</title>
belaran@999 14739
belaran@999 14740 <para id="x_195">Using MQ, writing a backport patch is a simple process.
belaran@999 14741 All such a patch has to do is modify a piece of code that uses
belaran@999 14742 a kernel feature not present in the older version of the
belaran@999 14743 kernel, so that the driver continues to work correctly under
belaran@999 14744 that older version.</para>
belaran@999 14745
belaran@999 14746 <para id="x_196">A useful goal when writing a good backport patch is to
belaran@999 14747 make your code look as if it was written for the older version
belaran@999 14748 of the kernel you're targeting. The less obtrusive the patch,
belaran@999 14749 the easier it will be to understand and maintain. If you're
belaran@999 14750 writing a collection of backport patches to avoid the
belaran@999 14751 <quote>rat's nest</quote> effect of lots of
belaran@999 14752 <literal moreinfo="none">#ifdef</literal>s (hunks of source code that are only
belaran@999 14753 used conditionally) in your code, don't introduce
belaran@999 14754 version-dependent <literal moreinfo="none">#ifdef</literal>s into the patches.
belaran@999 14755 Instead, write several patches, each of which makes
belaran@999 14756 unconditional changes, and control their application using
belaran@999 14757 guards.</para>
belaran@999 14758
belaran@999 14759 <para id="x_197">There are two reasons to divide backport patches into a
belaran@999 14760 distinct group, away from the <quote>regular</quote> patches
belaran@999 14761 whose effects they modify. The first is that intermingling the
belaran@999 14762 two makes it more difficult to use a tool like the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension to automate the
belaran@999 14763 process of submitting the patches to an upstream maintainer.
belaran@999 14764 The second is that a backport patch could perturb the context
belaran@999 14765 in which a subsequent regular patch is applied, making it
belaran@999 14766 impossible to apply the regular patch cleanly
belaran@999 14767 <emphasis>without</emphasis> the earlier backport patch
belaran@999 14768 already being applied.</para>
belaran@999 14769
belaran@999 14770 </sect2>
belaran@999 14771 </sect1>
belaran@999 14772 <sect1>
belaran@999 14773 <title>Useful tips for developing with MQ</title>
belaran@999 14774
belaran@999 14775 <sect2>
belaran@999 14776 <title>Organising patches in directories</title>
belaran@999 14777
belaran@999 14778 <para id="x_198">If you're working on a substantial project with MQ, it's
belaran@999 14779 not difficult to accumulate a large number of patches. For
belaran@999 14780 example, I have one patch repository that contains over 250
belaran@999 14781 patches.</para>
belaran@999 14782
belaran@999 14783 <para id="x_199">If you can group these patches into separate logical
belaran@999 14784 categories, you can if you like store them in different
belaran@999 14785 directories; MQ has no problems with patch names that contain
belaran@999 14786 path separators.</para>
belaran@999 14787
belaran@999 14788 </sect2>
belaran@999 14789 <sect2 id="mq-collab:tips:interdiff">
belaran@999 14790 <title>Viewing the history of a patch</title>
belaran@999 14791
belaran@999 14792 <para id="x_19a">If you're developing a set of patches over a long time,
belaran@999 14793 it's a good idea to maintain them in a repository, as
belaran@999 14794 discussed in <xref linkend="sec:mq:repo"/>. If you do
belaran@999 14795 so, you'll quickly
belaran@999 14796 discover that using the <command role="hg-cmd" moreinfo="none">hg
belaran@999 14797 diff</command> command to look at the history of changes to
belaran@999 14798 a patch is unworkable. This is in part because you're looking
belaran@999 14799 at the second derivative of the real code (a diff of a diff),
belaran@999 14800 but also because MQ adds noise to the process by modifying
belaran@999 14801 time stamps and directory names when it updates a
belaran@999 14802 patch.</para>
belaran@999 14803
belaran@999 14804 <para id="x_19b">However, you can use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension, which is bundled
belaran@999 14805 with Mercurial, to turn a diff of two versions of a patch into
belaran@999 14806 something readable. To do this, you will need a third-party
belaran@999 14807 package called <literal role="package" moreinfo="none">patchutils</literal>
belaran@999 14808 <citation>web:patchutils</citation>. This provides a command
belaran@999 14809 named <command moreinfo="none">interdiff</command>, which shows the
belaran@999 14810 differences between two diffs as a diff. Used on two versions
belaran@999 14811 of the same diff, it generates a diff that represents the diff
belaran@999 14812 from the first to the second version.</para>
belaran@999 14813
belaran@999 14814 <para id="x_19c">You can enable the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension in the usual way,
belaran@999 14815 by adding a line to the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your
belaran@999 14816 <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
belaran@999 14817 <programlisting format="linespecific">[extensions]
belaran@999 14818 extdiff =</programlisting>
belaran@999 14819 <para id="x_19d">The <command moreinfo="none">interdiff</command> command expects to be
belaran@999 14820 passed the names of two files, but the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension passes the program
belaran@999 14821 it runs a pair of directories, each of which can contain an
belaran@999 14822 arbitrary number of files. We thus need a small program that
belaran@999 14823 will run <command moreinfo="none">interdiff</command> on each pair of files in
belaran@999 14824 these two directories. This program is available as <filename role="special" moreinfo="none">hg-interdiff</filename> in the <filename class="directory" moreinfo="none">examples</filename> directory of the
belaran@999 14825 source code repository that accompanies this book. <!--
belaran@999 14826 &example.hg-interdiff; --></para>
belaran@999 14827
belaran@999 14828 <para id="x_19e">With the <filename role="special" moreinfo="none">hg-interdiff</filename>
belaran@999 14829 program in your shell's search path, you can run it as
belaran@999 14830 follows, from inside an MQ patch directory:</para>
belaran@999 14831 <programlisting format="linespecific">hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting>
belaran@999 14832 <para id="x_19f">Since you'll probably want to use this long-winded command
belaran@999 14833 a lot, you can get <literal role="hg-ext" moreinfo="none">hgext</literal> to
belaran@999 14834 make it available as a normal Mercurial command, again by
belaran@999 14835 editing your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
belaran@999 14836 <programlisting format="linespecific">[extdiff]
belaran@999 14837 cmd.interdiff = hg-interdiff</programlisting>
belaran@999 14838 <para id="x_1a0">This directs <literal role="hg-ext" moreinfo="none">hgext</literal> to
belaran@999 14839 make an <literal moreinfo="none">interdiff</literal> command available, so you
belaran@999 14840 can now shorten the previous invocation of <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> to something a
belaran@999 14841 little more wieldy.</para>
belaran@999 14842 <programlisting format="linespecific">hg interdiff -r A:B my-change.patch</programlisting>
belaran@999 14843
belaran@999 14844 <note>
belaran@999 14845 <para id="x_1a1"> The <command moreinfo="none">interdiff</command> command works well
belaran@999 14846 only if the underlying files against which versions of a
belaran@999 14847 patch are generated remain the same. If you create a patch,
belaran@999 14848 modify the underlying files, and then regenerate the patch,
belaran@999 14849 <command moreinfo="none">interdiff</command> may not produce useful
belaran@999 14850 output.</para>
belaran@999 14851 </note>
belaran@999 14852
belaran@999 14853 <para id="x_1a2">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is
belaran@999 14854 useful for more than merely improving the presentation of MQ
belaran@999 14855 patches. To read more about it, go to <xref linkend="sec:hgext:extdiff"/>.</para>
belaran@999 14856
belaran@999 14857 </sect2>
belaran@999 14858 </sect1>
belaran@999 14859 </chapter>
belaran@999 14860
belaran@999 14861 <!--
belaran@999 14862 local variables:
belaran@999 14863 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 14864 end:
belaran@999 14865 -->
belaran@999 14866
belaran@999 14867 <!-- BEGIN ch14 -->
belaran@999 14868 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 14869
belaran@999 14870 <chapter id="chap:hgext">
belaran@999 14871 <?dbhtml filename="adding-functionality-with-extensions.html"?>
belaran@999 14872 <title>Adding functionality with extensions</title>
belaran@999 14873
belaran@999 14874 <para id="x_4fe">While the core of Mercurial is quite complete from a
belaran@999 14875 functionality standpoint, it's deliberately shorn of fancy
belaran@999 14876 features. This approach of preserving simplicity keeps the
belaran@999 14877 software easy to deal with for both maintainers and users.</para>
belaran@999 14878
belaran@999 14879 <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible
belaran@999 14880 command set: you can add features to it as
belaran@999 14881 <emphasis>extensions</emphasis> (sometimes known as
belaran@999 14882 <emphasis>plugins</emphasis>). We've already discussed a few of
belaran@999 14883 these extensions in earlier chapters.</para>
belaran@999 14884 <itemizedlist>
belaran@999 14885 <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/>
belaran@999 14886 covers the <literal role="hg-ext" moreinfo="none">fetch</literal> extension;
belaran@999 14887 this combines pulling new changes and merging them with local
belaran@999 14888 changes into a single command, <command role="hg-ext-fetch" moreinfo="none">fetch</command>.</para>
belaran@999 14889 </listitem>
belaran@999 14890 <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered
belaran@999 14891 several extensions that are useful for hook-related
belaran@999 14892 functionality: <literal role="hg-ext" moreinfo="none">acl</literal> adds
belaran@999 14893 access control lists; <literal role="hg-ext" moreinfo="none">bugzilla</literal> adds integration with the
belaran@999 14894 Bugzilla bug tracking system; and <literal role="hg-ext" moreinfo="none">notify</literal> sends notification emails on
belaran@999 14895 new changes.</para>
belaran@999 14896 </listitem>
belaran@999 14897 <listitem><para id="x_502">The Mercurial Queues patch management extension is
belaran@999 14898 so invaluable that it merits two chapters and an appendix all
belaran@999 14899 to itself. <xref linkend="chap:mq"/> covers the
belaran@999 14900 basics; <xref linkend="chap:mq-collab"/> discusses advanced topics;
belaran@999 14901 and <xref linkend="chap:mqref"/> goes into detail on
belaran@999 14902 each
belaran@999 14903 command.</para>
belaran@999 14904 </listitem></itemizedlist>
belaran@999 14905
belaran@999 14906 <para id="x_503">In this chapter, we'll cover some of the other extensions that
belaran@999 14907 are available for Mercurial, and briefly touch on some of the
belaran@999 14908 machinery you'll need to know about if you want to write an
belaran@999 14909 extension of your own.</para>
belaran@999 14910 <itemizedlist>
belaran@999 14911 <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>,
belaran@999 14912 we'll discuss the possibility of <emphasis>huge</emphasis>
belaran@999 14913 performance improvements using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.</para>
belaran@999 14914 </listitem></itemizedlist>
belaran@999 14915
belaran@999 14916 <sect1 id="sec:hgext:inotify">
belaran@999 14917 <title>Improve performance with the <literal role="hg-ext" moreinfo="none">inotify</literal> extension</title>
belaran@999 14918
belaran@999 14919 <para id="x_505">Are you interested in having some of the most common
belaran@999 14920 Mercurial operations run as much as a hundred times faster?
belaran@999 14921 Read on!</para>
belaran@999 14922
belaran@999 14923 <para id="x_506">Mercurial has great performance under normal circumstances.
belaran@999 14924 For example, when you run the <command role="hg-cmd" moreinfo="none">hg
belaran@999 14925 status</command> command, Mercurial has to scan almost every
belaran@999 14926 directory and file in your repository so that it can display
belaran@999 14927 file status. Many other Mercurial commands need to do the same
belaran@999 14928 work behind the scenes; for example, the <command role="hg-cmd" moreinfo="none">hg diff</command> command uses the status
belaran@999 14929 machinery to avoid doing an expensive comparison operation on
belaran@999 14930 files that obviously haven't changed.</para>
belaran@999 14931
belaran@999 14932 <para id="x_507">Because obtaining file status is crucial to good
belaran@999 14933 performance, the authors of Mercurial have optimised this code
belaran@999 14934 to within an inch of its life. However, there's no avoiding the
belaran@999 14935 fact that when you run <command role="hg-cmd" moreinfo="none">hg
belaran@999 14936 status</command>, Mercurial is going to have to perform at
belaran@999 14937 least one expensive system call for each managed file to
belaran@999 14938 determine whether it's changed since the last time Mercurial
belaran@999 14939 checked. For a sufficiently large repository, this can take a
belaran@999 14940 long time.</para>
belaran@999 14941
belaran@999 14942 <para id="x_508">To put a number on the magnitude of this effect, I created a
belaran@999 14943 repository containing 150,000 managed files. I timed <command role="hg-cmd" moreinfo="none">hg status</command> as taking ten seconds to
belaran@999 14944 run, even when <emphasis>none</emphasis> of those files had been
belaran@999 14945 modified.</para>
belaran@999 14946
belaran@999 14947 <para id="x_509">Many modern operating systems contain a file notification
belaran@999 14948 facility. If a program signs up to an appropriate service, the
belaran@999 14949 operating system will notify it every time a file of interest is
belaran@999 14950 created, modified, or deleted. On Linux systems, the kernel
belaran@999 14951 component that does this is called
belaran@999 14952 <literal moreinfo="none">inotify</literal>.</para>
belaran@999 14953
belaran@999 14954 <para id="x_50a">Mercurial's <literal role="hg-ext" moreinfo="none">inotify</literal>
belaran@999 14955 extension talks to the kernel's <literal moreinfo="none">inotify</literal>
belaran@999 14956 component to optimise <command role="hg-cmd" moreinfo="none">hg status</command>
belaran@999 14957 commands. The extension has two components. A daemon sits in
belaran@999 14958 the background and receives notifications from the
belaran@999 14959 <literal moreinfo="none">inotify</literal> subsystem. It also listens for
belaran@999 14960 connections from a regular Mercurial command. The extension
belaran@999 14961 modifies Mercurial's behavior so that instead of scanning the
belaran@999 14962 filesystem, it queries the daemon. Since the daemon has perfect
belaran@999 14963 information about the state of the repository, it can respond
belaran@999 14964 with a result instantaneously, avoiding the need to scan every
belaran@999 14965 directory and file in the repository.</para>
belaran@999 14966
belaran@999 14967 <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as
belaran@999 14968 taking to run <command role="hg-cmd" moreinfo="none">hg status</command> on a
belaran@999 14969 150,000 file repository. With the <literal role="hg-ext" moreinfo="none">inotify</literal> extension enabled, the time
belaran@999 14970 dropped to 0.1 seconds, a factor of <emphasis>one
belaran@999 14971 hundred</emphasis> faster.</para>
belaran@999 14972
belaran@999 14973 <para id="x_50c">Before we continue, please pay attention to some
belaran@999 14974 caveats.</para>
belaran@999 14975 <itemizedlist>
belaran@999 14976 <listitem><para id="x_50d">The <literal role="hg-ext" moreinfo="none">inotify</literal>
belaran@999 14977 extension is Linux-specific. Because it interfaces directly
belaran@999 14978 to the Linux kernel's <literal moreinfo="none">inotify</literal> subsystem,
belaran@999 14979 it does not work on other operating systems.</para>
belaran@999 14980 </listitem>
belaran@999 14981 <listitem><para id="x_50e">It should work on any Linux distribution that
belaran@999 14982 was released after early 2005. Older distributions are
belaran@999 14983 likely to have a kernel that lacks
belaran@999 14984 <literal moreinfo="none">inotify</literal>, or a version of
belaran@999 14985 <literal moreinfo="none">glibc</literal> that does not have the necessary
belaran@999 14986 interfacing support.</para>
belaran@999 14987 </listitem>
belaran@999 14988 <listitem><para id="x_50f">Not all filesystems are suitable for use with
belaran@999 14989 the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.
belaran@999 14990 Network filesystems such as NFS are a non-starter, for
belaran@999 14991 example, particularly if you're running Mercurial on several
belaran@999 14992 systems, all mounting the same network filesystem. The
belaran@999 14993 kernel's <literal moreinfo="none">inotify</literal> system has no way of
belaran@999 14994 knowing about changes made on another system. Most local
belaran@999 14995 filesystems (e.g. ext3, XFS, ReiserFS) should work
belaran@999 14996 fine.</para>
belaran@999 14997 </listitem></itemizedlist>
belaran@999 14998
belaran@999 14999 <para id="x_510">The <literal role="hg-ext" moreinfo="none">inotify</literal> extension is
belaran@999 15000 not yet shipped with Mercurial as of May 2007, so it's a little
belaran@999 15001 more involved to set up than other extensions. But the
belaran@999 15002 performance improvement is worth it!</para>
belaran@999 15003
belaran@999 15004 <para id="x_511">The extension currently comes in two parts: a set of patches
belaran@999 15005 to the Mercurial source code, and a library of Python bindings
belaran@999 15006 to the <literal moreinfo="none">inotify</literal> subsystem.</para>
belaran@999 15007 <note>
belaran@999 15008 <para id="x_512"> There are <emphasis>two</emphasis> Python
belaran@999 15009 <literal moreinfo="none">inotify</literal> binding libraries. One of them is
belaran@999 15010 called <literal moreinfo="none">pyinotify</literal>, and is packaged by some
belaran@999 15011 Linux distributions as <literal moreinfo="none">python-inotify</literal>.
belaran@999 15012 This is <emphasis>not</emphasis> the one you'll need, as it is
belaran@999 15013 too buggy and inefficient to be practical.</para>
belaran@999 15014 </note>
belaran@999 15015 <para id="x_513">To get going, it's best to already have a functioning copy
belaran@999 15016 of Mercurial installed.</para>
belaran@999 15017 <note>
belaran@999 15018 <para id="x_514"> If you follow the instructions below, you'll be
belaran@999 15019 <emphasis>replacing</emphasis> and overwriting any existing
belaran@999 15020 installation of Mercurial that you might already have, using
belaran@999 15021 the latest <quote>bleeding edge</quote> Mercurial code. Don't
belaran@999 15022 say you weren't warned!</para>
belaran@999 15023 </note>
belaran@999 15024 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 15025 <listitem><para id="x_515">Clone the Python <literal moreinfo="none">inotify</literal>
belaran@999 15026 binding repository. Build and install it.</para>
belaran@999 15027 <programlisting format="linespecific">hg clone http://hg.kublai.com/python/inotify
belaran@999 15028 cd inotify
belaran@999 15029 python setup.py build --force
belaran@999 15030 sudo python setup.py install --skip-build</programlisting>
belaran@999 15031 </listitem>
belaran@999 15032 <listitem><para id="x_516">Clone the <filename class="directory" moreinfo="none">crew</filename> Mercurial repository.
belaran@999 15033 Clone the <literal role="hg-ext" moreinfo="none">inotify</literal> patch
belaran@999 15034 repository so that Mercurial Queues will be able to apply
belaran@999 15035 patches to your cope of the <filename class="directory" moreinfo="none">crew</filename> repository.</para>
belaran@999 15036 <programlisting format="linespecific">hg clone http://hg.intevation.org/mercurial/crew
belaran@999 15037 hg clone crew inotify
belaran@999 15038 hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting>
belaran@999 15039 </listitem>
belaran@999 15040 <listitem><para id="x_517">Make sure that you have the Mercurial Queues
belaran@999 15041 extension, <literal role="hg-ext" moreinfo="none">mq</literal>, enabled. If
belaran@999 15042 you've never used MQ, read <xref linkend="sec:mq:start"/> to get started
belaran@999 15043 quickly.</para>
belaran@999 15044 </listitem>
belaran@999 15045 <listitem><para id="x_518">Go into the <filename class="directory" moreinfo="none">inotify</filename> repo, and apply all
belaran@999 15046 of the <literal role="hg-ext" moreinfo="none">inotify</literal> patches
belaran@999 15047 using the <option role="hg-ext-mq-cmd-qpush-opt">hg
belaran@999 15048 -a</option> option to the <command role="hg-ext-mq" moreinfo="none">qpush</command> command.</para>
belaran@999 15049 <programlisting format="linespecific">cd inotify
belaran@999 15050 hg qpush -a</programlisting>
belaran@999 15051 </listitem>
belaran@999 15052 <listitem><para id="x_519"> If you get an error message from <command role="hg-ext-mq" moreinfo="none">qpush</command>, you should not continue.
belaran@999 15053 Instead, ask for help.</para>
belaran@999 15054 </listitem>
belaran@999 15055 <listitem><para id="x_51a">Build and install the patched version of
belaran@999 15056 Mercurial.</para>
belaran@999 15057 <programlisting format="linespecific">python setup.py build --force
belaran@999 15058 sudo python setup.py install --skip-build</programlisting>
belaran@999 15059 </listitem>
belaran@999 15060 </orderedlist>
belaran@999 15061 <para id="x_51b">Once you've build a suitably patched version of Mercurial,
belaran@999 15062 all you need to do to enable the <literal role="hg-ext" moreinfo="none">inotify</literal> extension is add an entry to
belaran@999 15063 your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
belaran@999 15064 <programlisting format="linespecific">[extensions] inotify =</programlisting>
belaran@999 15065 <para id="x_51c">When the <literal role="hg-ext" moreinfo="none">inotify</literal> extension
belaran@999 15066 is enabled, Mercurial will automatically and transparently start
belaran@999 15067 the status daemon the first time you run a command that needs
belaran@999 15068 status in a repository. It runs one status daemon per
belaran@999 15069 repository.</para>
belaran@999 15070
belaran@999 15071 <para id="x_51d">The status daemon is started silently, and runs in the
belaran@999 15072 background. If you look at a list of running processes after
belaran@999 15073 you've enabled the <literal role="hg-ext" moreinfo="none">inotify</literal>
belaran@999 15074 extension and run a few commands in different repositories,
belaran@999 15075 you'll thus see a few <literal moreinfo="none">hg</literal> processes sitting
belaran@999 15076 around, waiting for updates from the kernel and queries from
belaran@999 15077 Mercurial.</para>
belaran@999 15078
belaran@999 15079 <para id="x_51e">The first time you run a Mercurial command in a repository
belaran@999 15080 when you have the <literal role="hg-ext" moreinfo="none">inotify</literal>
belaran@999 15081 extension enabled, it will run with about the same performance
belaran@999 15082 as a normal Mercurial command. This is because the status
belaran@999 15083 daemon needs to perform a normal status scan so that it has a
belaran@999 15084 baseline against which to apply later updates from the kernel.
belaran@999 15085 However, <emphasis>every</emphasis> subsequent command that does
belaran@999 15086 any kind of status check should be noticeably faster on
belaran@999 15087 repositories of even fairly modest size. Better yet, the bigger
belaran@999 15088 your repository is, the greater a performance advantage you'll
belaran@999 15089 see. The <literal role="hg-ext" moreinfo="none">inotify</literal> daemon makes
belaran@999 15090 status operations almost instantaneous on repositories of all
belaran@999 15091 sizes!</para>
belaran@999 15092
belaran@999 15093 <para id="x_51f">If you like, you can manually start a status daemon using
belaran@999 15094 the <command role="hg-ext-inotify" moreinfo="none">inserve</command> command.
belaran@999 15095 This gives you slightly finer control over how the daemon ought
belaran@999 15096 to run. This command will of course only be available when the
belaran@999 15097 <literal role="hg-ext" moreinfo="none">inotify</literal> extension is
belaran@999 15098 enabled.</para>
belaran@999 15099
belaran@999 15100 <para id="x_520">When you're using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension, you should notice
belaran@999 15101 <emphasis>no difference at all</emphasis> in Mercurial's
belaran@999 15102 behavior, with the sole exception of status-related commands
belaran@999 15103 running a whole lot faster than they used to. You should
belaran@999 15104 specifically expect that commands will not print different
belaran@999 15105 output; neither should they give different results. If either of
belaran@999 15106 these situations occurs, please report a bug.</para>
belaran@999 15107
belaran@999 15108 </sect1>
belaran@999 15109 <sect1 id="sec:hgext:extdiff">
belaran@999 15110 <title>Flexible diff support with the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension</title>
belaran@999 15111
belaran@999 15112 <para id="x_521">Mercurial's built-in <command role="hg-cmd" moreinfo="none">hg
belaran@999 15113 diff</command> command outputs plaintext unified diffs.</para>
belaran@999 15114
belaran@999 15115 <!-- BEGIN extdiff.diff -->
belaran@999 15116 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
belaran@999 15117 diff -r 801b35c37d8b myfile
belaran@999 15118 --- a/myfile Sun Aug 16 14:05:02 2009 +0000
belaran@999 15119 +++ b/myfile Sun Aug 16 14:05:02 2009 +0000
belaran@999 15120 @@ -1,1 +1,2 @@
belaran@999 15121 The first line.
belaran@999 15122 +The second line.
belaran@999 15123 </screen>
belaran@999 15124 <!-- END extdiff.diff -->
belaran@999 15125
belaran@999 15126
belaran@999 15127 <para id="x_522">If you would like to use an external tool to display
belaran@999 15128 modifications, you'll want to use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension. This will let you
belaran@999 15129 use, for example, a graphical diff tool.</para>
belaran@999 15130
belaran@999 15131 <para id="x_523">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is
belaran@999 15132 bundled with Mercurial, so it's easy to set up. In the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your
belaran@999 15133 <filename role="special" moreinfo="none">~/.hgrc</filename>, simply add a
belaran@999 15134 one-line entry to enable the extension.</para>
belaran@999 15135 <programlisting format="linespecific">[extensions]
belaran@999 15136 extdiff =</programlisting>
belaran@999 15137 <para id="x_524">This introduces a command named <command role="hg-ext-extdiff" moreinfo="none">extdiff</command>, which by default uses
belaran@999 15138 your system's <command moreinfo="none">diff</command> command to generate a
belaran@999 15139 unified diff in the same form as the built-in <command role="hg-cmd" moreinfo="none">hg diff</command> command.</para>
belaran@999 15140
belaran@999 15141 <!-- BEGIN extdiff.extdiff -->
belaran@999 15142 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff</userinput>
belaran@999 15143 --- a.801b35c37d8b/myfile 2009-08-16 14:05:02.000000000 +0000
belaran@999 15144 +++ /tmp/extdiffl1y_s9/a/myfile 2009-08-16 14:05:02.000000000 +0000
belaran@999 15145 @@ -1 +1,2 @@
belaran@999 15146 The first line.
belaran@999 15147 +The second line.
belaran@999 15148 </screen>
belaran@999 15149 <!-- END extdiff.extdiff -->
belaran@999 15150
belaran@999 15151
belaran@999 15152 <para id="x_525">The result won't be exactly the same as with the built-in
belaran@999 15153 <command role="hg-cmd" moreinfo="none">hg diff</command> variations, because the
belaran@999 15154 output of <command moreinfo="none">diff</command> varies from one system to
belaran@999 15155 another, even when passed the same options.</para>
belaran@999 15156
belaran@999 15157 <para id="x_526">As the <quote><literal moreinfo="none">making snapshot</literal></quote>
belaran@999 15158 lines of output above imply, the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command works by
belaran@999 15159 creating two snapshots of your source tree. The first snapshot
belaran@999 15160 is of the source revision; the second, of the target revision or
belaran@999 15161 working directory. The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command generates
belaran@999 15162 these snapshots in a temporary directory, passes the name of
belaran@999 15163 each directory to an external diff viewer, then deletes the
belaran@999 15164 temporary directory. For efficiency, it only snapshots the
belaran@999 15165 directories and files that have changed between the two
belaran@999 15166 revisions.</para>
belaran@999 15167
belaran@999 15168 <para id="x_527">Snapshot directory names have the same base name as your
belaran@999 15169 repository. If your repository path is <filename class="directory" moreinfo="none">/quux/bar/foo</filename>, then <filename class="directory" moreinfo="none">foo</filename> will be the name of each
belaran@999 15170 snapshot directory. Each snapshot directory name has its
belaran@999 15171 changeset ID appended, if appropriate. If a snapshot is of
belaran@999 15172 revision <literal moreinfo="none">a631aca1083f</literal>, the directory will be
belaran@999 15173 named <filename class="directory" moreinfo="none">foo.a631aca1083f</filename>.
belaran@999 15174 A snapshot of the working directory won't have a changeset ID
belaran@999 15175 appended, so it would just be <filename class="directory" moreinfo="none">foo</filename> in this example. To see what
belaran@999 15176 this looks like in practice, look again at the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> example above. Notice
belaran@999 15177 that the diff has the snapshot directory names embedded in its
belaran@999 15178 header.</para>
belaran@999 15179
belaran@999 15180 <para id="x_528">The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command
belaran@999 15181 accepts two important options. The <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option
belaran@999 15182 lets you choose a program to view differences with, instead of
belaran@999 15183 <command moreinfo="none">diff</command>. With the <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option,
belaran@999 15184 you can change the options that <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> passes to the program
belaran@999 15185 (by default, these options are
belaran@999 15186 <quote><literal moreinfo="none">-Npru</literal></quote>, which only make sense
belaran@999 15187 if you're running <command moreinfo="none">diff</command>). In other respects,
belaran@999 15188 the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command
belaran@999 15189 acts similarly to the built-in <command role="hg-cmd" moreinfo="none">hg
belaran@999 15190 diff</command> command: you use the same option names, syntax,
belaran@999 15191 and arguments to specify the revisions you want, the files you
belaran@999 15192 want, and so on.</para>
belaran@999 15193
belaran@999 15194 <para id="x_529">As an example, here's how to run the normal system
belaran@999 15195 <command moreinfo="none">diff</command> command, getting it to generate context
belaran@999 15196 diffs (using the <option role="cmd-opt-diff">-c</option> option)
belaran@999 15197 instead of unified diffs, and five lines of context instead of
belaran@999 15198 the default three (passing <literal moreinfo="none">5</literal> as the argument
belaran@999 15199 to the <option role="cmd-opt-diff">-C</option> option).</para>
belaran@999 15200
belaran@999 15201 <!-- BEGIN extdiff.extdiff-ctx -->
belaran@999 15202 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff -o -NprcC5</userinput>
belaran@999 15203 *** a.801b35c37d8b/myfile Sun Aug 16 14:05:02 2009
belaran@999 15204 --- /tmp/extdiffl1y_s9/a/myfile Sun Aug 16 14:05:02 2009
belaran@999 15205 ***************
belaran@999 15206 *** 1 ****
belaran@999 15207 --- 1,2 ----
belaran@999 15208 The first line.
belaran@999 15209 + The second line.
belaran@999 15210 </screen>
belaran@999 15211 <!-- END extdiff.extdiff-ctx -->
belaran@999 15212
belaran@999 15213
belaran@999 15214 <para id="x_52a">Launching a visual diff tool is just as easy. Here's how to
belaran@999 15215 launch the <command moreinfo="none">kdiff3</command> viewer.</para>
belaran@999 15216 <programlisting format="linespecific">hg extdiff -p kdiff3 -o</programlisting>
belaran@999 15217
belaran@999 15218 <para id="x_52b">If your diff viewing command can't deal with directories,
belaran@999 15219 you can easily work around this with a little scripting. For an
belaran@999 15220 example of such scripting in action with the <literal role="hg-ext" moreinfo="none">mq</literal> extension and the
belaran@999 15221 <command moreinfo="none">interdiff</command> command, see <xref linkend="mq-collab:tips:interdiff"/>.</para>
belaran@999 15222
belaran@999 15223 <sect2>
belaran@999 15224 <title>Defining command aliases</title>
belaran@999 15225
belaran@999 15226 <para id="x_52c">It can be cumbersome to remember the options to both the
belaran@999 15227 <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command and
belaran@999 15228 the diff viewer you want to use, so the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension lets you define
belaran@999 15229 <emphasis>new</emphasis> commands that will invoke your diff
belaran@999 15230 viewer with exactly the right options.</para>
belaran@999 15231
belaran@999 15232 <para id="x_52d">All you need to do is edit your <filename role="special" moreinfo="none">~/.hgrc</filename>, and add a section named
belaran@999 15233 <literal role="rc-extdiff" moreinfo="none">extdiff</literal>. Inside this
belaran@999 15234 section, you can define multiple commands. Here's how to add
belaran@999 15235 a <literal moreinfo="none">kdiff3</literal> command. Once you've defined
belaran@999 15236 this, you can type <quote><literal moreinfo="none">hg kdiff3</literal></quote>
belaran@999 15237 and the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension
belaran@999 15238 will run <command moreinfo="none">kdiff3</command> for you.</para>
belaran@999 15239 <programlisting format="linespecific">[extdiff]
belaran@999 15240 cmd.kdiff3 =</programlisting>
belaran@999 15241 <para id="x_52e">If you leave the right hand side of the definition empty,
belaran@999 15242 as above, the <literal role="hg-ext" moreinfo="none">extdiff</literal>
belaran@999 15243 extension uses the name of the command you defined as the name
belaran@999 15244 of the external program to run. But these names don't have to
belaran@999 15245 be the same. Here, we define a command named
belaran@999 15246 <quote><literal moreinfo="none">hg wibble</literal></quote>, which runs
belaran@999 15247 <command moreinfo="none">kdiff3</command>.</para>
belaran@999 15248 <programlisting format="linespecific">[extdiff]
belaran@999 15249 cmd.wibble = kdiff3</programlisting>
belaran@999 15250
belaran@999 15251 <para id="x_52f">You can also specify the default options that you want to
belaran@999 15252 invoke your diff viewing program with. The prefix to use is
belaran@999 15253 <quote><literal moreinfo="none">opts.</literal></quote>, followed by the name
belaran@999 15254 of the command to which the options apply. This example
belaran@999 15255 defines a <quote><literal moreinfo="none">hg vimdiff</literal></quote> command
belaran@999 15256 that runs the <command moreinfo="none">vim</command> editor's
belaran@999 15257 <literal moreinfo="none">DirDiff</literal> extension.</para>
belaran@999 15258 <programlisting format="linespecific">[extdiff]
belaran@999 15259 cmd.vimdiff = vim
belaran@999 15260 opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting>
belaran@999 15261
belaran@999 15262 </sect2>
belaran@999 15263 </sect1>
belaran@999 15264 <sect1 id="sec:hgext:transplant">
belaran@999 15265 <title>Cherrypicking changes with the <literal role="hg-ext" moreinfo="none">transplant</literal> extension</title>
belaran@999 15266
belaran@999 15267 <para id="x_530">Need to have a long chat with Brendan about this.</para>
belaran@999 15268
belaran@999 15269 </sect1>
belaran@999 15270 <sect1 id="sec:hgext:patchbomb">
belaran@999 15271 <title>Send changes via email with the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension</title>
belaran@999 15272
belaran@999 15273 <para id="x_531">Many projects have a culture of <quote>change
belaran@999 15274 review</quote>, in which people send their modifications to a
belaran@999 15275 mailing list for others to read and comment on before they
belaran@999 15276 commit the final version to a shared repository. Some projects
belaran@999 15277 have people who act as gatekeepers; they apply changes from
belaran@999 15278 other people to a repository to which those others don't have
belaran@999 15279 access.</para>
belaran@999 15280
belaran@999 15281 <para id="x_532">Mercurial makes it easy to send changes over email for
belaran@999 15282 review or application, via its <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension. The extension is
belaran@999 15283 so named because changes are formatted as patches, and it's usual
belaran@999 15284 to send one changeset per email message. Sending a long series
belaran@999 15285 of changes by email is thus much like <quote>bombing</quote> the
belaran@999 15286 recipient's inbox, hence <quote>patchbomb</quote>.</para>
belaran@999 15287
belaran@999 15288 <para id="x_533">As usual, the basic configuration of the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension takes just one or
belaran@999 15289 two lines in your <filename role="special" moreinfo="none">
belaran@999 15290 /.hgrc</filename>.</para>
belaran@999 15291 <programlisting format="linespecific">[extensions]
belaran@999 15292 patchbomb =</programlisting>
belaran@999 15293 <para id="x_534">Once you've enabled the extension, you will have a new
belaran@999 15294 command available, named <command role="hg-ext-patchbomb" moreinfo="none">email</command>.</para>
belaran@999 15295
belaran@999 15296 <para id="x_535">The safest and best way to invoke the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command is to
belaran@999 15297 <emphasis>always</emphasis> run it first with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option.
belaran@999 15298 This will show you what the command <emphasis>would</emphasis>
belaran@999 15299 send, without actually sending anything. Once you've had a
belaran@999 15300 quick glance over the changes and verified that you are sending
belaran@999 15301 the right ones, you can rerun the same command, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option
belaran@999 15302 removed.</para>
belaran@999 15303
belaran@999 15304 <para id="x_536">The <command role="hg-ext-patchbomb" moreinfo="none">email</command> command
belaran@999 15305 accepts the same kind of revision syntax as every other
belaran@999 15306 Mercurial command. For example, this command will send every
belaran@999 15307 revision between 7 and <literal moreinfo="none">tip</literal>, inclusive.</para>
belaran@999 15308 <programlisting format="linespecific">hg email -n 7:tip</programlisting>
belaran@999 15309 <para id="x_537">You can also specify a <emphasis>repository</emphasis> to
belaran@999 15310 compare with. If you provide a repository but no revisions, the
belaran@999 15311 <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will
belaran@999 15312 send all revisions in the local repository that are not present
belaran@999 15313 in the remote repository. If you additionally specify revisions
belaran@999 15314 or a branch name (the latter using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option),
belaran@999 15315 this will constrain the revisions sent.</para>
belaran@999 15316
belaran@999 15317 <para id="x_538">It's perfectly safe to run the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command without the
belaran@999 15318 names of the people you want to send to: if you do this, it will
belaran@999 15319 just prompt you for those values interactively. (If you're
belaran@999 15320 using a Linux or Unix-like system, you should have enhanced
belaran@999 15321 <literal moreinfo="none">readline</literal>-style editing capabilities when
belaran@999 15322 entering those headers, too, which is useful.)</para>
belaran@999 15323
belaran@999 15324 <para id="x_539">When you are sending just one revision, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will by
belaran@999 15325 default use the first line of the changeset description as the
belaran@999 15326 subject of the single email message it sends.</para>
belaran@999 15327
belaran@999 15328 <para id="x_53a">If you send multiple revisions, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will usually
belaran@999 15329 send one message per changeset. It will preface the series with
belaran@999 15330 an introductory message, in which you should describe the
belaran@999 15331 purpose of the series of changes you're sending.</para>
belaran@999 15332
belaran@999 15333 <sect2>
belaran@999 15334 <title>Changing the behavior of patchbombs</title>
belaran@999 15335
belaran@999 15336 <para id="x_53b">Not every project has exactly the same conventions for
belaran@999 15337 sending changes in email; the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension tries to
belaran@999 15338 accommodate a number of variations through command line
belaran@999 15339 options.</para>
belaran@999 15340 <itemizedlist>
belaran@999 15341 <listitem><para id="x_53c">You can write a subject for the introductory
belaran@999 15342 message on the command line using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -s</option>
belaran@999 15343 option. This takes one argument, the text of the subject
belaran@999 15344 to use.</para>
belaran@999 15345 </listitem>
belaran@999 15346 <listitem><para id="x_53d">To change the email address from which the
belaran@999 15347 messages originate, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -f</option>
belaran@999 15348 option. This takes one argument, the email address to
belaran@999 15349 use.</para>
belaran@999 15350 </listitem>
belaran@999 15351 <listitem><para id="x_53e">The default behavior is to send unified diffs
belaran@999 15352 (see <xref linkend="sec:mq:patch"/> for a
belaran@999 15353 description of the
belaran@999 15354 format), one per message. You can send a binary bundle
belaran@999 15355 instead with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>
belaran@999 15356 option.</para>
belaran@999 15357 </listitem>
belaran@999 15358 <listitem><para id="x_53f">Unified diffs are normally prefaced with a
belaran@999 15359 metadata header. You can omit this, and send unadorned
belaran@999 15360 diffs, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg
belaran@999 15361 --plain</option> option.</para>
belaran@999 15362 </listitem>
belaran@999 15363 <listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>,
belaran@999 15364 in the same body part as the description of a patch. This
belaran@999 15365 makes it easiest for the largest number of readers to
belaran@999 15366 quote and respond to parts of a diff, as some mail clients
belaran@999 15367 will only quote the first MIME body part in a message. If
belaran@999 15368 you'd prefer to send the description and the diff in
belaran@999 15369 separate body parts, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -a</option>
belaran@999 15370 option.</para>
belaran@999 15371 </listitem>
belaran@999 15372 <listitem><para id="x_541">Instead of sending mail messages, you can
belaran@999 15373 write them to an <literal moreinfo="none">mbox</literal>-format mail
belaran@999 15374 folder using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -m</option>
belaran@999 15375 option. That option takes one argument, the name of the
belaran@999 15376 file to write to.</para>
belaran@999 15377 </listitem>
belaran@999 15378 <listitem><para id="x_542">If you would like to add a
belaran@999 15379 <command moreinfo="none">diffstat</command>-format summary to each patch,
belaran@999 15380 and one to the introductory message, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -d</option>
belaran@999 15381 option. The <command moreinfo="none">diffstat</command> command displays
belaran@999 15382 a table containing the name of each file patched, the
belaran@999 15383 number of lines affected, and a histogram showing how much
belaran@999 15384 each file is modified. This gives readers a qualitative
belaran@999 15385 glance at how complex a patch is.</para>
belaran@999 15386 </listitem></itemizedlist>
belaran@999 15387
belaran@999 15388 </sect2>
belaran@999 15389 </sect1>
belaran@999 15390 </chapter>
belaran@999 15391
belaran@999 15392 <!--
belaran@999 15393 local variables:
belaran@999 15394 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@999 15395 end:
belaran@999 15396 -->
belaran@999 15397
belaran@999 15398 <!-- BEGIN appA -->
belaran@999 15399
belaran@999 15400
belaran@999 15401 <appendix id="svn">
belaran@999 15402 <?dbhtml filename="migrating-to-mercurial.html"?>
belaran@999 15403 <title>Migrer vers Mercurial</title>
belaran@999 15404
belaran@999 15405 <para id="x_6e1">Une manière courante de s'essayer à un nouveau
belaran@999 15406 gestionnaire de révisions est d'expérimenter en migrant un
belaran@999 15407 projet existant, plutôt que le faire avec un nouveau projet.
belaran@999 15408 </para>
belaran@999 15409
belaran@999 15410 <para id="x_6e2">Dans cette annexe, nous discuterons comment importer
belaran@999 15411 l'historique d'un projet dans Mercurial, et à quoi faire attention
belaran@999 15412 si vous êtes habitués à un autre outil de gestion de révisions.
belaran@999 15413 </para>
belaran@999 15414
belaran@999 15415 <sect1>
belaran@999 15416 <title>Importer l'historique depuis un autre système</title>
belaran@999 15417
belaran@999 15418 <para id="x_6e3">Mercurial est livré avec une extension nommée
belaran@999 15419 <literal moreinfo="none">convert</literal>, qui permet d'importer un historique
belaran@999 15420 depuis les gestionnaire de révisions les plus courants. Au moment de
belaran@999 15421 l'écriture de ce livre, il pouvait importer l'historique depuis:
belaran@999 15422 </para>
belaran@999 15423 <itemizedlist>
belaran@999 15424 <listitem>
belaran@999 15425 <para id="x_6e4">Subversion</para>
belaran@999 15426 </listitem>
belaran@999 15427 <listitem>
belaran@999 15428 <para id="x_6e5">CVS</para>
belaran@999 15429 </listitem>
belaran@999 15430 <listitem>
belaran@999 15431 <para id="x_6e6">git</para>
belaran@999 15432 </listitem>
belaran@999 15433 <listitem>
belaran@999 15434 <para id="x_6e7">Darcs</para>
belaran@999 15435 </listitem>
belaran@999 15436 <listitem>
belaran@999 15437 <para id="x_6e8">Bazaar</para>
belaran@999 15438 </listitem>
belaran@999 15439 <listitem>
belaran@999 15440 <para id="x_6e9">Monotone</para>
belaran@999 15441 </listitem>
belaran@999 15442 <listitem>
belaran@999 15443 <para id="x_6ea">GNU Arch</para>
belaran@999 15444 </listitem>
belaran@999 15445 <listitem>
belaran@999 15446 <para id="x_6eb">Mercurial</para>
belaran@999 15447 </listitem>
belaran@999 15448 </itemizedlist>
belaran@999 15449
belaran@999 15450 <para id="x_6ec">(Pour savoir pourquoi Mercurial lui même est supporté
belaran@999 15451 comme source, voir <xref linkend="svn.filemap"/>.)</para>
belaran@999 15452
belaran@999 15453 <para id="x_6ed">Vous pouvez activer l'extension de la manière
belaran@999 15454 habituelle, en éditant votre fichier <filename moreinfo="none">~/.hgrc</filename></para>
belaran@999 15455
belaran@999 15456 <programlisting format="linespecific">[extensions]
belaran@999 15457 convert =</programlisting>
belaran@999 15458
belaran@999 15459 <para id="x_6ee">Ceci rendra la commande <command moreinfo="none">hg convert</command>
belaran@999 15460 disponible. La commande est facile à utiliser. Par exemple, la
belaran@999 15461 commande suivante va importer l'historique Subversion du <emphasis remap="it">framework</emphasis> de test <quote>Nose Unit</quote> dans Mercurial.
belaran@999 15462 </para>
belaran@999 15463
belaran@999 15464 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen>
belaran@999 15465
belaran@999 15466 <para id="x_6ef">L'extension <literal moreinfo="none">convert</literal> opère de
belaran@999 15467 manière incrémentale. En d'autres mots, après une première exécution de
belaran@999 15468 la commande <command moreinfo="none">hg convert</command>, les exécutions ultérieures
belaran@999 15469 importeront les révisions ultérieures à l'exécution précédente.
belaran@999 15470 La conversion incrémentale ne réussira que si
belaran@999 15471 vous exécutez <command moreinfo="none">hg convert</command> dans le même dépôt que vous
belaran@999 15472 aviez utilisé à l'origine, ceci parce que l'extension <literal moreinfo="none">convert</literal>
belaran@999 15473 sauvegarde un certain nombre de méta-données privées dans le fichier
belaran@999 15474 <filename moreinfo="none">.hg/shamap</filename> (non versioné) au sein du dépôt cible.
belaran@999 15475 </para>
belaran@999 15476
belaran@999 15477 <para id="x_707">Lorsque vous voulez faire des modifications en utilisant
belaran@999 15478 Mercurial, le mieux est de faire un clone de l'ensemble de l'arborescence
belaran@999 15479 que vous souhaitez convertir, et de laisser l'arborescence d'origine pour
belaran@999 15480 de futures conversions incrémentales. C'est la manière la plus sûre pour vous laisser
belaran@999 15481 récupérer et fusionner les modifications futures depuis l'outil de gestion
belaran@999 15482 de révisions dans votre nouveau dépôt Mercurial.</para>
belaran@999 15483
belaran@999 15484 <sect2>
belaran@999 15485 <title>Convertir plusieurs branches</title>
belaran@999 15486
belaran@999 15487 <para id="x_708">La commande <command moreinfo="none">hg convert</command> citée
belaran@999 15488 ci-dessus convertit seulement l'historique de la <literal moreinfo="none">branche
belaran@999 15489 principale (trunk)</literal> du dépôt Subversion. Si nous utilisons
belaran@999 15490 à la place l'URL <literal moreinfo="none">http://python-nose.googlecode.com/svn</literal>,
belaran@999 15491 Mercurial va automatiquement détecter la
belaran@999 15492 <literal moreinfo="none">branche principale (trunk)</literal>, les <literal moreinfo="none">étiquettes
belaran@999 15493 (tags)</literal>, et les <literal moreinfo="none">branches</literal> que les dépôts
belaran@999 15494 Subversion utilisent généralement, et les importera chacun dans
belaran@999 15495 une branche Mercurial distincte.</para>
belaran@999 15496
belaran@999 15497 <para id="x_709">Par défaut, chaque branche Subversion importée
belaran@999 15498 dans Mercurial se voit attribuer un nom de branche. Une fois la
belaran@999 15499 conversion achevée, vous pouvez obtenir la liste des noms des branches
belaran@999 15500 actives dans le dépôt Mercurial en utilisant la commande
belaran@999 15501 <command moreinfo="none">hg branches -a</command>. Si vous préférez importer les
belaran@999 15502 branches Subversion sans noms, ajoutez l'option <option>--config
belaran@999 15503 convert.hg.usebranches=false</option> à la commande
belaran@999 15504 <command moreinfo="none">hg convert</command>.</para>
belaran@999 15505
belaran@999 15506 <para id="x_70a">Une fois votre arborescence convertie,
belaran@999 15507 si vous souhaitez travailler selon la pratique habituelle sous Mercurial
belaran@999 15508 avec une arborescence qui ne contient qu'une seule branche, vous pouvez cloner
belaran@999 15509 cette seule branche en utilisant
belaran@999 15510 <command moreinfo="none">hg clone -r nomdemabranche</command>.</para>
belaran@999 15511 </sect2>
belaran@999 15512
belaran@999 15513 <sect2>
belaran@999 15514 <title>Associer les noms d'utilisateurs</title>
belaran@999 15515
belaran@999 15516 <para id="x_6f0">Certains outils de gestion de révisions
belaran@999 15517 ne sauvegardent, avec les modifications, que les noms
belaran@999 15518 d'utilisateurs raccourcis. Ceux-ci peuvent être difficiles à
belaran@999 15519 interpréter. La norme avec Mercurial est de sauvegarder le
belaran@999 15520 nom du <emphasis remap="it">committeur</emphasis> et son adresse
belaran@999 15521 mail, ce qui est beaucoup plus utile pour discuter avec lui
belaran@999 15522 par la suite.</para>
belaran@999 15523
belaran@999 15524 <para id="x_6f1">Si vous convertissez une arborescence depuis
belaran@999 15525 un gestionnaire de révisions qui utilise seulement les noms
belaran@999 15526 raccourcis, vous pouvez associer ces noms à des équivalents
belaran@999 15527 plus détaillés en passant l'option <option>--authors</option>
belaran@999 15528 à la commande <command moreinfo="none">hg convert</command>. Cette option
belaran@999 15529 attend un fichier qui contient des entrées sous la forme suivante:
belaran@999 15530 </para>
belaran@999 15531
belaran@999 15532 <programlisting format="linespecific">arist = Aristotle &lt;aristotle@phil.example.gr&gt;
belaran@999 15533 soc = Socrates &lt;socrates@phil.example.gr&gt;</programlisting>
belaran@999 15534
belaran@999 15535 <para id="x_6f2">Quand <literal moreinfo="none">convert</literal> trouve une
belaran@999 15536 modification associée au nom <literal moreinfo="none">arist</literal> dans le
belaran@999 15537 dépôt de source, il va utiliser le nom <literal moreinfo="none">Aristotle
belaran@999 15538 &lt;aristotle@phil.example.gr&gt;</literal> dans les révisions
belaran@999 15539 Mercurial. Si aucune correspondance n'est trouvé, il utilise
belaran@999 15540 le nom tel quel.</para>
belaran@999 15541 </sect2>
belaran@999 15542
belaran@999 15543 <sect2 id="svn.filemap">
belaran@999 15544 <title>Nettoyer l'arboresence</title>
belaran@999 15545
belaran@999 15546 <para id="x_6f3">Tous les projets n'ont pas un historique parfait.
belaran@999 15547 Il peut y avoir des répertoires qui n'auraient jamais dû être ajoutés,
belaran@999 15548 un fichier qui est trop volumineux, ou même une partie de la
belaran@999 15549 hiérarchie qui devrait être réorganisée.</para>
belaran@999 15550
belaran@999 15551 <para id="x_6f4">L'extension <literal moreinfo="none">convert</literal> permet
belaran@999 15552 d'utiliser un <quote>fichier d'association</quote> qui peut
belaran@999 15553 réorganiser les fichiers et les répertoires dans un projet lors de
belaran@999 15554 l'importation de son historique. Ceci est utile non seulement quand vous
belaran@999 15555 importez l'historique d'un autre gestionnaire de révisions, mais
belaran@999 15556 aussi pour nettoyer ou réorganiser l'arborescence d'un projet
belaran@999 15557 Mercurial.</para>
belaran@999 15558
belaran@999 15559 <para id="x_6f5">Pour indiquer le fichier d'association, on utilise
belaran@999 15560 l'option <option>--filemap</option> en lui fournissant un nom de
belaran@999 15561 fichier. Le fichier d'association contient des lignes de la forme
belaran@999 15562 suivante :</para>
belaran@999 15563
belaran@999 15564 <programlisting format="linespecific"># Ceci est un commentaire.
belaran@999 15565 # Les lignes vides sont ignorées.
belaran@999 15566
belaran@999 15567 include path/to/file
belaran@999 15568
belaran@999 15569 exclude path/to/file
belaran@999 15570
belaran@999 15571 rename from/some/path to/some/other/place
belaran@999 15572 </programlisting>
belaran@999 15573
belaran@999 15574 <para id="x_6f6">La directive <literal moreinfo="none">include</literal> inclut un
belaran@999 15575 fichier, ou l'ensemble des fichiers d'un répertoire, dans le dépôt
belaran@999 15576 de destination. La directive <literal moreinfo="none">exclude</literal> omet les
belaran@999 15577 fichiers ou répertoires du dépôt. Ceci inclut aussi les autres
belaran@999 15578 fichiers et répertoires qui ne sont pas explicitement inclus.
belaran@999 15579 La directive <literal moreinfo="none">exclude</literal> entraine l'omission
belaran@999 15580 des fichiers ou répertoires, et autres fichiers qui ne sont pas
belaran@999 15581 explicitement inclus.</para>
belaran@999 15582
belaran@999 15583 <para id="x_6f7">Pour déplacer un fichier ou un répertoire d'un
belaran@999 15584 emplacement à un autre, utilisez la directive
belaran@999 15585 <literal moreinfo="none">rename</literal>. Si vous avez besoin de déplacer un
belaran@999 15586 fichier ou un répertoire depuis un sous répertoire dans la racine
belaran@999 15587 du dépôt, utilisez <literal moreinfo="none">.</literal> comme second argument de
belaran@999 15588 la directive <literal moreinfo="none">rename</literal>.</para>
belaran@999 15589 </sect2>
belaran@999 15590
belaran@999 15591 <sect2>
belaran@999 15592 <title>Améliorer les performances de la conversion Subversion</title>
belaran@999 15593
belaran@999 15594 <para id="x_70b">Vous aurez souvent besoin de plusieurs essais
belaran@999 15595 avant d'arriver à la parfaite combinaison de fichier d'association de fichiers,
belaran@999 15596 de fichier d'association de noms d'utilisateurs et des autres paramètres. Or,
belaran@999 15597 convertir un dépôt Mercurial via un protocole comme <literal moreinfo="none">ssh</literal>
belaran@999 15598 ou <literal moreinfo="none">http</literal> peut être des milliers de fois plus long
belaran@999 15599 que ce dont le système d'exploitation est en fait capable de faire,
belaran@999 15600 à cause des latence réseau. Ceci peut rendre la conception de cette
belaran@999 15601 combinaison parfaite très douloureuse.</para>
belaran@999 15602
belaran@999 15603 <para id="x_70c">La commande <ulink url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command moreinfo="none">svnsync</command></ulink>
belaran@999 15604 peut grandement améliorer la vitesse de conversion d'un dépôt
belaran@999 15605 Subversion. Il s'agit d'un programme de miroir de dépôt Subversion
belaran@999 15606 en lecture seule. L'idée est de créer un miroir local d'une
belaran@999 15607 arborescence Subversion, puis de convertir ce miroir en dépôt
belaran@999 15608 Mercurial.</para>
belaran@999 15609
belaran@999 15610 <para id="x_70d">Supposez que nous voulions convertir le dépôt
belaran@999 15611 Subversion du populaire projet Memcached en une arborescence Mercurial.
belaran@999 15612 Tout d'abord, nous créons un dépôt Subversion local.</para>
belaran@999 15613
belaran@999 15614 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnadmin create memcached-mirror</userinput></screen>
belaran@999 15615
belaran@999 15616 <para id="x_70e">Puis, nous allons mettre en place un <quote>hook</quote> Subversion
belaran@999 15617 dont <command moreinfo="none">svnsync</command> a besoin.</para>
belaran@999 15618
belaran@999 15619 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '#!/bin/sh' &gt; memcached-mirror/hooks/pre-revprop-change</userinput>
belaran@999 15620 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen>
belaran@999 15621
belaran@999 15622 <para id="x_70f">Nous initialisons ensuite <command moreinfo="none">svnsync</command> dans ce
belaran@999 15623 dépôt.</para>
belaran@999 15624
belaran@999 15625 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync --init file://`pwd`/memcached-mirror \
belaran@999 15626 http://code.sixapart.com/svn/memcached</userinput></screen>
belaran@999 15627
belaran@999 15628 <para id="x_710">La prochaine étape est de commencer le processus de
belaran@999 15629 mirroring de <command moreinfo="none">svnsync</command>.</para>
belaran@999 15630
belaran@999 15631 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync sync file://`pwd`/memcached-mirror</userinput></screen>
belaran@999 15632
belaran@999 15633 <para id="x_711">Enfin, nous importons l'historique de notre dépôt
belaran@999 15634 local Subversion dans Mercurial.</para>
belaran@999 15635
belaran@999 15636 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert memcached-mirror</userinput></screen>
belaran@999 15637
belaran@999 15638 <para id="x_712">Nous pouvons utiliser ce processus de manière
belaran@999 15639 incrémentale, si le dépôt Subversion est toujours en activité.
belaran@999 15640 Il suffit d'exécuter de nouveau <command moreinfo="none">svnsync</command> pour
belaran@999 15641 récupérer les récentes modifications dans notre miroir, puis <command moreinfo="none">hg
belaran@999 15642 convert</command>
belaran@999 15643 les importe dans notre arborescence Mercurial.</para>
belaran@999 15644
belaran@999 15645 <para id="x_713">Il y a deux avantages à utiliser un import à deux
belaran@999 15646 étages comme avec <command moreinfo="none">svnsync</command>. Le premier
belaran@999 15647 est qu'il utilise du code de synchronisation réseau de Subversion
belaran@999 15648 plus efficace que la commande <command moreinfo="none">hg convert</command>,
belaran@999 15649 et donc transfère moins de données par le réseau. Le deuxième
belaran@999 15650 est que l'import depuis un dépôt Subversion local est si rapide que
belaran@999 15651 vous pouvez peaufiner et réitérer les paramètres de conversion de
belaran@999 15652 ce dernier sans souffrir de la qualité de la connexion réseau.</para>
belaran@999 15653 </sect2>
belaran@999 15654 </sect1>
belaran@999 15655
belaran@999 15656 <sect1>
belaran@999 15657 <title>Migrer depuis Subversion</title>
belaran@999 15658
belaran@999 15659 <para id="x_6f8">Subversion est le système de gestion de versions
belaran@999 15660 open source le plus populaire aujourd'hui. Bien qu'il y ait des
belaran@999 15661 différences entre Mercurial et Subversion, faire la transition de
belaran@999 15662 l'un à l'autre n'est pas très difficile. Les deux disposent en effet
belaran@999 15663 de jeux de commandes similaires et d'interfaces similaires.</para>
belaran@999 15664
belaran@999 15665 <sect2>
belaran@999 15666 <title>Différences philosophiques</title>
belaran@999 15667
belaran@999 15668 <para id="x_6f9">La différence fondamentale entre Subversion et
belaran@999 15669 Mercurial est bien évidement que Subversion est centralisé, alors
belaran@999 15670 que Mercurial est distribué. Puisque que Mercurial enregistre tout
belaran@999 15671 l'historique d'un projet sur votre disque dur local, il n'a besoin
belaran@999 15672 d'effectuer des accès au réseau que lorsque vous voulez
belaran@999 15673 explicitement communiquer avec un autre dépôt. Subversion, par contre,
belaran@999 15674 ne conserve que peu d'informations localement, et le client
belaran@999 15675 doit donc communiquer avec le serveur central pour la
belaran@999 15676 plupart des opérations communes.</para>
belaran@999 15677
belaran@999 15678 <para id="x_6fa">Subversion s'en tire plus ou moins bien sans notion
belaran@999 15679 de branche réellement bien définie : quelle portion de l'espace de nommage
belaran@999 15680 du serveur est une branche est une simple question de convention, le
belaran@999 15681 logiciel n'imposant rien à ce sujet. Mercurial considère
belaran@999 15682 un dépôt comme un élément de la gestion des branches.</para>
belaran@999 15683
belaran@999 15684 <sect3>
belaran@999 15685 <title>Portée des commandes</title>
belaran@999 15686
belaran@999 15687 <para id="x_6fb">Puisque que Subversion ne sait pas réellement
belaran@999 15688 quelle partie de son espace de nommage est en fait une branche, il
belaran@999 15689 traite la plupart des commandes comme des requêtes à exécuter sur le
belaran@999 15690 répertoire où vous vous situez, et ses sous répertoires. Par exemple,
belaran@999 15691 si vous exécutez <command moreinfo="none">svn log</command>, vous verrez l'historique
belaran@999 15692 de la partie de l'arborescence où vous vous situez, et non de la
belaran@999 15693 hiérarchie entière.</para>
belaran@999 15694
belaran@999 15695 <para id="x_6fc">Les commandes de Mercurial ont un comportement
belaran@999 15696 différent : toutes les commandes s'appliquent à l'ensemble de l'arborescence
belaran@999 15697 du dépôt. Exécutez la commande <command moreinfo="none">hg log</command> et elle vous
belaran@999 15698 donnera l'historique de l'ensemble de l'arborescence, quel que soit le
belaran@999 15699 sous-répertoire où vous vous situez. Si
belaran@999 15700 vous souhaitez obtenir l'historique d'un répertoire ou seulement d'un
belaran@999 15701 fichier, ajouter simplement le nom de celui-ci à la commande, par
belaran@999 15702 exemple <command moreinfo="none">hg log src</command>.</para>
belaran@999 15703
belaran@999 15704 <para id="x_6fd">De ma propre expérience, cette différence dans leur
belaran@999 15705 comportement par défaut est probablement ce qui risque de vous
belaran@999 15706 surprendre le plus si vous passez régulièrement d'un outil à l'autre.</para>
belaran@999 15707 </sect3>
belaran@999 15708
belaran@999 15709 <sect3>
belaran@999 15710 <title>Opération multi utilisateur et sécurité</title>
belaran@999 15711
belaran@999 15712 <para id="x_6fe">Avec Subversion, il est normal (bien que légèrement
belaran@999 15713 désapprouvé) que différentes personnes collaborent sur une seule
belaran@999 15714 branche. Si Alice et Bob travaillent ensemble, et Alice ajoute ses
belaran@999 15715 modifications à leur branche partagée, Bob doit alors mettre à jour
belaran@999 15716 sa vue de la branche avant de pouvoir appliquer un commit.
belaran@999 15717 Puisqu'il n'a, à ce moment, pas effectué de commit
belaran@999 15718 des modifications qu'il a faites, il se peut qu'il ne corrompe
belaran@999 15719 ou ne perde
belaran@999 15720 ses modifications pendant ou après la mise à jour.</para>
belaran@999 15721
belaran@999 15722 <para id="x_6ff">Mercurial encourage, à l'inverse, un modèle
belaran@999 15723 "commit-puis-merge". Avant de récupérer des modifications depuis le
belaran@999 15724 serveur, ou avant d'y envoyer les siennes, Bob enregistre ses
belaran@999 15725 modifications de manière locale en appliquant un commit. C'est à dire
belaran@999 15726 que si Alice avait envoyé ses modifications sur le serveur avant
belaran@999 15727 que Bob n'envoie les siennes, ce dernier ne pourra le faire
belaran@999 15728 qu'après avoir récupéré et fusionné celles d'Alice avec les siennes.
belaran@999 15729 Si Bob fait alors une
belaran@999 15730 erreur lors de la fusion, il pourra toujours restaurer sa version, pour
belaran@999 15731 laquelle il avait appliqué le commit.</para>
belaran@999 15732
belaran@999 15733 <para id="x_700">Il est important de souligner qu'il s'agit de la
belaran@999 15734 manière habituelle de travailler avec ces outils. Subversion propose
belaran@999 15735 une manière plus sûre de "travailler-dans-votre-propre-branche", mais elle
belaran@999 15736 est assez complexe pour que, en pratique, elle ne soit que rarement utilisé.
belaran@999 15737 Mercurial propose de son côté un mode un peu moins sûr, permettant de
belaran@999 15738 récupérer des modifications par dessus des modifications non
belaran@999 15739 committées, qui reste toutefois très peu répandu.</para>
belaran@999 15740 </sect3>
belaran@999 15741
belaran@999 15742 <sect3>
belaran@999 15743 <title>Publication vs changement locaux</title>
belaran@999 15744
belaran@999 15745 <para id="x_701">Une commande Subversion <command moreinfo="none">svn
belaran@999 15746 commit</command> publie immédiatement les modifications sur le
belaran@999 15747 serveur, où elles peuvent être vu par n'importe qui doté d'un privilège
belaran@999 15748 de lecture.</para>
belaran@999 15749
belaran@999 15750 <para id="x_702">Avec Mercurial, les modifications sont toujours d'abord
belaran@999 15751 enregistrées localement, et doivent être par la suite transférés par
belaran@999 15752 la commande <command moreinfo="none">hg push</command>.</para>
belaran@999 15753
belaran@999 15754 <para id="x_703">Chaque approche a ses avantages et ses inconvénients.
belaran@999 15755 Le modèle Subversion implique que les modifications soient publiées, et
belaran@999 15756 donc disponibles immédiatement. D'un autre coté, cela implique aussi
belaran@999 15757 que, pour pouvoir utiliser le logiciel normalement, un utilisateur doit
belaran@999 15758 avoir les droits d'écriture dans le dépôt, et ce privilège n'est pas concédé
belaran@999 15759 facilement par la plupart des projets Open Source.</para>
belaran@999 15760
belaran@999 15761 <para id="x_704">L'approche de Mercurial permet à quiconque de faire
belaran@999 15762 un clone du dépôt et d'y ajouter ses modifications sans jamais avoir
belaran@999 15763 besoin de la permission de quiconque, et l'on peut même publier ses
belaran@999 15764 modifications et continuer à participer comme on le désire. Toutefois, la
belaran@999 15765 distinction entre les commits et le transfert de ces derniers présente
belaran@999 15766 le risque que quelqu'un applique ses modifications par un commit local
belaran@999 15767 sur son portable et parte se promener pendant quelques jours en ayant
belaran@999 15768 oublié de les transférer, ce qui peut, dans certains rares cas,
belaran@999 15769 bloquer temporairement ses collaborateurs.</para>
belaran@999 15770 </sect3>
belaran@999 15771 </sect2>
belaran@999 15772
belaran@999 15773 <sect2>
belaran@999 15774 <title>Références des commandes</title>
belaran@999 15775
belaran@999 15776 <table>
belaran@999 15777 <title>Commandes Subversion et leurs équivalents Mercurial</title>
belaran@999 15778 <tgroup cols="3">
belaran@999 15779 <thead>
belaran@999 15780 <row>
belaran@999 15781 <entry>Subversion</entry>
belaran@999 15782 <entry>Mercurial</entry>
belaran@999 15783 <entry>Notes</entry>
belaran@999 15784 </row>
belaran@999 15785 </thead>
belaran@999 15786 <tbody>
belaran@999 15787 <row>
belaran@999 15788 <entry><command moreinfo="none">svn add</command></entry>
belaran@999 15789 <entry><command moreinfo="none">hg add</command></entry>
belaran@999 15790 <entry/>
belaran@999 15791 </row>
belaran@999 15792 <row>
belaran@999 15793 <entry><command moreinfo="none">svn blame</command></entry>
belaran@999 15794 <entry><command moreinfo="none">hg annotate</command></entry>
belaran@999 15795 <entry/>
belaran@999 15796 </row>
belaran@999 15797 <row>
belaran@999 15798 <entry><command moreinfo="none">svn cat</command></entry>
belaran@999 15799 <entry><command moreinfo="none">hg cat</command></entry>
belaran@999 15800 <entry/>
belaran@999 15801 </row>
belaran@999 15802 <row>
belaran@999 15803 <entry><command moreinfo="none">svn checkout</command></entry>
belaran@999 15804 <entry><command moreinfo="none">hg clone</command></entry>
belaran@999 15805 <entry/>
belaran@999 15806 </row>
belaran@999 15807 <row>
belaran@999 15808 <entry><command moreinfo="none">svn cleanup</command></entry>
belaran@999 15809 <entry>n/a</entry>
belaran@999 15810 <entry>Aucun nettoyage nécessaire.</entry>
belaran@999 15811 </row>
belaran@999 15812 <row>
belaran@999 15813 <entry><command moreinfo="none">svn commit</command></entry>
belaran@999 15814 <entry><command moreinfo="none">hg commit</command>; <command moreinfo="none">hg
belaran@999 15815 push</command></entry>
belaran@999 15816 <entry><command moreinfo="none">hg push</command> publie les modifications
belaran@999 15817 après un commit.</entry>
belaran@999 15818 </row>
belaran@999 15819 <row>
belaran@999 15820 <entry><command moreinfo="none">svn copy</command></entry>
belaran@999 15821 <entry><command moreinfo="none">hg clone</command></entry>
belaran@999 15822 <entry>Pour créer une nouvelle branche</entry>
belaran@999 15823 </row>
belaran@999 15824 <row>
belaran@999 15825 <entry><command moreinfo="none">svn copy</command></entry>
belaran@999 15826 <entry><command moreinfo="none">hg copy</command></entry>
belaran@999 15827 <entry>Pour copier des fichiers ou des répertoires</entry>
belaran@999 15828 </row>
belaran@999 15829 <row>
belaran@999 15830 <entry><command moreinfo="none">svn delete</command> (<command moreinfo="none">svn
belaran@999 15831 remove</command>)</entry>
belaran@999 15832 <entry><command moreinfo="none">hg remove</command></entry>
belaran@999 15833 <entry/>
belaran@999 15834 </row>
belaran@999 15835 <row>
belaran@999 15836 <entry><command moreinfo="none">svn diff</command></entry>
belaran@999 15837 <entry><command moreinfo="none">hg diff</command></entry>
belaran@999 15838 <entry/>
belaran@999 15839 </row>
belaran@999 15840 <row>
belaran@999 15841 <entry><command moreinfo="none">svn export</command></entry>
belaran@999 15842 <entry><command moreinfo="none">hg archive</command></entry>
belaran@999 15843 <entry/>
belaran@999 15844 </row>
belaran@999 15845 <row>
belaran@999 15846 <entry><command moreinfo="none">svn help</command></entry>
belaran@999 15847 <entry><command moreinfo="none">hg help</command></entry>
belaran@999 15848 <entry/>
belaran@999 15849 </row>
belaran@999 15850 <row>
belaran@999 15851 <entry><command moreinfo="none">svn import</command></entry>
belaran@999 15852 <entry><command moreinfo="none">hg addremove</command>; <command moreinfo="none">hg
belaran@999 15853 commit</command></entry>
belaran@999 15854 <entry/>
belaran@999 15855 </row>
belaran@999 15856 <row>
belaran@999 15857 <entry><command moreinfo="none">svn info</command></entry>
belaran@999 15858 <entry><command moreinfo="none">hg parents</command></entry>
belaran@999 15859 <entry>Affiche la version sur la base de laquelle on travaille</entry>
belaran@999 15860 </row>
belaran@999 15861 <row>
belaran@999 15862 <entry><command moreinfo="none">svn info</command></entry>
belaran@999 15863 <entry><command moreinfo="none">hg showconfig
belaran@999 15864 paths.default</command></entry>
belaran@999 15865 <entry>Affiche de quelle URL est extrait ce dépôt</entry>
belaran@999 15866 </row>
belaran@999 15867 <row>
belaran@999 15868 <entry><command moreinfo="none">svn list</command></entry>
belaran@999 15869 <entry><command moreinfo="none">hg manifest</command></entry>
belaran@999 15870 <entry/>
belaran@999 15871 </row>
belaran@999 15872 <row>
belaran@999 15873 <entry><command moreinfo="none">svn log</command></entry>
belaran@999 15874 <entry><command moreinfo="none">hg log</command></entry>
belaran@999 15875 <entry/>
belaran@999 15876 </row>
belaran@999 15877 <row>
belaran@999 15878 <entry><command moreinfo="none">svn merge</command></entry>
belaran@999 15879 <entry><command moreinfo="none">hg merge</command></entry>
belaran@999 15880 <entry/>
belaran@999 15881 </row>
belaran@999 15882 <row>
belaran@999 15883 <entry><command moreinfo="none">svn mkdir</command></entry>
belaran@999 15884 <entry>n/a</entry>
belaran@999 15885 <entry>Mercurial ne versionne pas les répertoires</entry>
belaran@999 15886 </row>
belaran@999 15887 <row>
belaran@999 15888 <entry><command moreinfo="none">svn move</command> (<command moreinfo="none">svn
belaran@999 15889 rename</command>)</entry>
belaran@999 15890 <entry><command moreinfo="none">hg rename</command></entry>
belaran@999 15891 <entry/>
belaran@999 15892 </row>
belaran@999 15893 <row>
belaran@999 15894 <entry><command moreinfo="none">svn resolved</command></entry>
belaran@999 15895 <entry><command moreinfo="none">hg resolve -m</command></entry>
belaran@999 15896 <entry/>
belaran@999 15897 </row>
belaran@999 15898 <row>
belaran@999 15899 <entry><command moreinfo="none">svn revert</command></entry>
belaran@999 15900 <entry><command moreinfo="none">hg revert</command></entry>
belaran@999 15901 <entry/>
belaran@999 15902 </row>
belaran@999 15903 <row>
belaran@999 15904 <entry><command moreinfo="none">svn status</command></entry>
belaran@999 15905 <entry><command moreinfo="none">hg status</command></entry>
belaran@999 15906 <entry/>
belaran@999 15907 </row>
belaran@999 15908 <row>
belaran@999 15909 <entry><command moreinfo="none">svn update</command></entry>
belaran@999 15910 <entry><command moreinfo="none">hg pull -u</command></entry>
belaran@999 15911 <entry/>
belaran@999 15912 </row>
belaran@999 15913 </tbody>
belaran@999 15914 </tgroup>
belaran@999 15915 </table>
belaran@999 15916 </sect2>
belaran@999 15917 </sect1>
belaran@999 15918
belaran@999 15919 <sect1>
belaran@999 15920 <title>Conseils utiles pour les débutants</title>
belaran@999 15921
belaran@999 15922 <para id="x_705">Avec la plupart des gestionnaire de versions, afficher
belaran@999 15923 un diff associé à une révision peut être assez douloureux. Par exemple,
belaran@999 15924 avec Subversion, pour voir ce qui a été modifiée dans la révision 104654,
belaran@999 15925 vous devez saisir <command moreinfo="none">svn diff -r104653:104654</command>. Mercurial
belaran@999 15926 élimine le besoin de saisir l'identifiant d'une révision deux fois dans
belaran@999 15927 ce cas classique. Pour un simple diff, <command moreinfo="none">hg
belaran@999 15928 export 104654</command> suffit. Pour obtenir une entrée du journal suivie d'un diff,
belaran@999 15929 <command moreinfo="none">hg log -r104654 -p</command>.</para>
belaran@999 15930
belaran@999 15931 <para id="x_706">Quand vous exécutez la commande <command moreinfo="none">hg status</command>
belaran@999 15932 sans aucun argument, elle affiche l'état de l'ensemble de l'arborescence,
belaran@999 15933 avec des chemins relatifs partant de la racine du dépôt. Ceci rend
belaran@999 15934 difficile de copier un nom de fichier depuis la sortie de la commande
belaran@999 15935 <command moreinfo="none">hg status</command> dans une autre ligne de commande. Si vous
belaran@999 15936 fournissez un fichier ou un répertoire à la commande <command moreinfo="none">hg
belaran@999 15937 status</command>, elle va afficher les chemins relatif depuis votre
belaran@999 15938 répertoire courant à la place. Ainsi, pour avoir un état sur l'ensemble
belaran@999 15939 de l'arborescence à l'aide de <command moreinfo="none">hg status</command>, avec des
belaran@999 15940 chemins relatifs à votre répertoire courant, et non la racine du dépôt,
belaran@999 15941 ajoutez la sortie de <command moreinfo="none">hg root</command> à la commande
belaran@999 15942 <command moreinfo="none">hg status</command>. Vous pouvez le faire aisément sur un
belaran@999 15943 système Unix ainsi :</para>
belaran@999 15944
belaran@999 15945 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput></screen>
belaran@999 15946 </sect1>
belaran@999 15947 </appendix>
belaran@999 15948
belaran@999 15949 <!--
belaran@999 15950 local variables:
belaran@999 15951 sgml-parent-document: ("00book.xml" "book" "appendix")
belaran@999 15952 end:
belaran@999 15953 -->
belaran@999 15954
belaran@999 15955 <!-- BEGIN appB -->
belaran@999 15956 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 15957
belaran@999 15958 <appendix id="chap:mqref">
belaran@999 15959 <?dbhtml filename="mercurial-queues-reference.html"?>
belaran@999 15960 <title>Mercurial Queues reference</title>
belaran@999 15961
belaran@999 15962 <sect1 id="sec:mqref:cmdref">
belaran@999 15963 <title>MQ command reference</title>
belaran@999 15964
belaran@999 15965 <para id="x_5e8">For an overview of the commands provided by MQ, use the
belaran@999 15966 command <command role="hg-cmd" moreinfo="none">hg help mq</command>.</para>
belaran@999 15967
belaran@999 15968 <sect2>
belaran@999 15969 <title><command role="hg-ext-mq" moreinfo="none">qapplied</command>—print
belaran@999 15970 applied patches</title>
belaran@999 15971
belaran@999 15972 <para id="x_5e9">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command
belaran@999 15973 prints the current stack of applied patches. Patches are
belaran@999 15974 printed in oldest-to-newest order, so the last patch in the
belaran@999 15975 list is the <quote>top</quote> patch.</para>
belaran@999 15976
belaran@999 15977 </sect2>
belaran@999 15978 <sect2>
belaran@999 15979 <title><command role="hg-ext-mq" moreinfo="none">qcommit</command>—commit
belaran@999 15980 changes in the queue repository</title>
belaran@999 15981
belaran@999 15982 <para id="x_5ea">The <command role="hg-ext-mq" moreinfo="none">qcommit</command> command
belaran@999 15983 commits any outstanding changes in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
belaran@999 15984 repository. This command only works if the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
belaran@999 15985 directory is a repository, i.e. you created the directory
belaran@999 15986 using <command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or
belaran@999 15987 ran <command role="hg-cmd" moreinfo="none">hg init</command> in the directory
belaran@999 15988 after running <command role="hg-ext-mq" moreinfo="none">qinit</command>.</para>
belaran@999 15989
belaran@999 15990 <para id="x_5eb">This command is shorthand for <command role="hg-cmd" moreinfo="none">hg
belaran@999 15991 commit --cwd .hg/patches</command>.</para>
belaran@999 15992 </sect2>
belaran@999 15993 <sect2>
belaran@999 15994 <title><command role="hg-ext-mq" moreinfo="none">qdelete</command>—delete a patch
belaran@999 15995 from the <filename role="special" moreinfo="none">series</filename>
belaran@999 15996 file</title>
belaran@999 15997
belaran@999 15998 <para id="x_5ec">The <command role="hg-ext-mq" moreinfo="none">qdelete</command> command
belaran@999 15999 removes the entry for a patch from the <filename role="special" moreinfo="none">series</filename> file in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
belaran@999 16000 directory. It does not pop the patch if the patch is already
belaran@999 16001 applied. By default, it does not delete the patch file; use
belaran@999 16002 the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option
belaran@999 16003 to do that.</para>
belaran@999 16004
belaran@999 16005 <para id="x_5ed">Options:</para>
belaran@999 16006 <itemizedlist>
belaran@999 16007 <listitem><para id="x_5ee"><option role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the
belaran@999 16008 patch file.</para>
belaran@999 16009 </listitem></itemizedlist>
belaran@999 16010
belaran@999 16011 </sect2>
belaran@999 16012 <sect2>
belaran@999 16013 <title><command role="hg-ext-mq" moreinfo="none">qdiff</command>—print a
belaran@999 16014 diff of the topmost applied patch</title>
belaran@999 16015
belaran@999 16016 <para id="x_5ef">The <command role="hg-ext-mq" moreinfo="none">qdiff</command> command
belaran@999 16017 prints a diff of the topmost applied patch. It is equivalent
belaran@999 16018 to <command role="hg-cmd" moreinfo="none">hg diff -r-2:-1</command>.</para>
belaran@999 16019
belaran@999 16020 </sect2>
belaran@999 16021 <sect2>
belaran@999 16022 <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—move
belaran@999 16023 applied patches into repository history</title>
belaran@999 16024
belaran@999 16025 <para id="x_72d">The <command moreinfo="none">hg qfinish</command> command converts the
belaran@999 16026 specified applied patches into permanent changes by moving
belaran@999 16027 them out of MQ's control so that they will be treated as
belaran@999 16028 normal repository history.</para>
belaran@999 16029 </sect2>
belaran@999 16030
belaran@999 16031 <sect2>
belaran@999 16032 <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—merge
belaran@999 16033 (<quote>fold</quote>) several patches into one</title>
belaran@999 16034
belaran@999 16035 <para id="x_5f0">The <command role="hg-ext-mq" moreinfo="none">qfold</command> command
belaran@999 16036 merges multiple patches into the topmost applied patch, so
belaran@999 16037 that the topmost applied patch makes the union of all of the
belaran@999 16038 changes in the patches in question.</para>
belaran@999 16039
belaran@999 16040 <para id="x_5f1">The patches to fold must not be applied; <command role="hg-ext-mq" moreinfo="none">qfold</command> will exit with an error if
belaran@999 16041 any is. The order in which patches are folded is significant;
belaran@999 16042 <command role="hg-cmd" moreinfo="none">hg qfold a b</command> means
belaran@999 16043 <quote>apply the current topmost patch, followed by
belaran@999 16044 <literal moreinfo="none">a</literal>, followed by
belaran@999 16045 <literal moreinfo="none">b</literal></quote>.</para>
belaran@999 16046
belaran@999 16047 <para id="x_5f2">The comments from the folded patches are appended to the
belaran@999 16048 comments of the destination patch, with each block of comments
belaran@999 16049 separated by three asterisk
belaran@999 16050 (<quote><literal moreinfo="none">*</literal></quote>) characters. Use the
belaran@999 16051 <option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to
belaran@999 16052 edit the commit message for the combined patch/changeset after
belaran@999 16053 the folding has completed.</para>
belaran@999 16054
belaran@999 16055 <para id="x_5f3">Options:</para>
belaran@999 16056 <itemizedlist>
belaran@999 16057 <listitem><para id="x_5f4"><option role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the
belaran@999 16058 commit message and patch description for the newly folded
belaran@999 16059 patch.</para>
belaran@999 16060 </listitem>
belaran@999 16061 <listitem><para id="x_5f5"><option role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the
belaran@999 16062 contents of the given file as the new commit message and
belaran@999 16063 patch description for the folded patch.</para>
belaran@999 16064 </listitem>
belaran@999 16065 <listitem><para id="x_5f6"><option role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the
belaran@999 16066 given text as the new commit message and patch description
belaran@999 16067 for the folded patch.</para>
belaran@999 16068 </listitem></itemizedlist>
belaran@999 16069
belaran@999 16070 </sect2>
belaran@999 16071 <sect2>
belaran@999 16072 <title><command role="hg-ext-mq" moreinfo="none">qheader</command>—display the
belaran@999 16073 header/description of a patch</title>
belaran@999 16074
belaran@999 16075 <para id="x_5f7">The <command role="hg-ext-mq" moreinfo="none">qheader</command> command
belaran@999 16076 prints the header, or description, of a patch. By default, it
belaran@999 16077 prints the header of the topmost applied patch. Given an
belaran@999 16078 argument, it prints the header of the named patch.</para>
belaran@999 16079
belaran@999 16080 </sect2>
belaran@999 16081 <sect2>
belaran@999 16082 <title><command role="hg-ext-mq" moreinfo="none">qimport</command>—import
belaran@999 16083 a third-party patch into the queue</title>
belaran@999 16084
belaran@999 16085 <para id="x_5f8">The <command role="hg-ext-mq" moreinfo="none">qimport</command> command
belaran@999 16086 adds an entry for an external patch to the <filename role="special" moreinfo="none">series</filename> file, and copies the patch
belaran@999 16087 into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory. It adds
belaran@999 16088 the entry immediately after the topmost applied patch, but
belaran@999 16089 does not push the patch.</para>
belaran@999 16090
belaran@999 16091 <para id="x_5f9">If the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a
belaran@999 16092 repository, <command role="hg-ext-mq" moreinfo="none">qimport</command>
belaran@999 16093 automatically does an <command role="hg-cmd" moreinfo="none">hg add</command>
belaran@999 16094 of the imported patch.</para>
belaran@999 16095
belaran@999 16096 </sect2>
belaran@999 16097 <sect2>
belaran@999 16098 <title><command role="hg-ext-mq" moreinfo="none">qinit</command>—prepare
belaran@999 16099 a repository to work with MQ</title>
belaran@999 16100
belaran@999 16101 <para id="x_5fa">The <command role="hg-ext-mq" moreinfo="none">qinit</command> command
belaran@999 16102 prepares a repository to work with MQ. It creates a directory
belaran@999 16103 called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>.</para>
belaran@999 16104
belaran@999 16105 <para id="x_5fb">Options:</para>
belaran@999 16106 <itemizedlist>
belaran@999 16107 <listitem><para id="x_5fc"><option role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create
belaran@999 16108 <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> as a repository
belaran@999 16109 in its own right. Also creates a <filename role="special" moreinfo="none">.hgignore</filename> file that will
belaran@999 16110 ignore the <filename role="special" moreinfo="none">status</filename>
belaran@999 16111 file.</para>
belaran@999 16112 </listitem></itemizedlist>
belaran@999 16113
belaran@999 16114 <para id="x_5fd">When the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a
belaran@999 16115 repository, the <command role="hg-ext-mq" moreinfo="none">qimport</command>
belaran@999 16116 and <command role="hg-ext-mq" moreinfo="none">qnew</command> commands
belaran@999 16117 automatically <command role="hg-cmd" moreinfo="none">hg add</command> new
belaran@999 16118 patches.</para>
belaran@999 16119
belaran@999 16120 </sect2>
belaran@999 16121 <sect2>
belaran@999 16122 <title><command role="hg-ext-mq" moreinfo="none">qnew</command>—create a
belaran@999 16123 new patch</title>
belaran@999 16124
belaran@999 16125 <para id="x_5fe">The <command role="hg-ext-mq" moreinfo="none">qnew</command> command
belaran@999 16126 creates a new patch. It takes one mandatory argument, the
belaran@999 16127 name to use for the patch file. The newly created patch is
belaran@999 16128 created empty by default. It is added to the <filename role="special" moreinfo="none">series</filename> file after the current
belaran@999 16129 topmost applied patch, and is immediately pushed on top of
belaran@999 16130 that patch.</para>
belaran@999 16131
belaran@999 16132 <para id="x_5ff">If <command role="hg-ext-mq" moreinfo="none">qnew</command> finds modified
belaran@999 16133 files in the working directory, it will refuse to create a new
belaran@999 16134 patch unless the <option role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used
belaran@999 16135 (see below). This behavior allows you to <command role="hg-ext-mq" moreinfo="none">qrefresh</command> your topmost applied
belaran@999 16136 patch before you apply a new patch on top of it.</para>
belaran@999 16137
belaran@999 16138 <para id="x_600">Options:</para>
belaran@999 16139 <itemizedlist>
belaran@999 16140 <listitem><para id="x_601"><option role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new
belaran@999 16141 patch if the contents of the working directory are
belaran@999 16142 modified. Any outstanding modifications are added to the
belaran@999 16143 newly created patch, so after this command completes, the
belaran@999 16144 working directory will no longer be modified.</para>
belaran@999 16145 </listitem>
belaran@999 16146 <listitem><para id="x_602"><option role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given
belaran@999 16147 text as the commit message. This text will be stored at
belaran@999 16148 the beginning of the patch file, before the patch
belaran@999 16149 data.</para>
belaran@999 16150 </listitem></itemizedlist>
belaran@999 16151
belaran@999 16152 </sect2>
belaran@999 16153 <sect2>
belaran@999 16154 <title><command role="hg-ext-mq" moreinfo="none">qnext</command>—print
belaran@999 16155 the name of the next patch</title>
belaran@999 16156
belaran@999 16157 <para id="x_603">The <command role="hg-ext-mq" moreinfo="none">qnext</command> command
belaran@999 16158 prints the name name of the next patch in the <filename role="special" moreinfo="none">series</filename> file after the topmost
belaran@999 16159 applied patch. This patch will become the topmost applied
belaran@999 16160 patch if you run <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para>
belaran@999 16161
belaran@999 16162 </sect2>
belaran@999 16163 <sect2>
belaran@999 16164 <title><command role="hg-ext-mq" moreinfo="none">qpop</command>—pop
belaran@999 16165 patches off the stack</title>
belaran@999 16166
belaran@999 16167 <para id="x_604">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command
belaran@999 16168 removes applied patches from the top of the stack of applied
belaran@999 16169 patches. By default, it removes only one patch.</para>
belaran@999 16170
belaran@999 16171 <para id="x_605">This command removes the changesets that represent the
belaran@999 16172 popped patches from the repository, and updates the working
belaran@999 16173 directory to undo the effects of the patches.</para>
belaran@999 16174
belaran@999 16175 <para id="x_606">This command takes an optional argument, which it uses as
belaran@999 16176 the name or index of the patch to pop to. If given a name, it
belaran@999 16177 will pop patches until the named patch is the topmost applied
belaran@999 16178 patch. If given a number, <command role="hg-ext-mq" moreinfo="none">qpop</command> treats the number as an
belaran@999 16179 index into the entries in the series file, counting from zero
belaran@999 16180 (empty lines and lines containing only comments do not count).
belaran@999 16181 It pops patches until the patch identified by the given index
belaran@999 16182 is the topmost applied patch.</para>
belaran@999 16183
belaran@999 16184 <para id="x_607">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command does
belaran@999 16185 not read or write patches or the <filename role="special" moreinfo="none">series</filename> file. It is thus safe to
belaran@999 16186 <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch that you have
belaran@999 16187 removed from the <filename role="special" moreinfo="none">series</filename>
belaran@999 16188 file, or a patch that you have renamed or deleted entirely.
belaran@999 16189 In the latter two cases, use the name of the patch as it was
belaran@999 16190 when you applied it.</para>
belaran@999 16191
belaran@999 16192 <para id="x_608">By default, the <command role="hg-ext-mq" moreinfo="none">qpop</command>
belaran@999 16193 command will not pop any patches if the working directory has
belaran@999 16194 been modified. You can override this behavior using the
belaran@999 16195 <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option,
belaran@999 16196 which reverts all modifications in the working
belaran@999 16197 directory.</para>
belaran@999 16198
belaran@999 16199 <para id="x_609">Options:</para>
belaran@999 16200 <itemizedlist>
belaran@999 16201 <listitem><para id="x_60a"><option role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all
belaran@999 16202 applied patches. This returns the repository to its state
belaran@999 16203 before you applied any patches.</para>
belaran@999 16204 </listitem>
belaran@999 16205 <listitem><para id="x_60b"><option role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly
belaran@999 16206 revert any modifications to the working directory when
belaran@999 16207 popping.</para>
belaran@999 16208 </listitem>
belaran@999 16209 <listitem><para id="x_60c"><option role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch
belaran@999 16210 from the named queue.</para>
belaran@999 16211 </listitem></itemizedlist>
belaran@999 16212
belaran@999 16213 <para id="x_60d">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command
belaran@999 16214 removes one line from the end of the <filename role="special" moreinfo="none">status</filename> file for each patch that it
belaran@999 16215 pops.</para>
belaran@999 16216
belaran@999 16217 </sect2>
belaran@999 16218 <sect2>
belaran@999 16219 <title><command role="hg-ext-mq" moreinfo="none">qprev</command>—print
belaran@999 16220 the name of the previous patch</title>
belaran@999 16221
belaran@999 16222 <para id="x_60e">The <command role="hg-ext-mq" moreinfo="none">qprev</command> command
belaran@999 16223 prints the name of the patch in the <filename role="special" moreinfo="none">series</filename> file that comes before the
belaran@999 16224 topmost applied patch. This will become the topmost applied
belaran@999 16225 patch if you run <command role="hg-ext-mq" moreinfo="none">qpop</command>.</para>
belaran@999 16226
belaran@999 16227 </sect2>
belaran@999 16228 <sect2 id="sec:mqref:cmd:qpush">
belaran@999 16229 <title><command role="hg-ext-mq" moreinfo="none">qpush</command>—push
belaran@999 16230 patches onto the stack</title>
belaran@999 16231
belaran@999 16232 <para id="x_60f">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command adds
belaran@999 16233 patches onto the applied stack. By default, it adds only one
belaran@999 16234 patch.</para>
belaran@999 16235
belaran@999 16236 <para id="x_610">This command creates a new changeset to represent each
belaran@999 16237 applied patch, and updates the working directory to apply the
belaran@999 16238 effects of the patches.</para>
belaran@999 16239
belaran@999 16240 <para id="x_611">The default data used when creating a changeset are as
belaran@999 16241 follows:</para>
belaran@999 16242 <itemizedlist>
belaran@999 16243 <listitem><para id="x_612">The commit date and time zone are the current
belaran@999 16244 date and time zone. Because these data are used to
belaran@999 16245 compute the identity of a changeset, this means that if
belaran@999 16246 you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and
belaran@999 16247 <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the
belaran@999 16248 changeset that you push will have a different identity
belaran@999 16249 than the changeset you popped.</para>
belaran@999 16250 </listitem>
belaran@999 16251 <listitem><para id="x_613">The author is the same as the default used by
belaran@999 16252 the <command role="hg-cmd" moreinfo="none">hg commit</command>
belaran@999 16253 command.</para>
belaran@999 16254 </listitem>
belaran@999 16255 <listitem><para id="x_614">The commit message is any text from the patch
belaran@999 16256 file that comes before the first diff header. If there is
belaran@999 16257 no such text, a default commit message is used that
belaran@999 16258 identifies the name of the patch.</para>
belaran@999 16259 </listitem></itemizedlist>
belaran@999 16260 <para id="x_615">If a patch contains a Mercurial patch header,
belaran@999 16261 the information in the patch header overrides these
belaran@999 16262 defaults.</para>
belaran@999 16263
belaran@999 16264 <para id="x_616">Options:</para>
belaran@999 16265 <itemizedlist>
belaran@999 16266 <listitem><para id="x_617"><option role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all
belaran@999 16267 unapplied patches from the <filename role="special" moreinfo="none">series</filename> file until there are
belaran@999 16268 none left to push.</para>
belaran@999 16269 </listitem>
belaran@999 16270 <listitem><para id="x_618"><option role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name
belaran@999 16271 of the patch to the end of the commit message.</para>
belaran@999 16272 </listitem>
belaran@999 16273 <listitem><para id="x_619"><option role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch
belaran@999 16274 fails to apply cleanly, use the entry for the patch in
belaran@999 16275 another saved queue to compute the parameters for a
belaran@999 16276 three-way merge, and perform a three-way merge using the
belaran@999 16277 normal Mercurial merge machinery. Use the resolution of
belaran@999 16278 the merge as the new patch content.</para>
belaran@999 16279 </listitem>
belaran@999 16280 <listitem><para id="x_61a"><option role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the
belaran@999 16281 named queue if merging while pushing.</para>
belaran@999 16282 </listitem></itemizedlist>
belaran@999 16283
belaran@999 16284 <para id="x_61b">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command
belaran@999 16285 reads, but does not modify, the <filename role="special" moreinfo="none">series</filename> file. It appends one line
belaran@999 16286 to the <command role="hg-cmd" moreinfo="none">hg status</command> file for
belaran@999 16287 each patch that it pushes.</para>
belaran@999 16288
belaran@999 16289 </sect2>
belaran@999 16290 <sect2>
belaran@999 16291 <title><command role="hg-ext-mq" moreinfo="none">qrefresh</command>—update the
belaran@999 16292 topmost applied patch</title>
belaran@999 16293
belaran@999 16294 <para id="x_61c">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
belaran@999 16295 updates the topmost applied patch. It modifies the patch,
belaran@999 16296 removes the old changeset that represented the patch, and
belaran@999 16297 creates a new changeset to represent the modified
belaran@999 16298 patch.</para>
belaran@999 16299
belaran@999 16300 <para id="x_61d">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
belaran@999 16301 looks for the following modifications:</para>
belaran@999 16302 <itemizedlist>
belaran@999 16303 <listitem><para id="x_61e">Changes to the commit message, i.e. the text
belaran@999 16304 before the first diff header in the patch file, are
belaran@999 16305 reflected in the new changeset that represents the
belaran@999 16306 patch.</para>
belaran@999 16307 </listitem>
belaran@999 16308 <listitem><para id="x_61f">Modifications to tracked files in the working
belaran@999 16309 directory are added to the patch.</para>
belaran@999 16310 </listitem>
belaran@999 16311 <listitem><para id="x_620">Changes to the files tracked using <command role="hg-cmd" moreinfo="none">hg add</command>, <command role="hg-cmd" moreinfo="none">hg copy</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>, or <command role="hg-cmd" moreinfo="none">hg rename</command>. Added files and copy
belaran@999 16312 and rename destinations are added to the patch, while
belaran@999 16313 removed files and rename sources are removed.</para>
belaran@999 16314 </listitem></itemizedlist>
belaran@999 16315
belaran@999 16316 <para id="x_621">Even if <command role="hg-ext-mq" moreinfo="none">qrefresh</command>
belaran@999 16317 detects no changes, it still recreates the changeset that
belaran@999 16318 represents the patch. This causes the identity of the
belaran@999 16319 changeset to differ from the previous changeset that
belaran@999 16320 identified the patch.</para>
belaran@999 16321
belaran@999 16322 <para id="x_622">Options:</para>
belaran@999 16323 <itemizedlist>
belaran@999 16324 <listitem><para id="x_623"><option role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify
belaran@999 16325 the commit and patch description, using the preferred text
belaran@999 16326 editor.</para>
belaran@999 16327 </listitem>
belaran@999 16328 <listitem><para id="x_624"><option role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify
belaran@999 16329 the commit message and patch description, using the given
belaran@999 16330 text.</para>
belaran@999 16331 </listitem>
belaran@999 16332 <listitem><para id="x_625"><option role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify
belaran@999 16333 the commit message and patch description, using text from
belaran@999 16334 the given file.</para>
belaran@999 16335 </listitem></itemizedlist>
belaran@999 16336
belaran@999 16337 </sect2>
belaran@999 16338 <sect2>
belaran@999 16339 <title><command role="hg-ext-mq" moreinfo="none">qrename</command>—rename
belaran@999 16340 a patch</title>
belaran@999 16341
belaran@999 16342 <para id="x_626">The <command role="hg-ext-mq" moreinfo="none">qrename</command> command
belaran@999 16343 renames a patch, and changes the entry for the patch in the
belaran@999 16344 <filename role="special" moreinfo="none">series</filename> file.</para>
belaran@999 16345
belaran@999 16346 <para id="x_627">With a single argument, <command role="hg-ext-mq" moreinfo="none">qrename</command> renames the topmost
belaran@999 16347 applied patch. With two arguments, it renames its first
belaran@999 16348 argument to its second.</para>
belaran@999 16349
belaran@999 16350 </sect2>
belaran@999 16351 <sect2>
belaran@999 16352 <title><command role="hg-ext-mq" moreinfo="none">qseries</command>—print
belaran@999 16353 the entire patch series</title>
belaran@999 16354
belaran@999 16355 <para id="x_62a">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command
belaran@999 16356 prints the entire patch series from the <filename role="special" moreinfo="none">series</filename> file. It prints only patch
belaran@999 16357 names, not empty lines or comments. It prints in order from
belaran@999 16358 first to be applied to last.</para>
belaran@999 16359
belaran@999 16360 </sect2>
belaran@999 16361 <sect2>
belaran@999 16362 <title><command role="hg-ext-mq" moreinfo="none">qtop</command>—print the
belaran@999 16363 name of the current patch</title>
belaran@999 16364
belaran@999 16365 <para id="x_62b">The <command role="hg-ext-mq" moreinfo="none">qtop</command> prints the
belaran@999 16366 name of the topmost currently applied patch.</para>
belaran@999 16367
belaran@999 16368 </sect2>
belaran@999 16369 <sect2>
belaran@999 16370 <title><command role="hg-ext-mq" moreinfo="none">qunapplied</command>—print patches
belaran@999 16371 not yet applied</title>
belaran@999 16372
belaran@999 16373 <para id="x_62c">The <command role="hg-ext-mq" moreinfo="none">qunapplied</command> command
belaran@999 16374 prints the names of patches from the <filename role="special" moreinfo="none">series</filename> file that are not yet
belaran@999 16375 applied. It prints them in order from the next patch that
belaran@999 16376 will be pushed to the last.</para>
belaran@999 16377
belaran@999 16378 </sect2>
belaran@999 16379 <sect2>
belaran@999 16380 <title><command role="hg-cmd" moreinfo="none">hg strip</command>—remove a
belaran@999 16381 revision and descendants</title>
belaran@999 16382
belaran@999 16383 <para id="x_62d">The <command role="hg-cmd" moreinfo="none">hg strip</command> command
belaran@999 16384 removes a revision, and all of its descendants, from the
belaran@999 16385 repository. It undoes the effects of the removed revisions
belaran@999 16386 from the repository, and updates the working directory to the
belaran@999 16387 first parent of the removed revision.</para>
belaran@999 16388
belaran@999 16389 <para id="x_62e">The <command role="hg-cmd" moreinfo="none">hg strip</command> command
belaran@999 16390 saves a backup of the removed changesets in a bundle, so that
belaran@999 16391 they can be reapplied if removed in error.</para>
belaran@999 16392
belaran@999 16393 <para id="x_62f">Options:</para>
belaran@999 16394 <itemizedlist>
belaran@999 16395 <listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save
belaran@999 16396 unrelated changesets that are intermixed with the stripped
belaran@999 16397 changesets in the backup bundle.</para>
belaran@999 16398 </listitem>
belaran@999 16399 <listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a
belaran@999 16400 branch has multiple heads, remove all heads.</para>
belaran@999 16401 </listitem>
belaran@999 16402 <listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do
belaran@999 16403 not save a backup bundle.</para>
belaran@999 16404 </listitem></itemizedlist>
belaran@999 16405
belaran@999 16406 </sect2>
belaran@999 16407 </sect1>
belaran@999 16408 <sect1>
belaran@999 16409 <title>MQ file reference</title>
belaran@999 16410
belaran@999 16411 <sect2>
belaran@999 16412 <title>The <filename role="special" moreinfo="none">series</filename>
belaran@999 16413 file</title>
belaran@999 16414
belaran@999 16415 <para id="x_633">The <filename role="special" moreinfo="none">series</filename> file
belaran@999 16416 contains a list of the names of all patches that MQ can apply.
belaran@999 16417 It is represented as a list of names, with one name saved per
belaran@999 16418 line. Leading and trailing white space in each line are
belaran@999 16419 ignored.</para>
belaran@999 16420
belaran@999 16421 <para id="x_634">Lines may contain comments. A comment begins with the
belaran@999 16422 <quote><literal moreinfo="none">#</literal></quote> character, and extends to
belaran@999 16423 the end of the line. Empty lines, and lines that contain only
belaran@999 16424 comments, are ignored.</para>
belaran@999 16425
belaran@999 16426 <para id="x_635">You will often need to edit the <filename role="special" moreinfo="none">series</filename> file by hand, hence the
belaran@999 16427 support for comments and empty lines noted above. For
belaran@999 16428 example, you can comment out a patch temporarily, and <command role="hg-ext-mq" moreinfo="none">qpush</command> will skip over that patch
belaran@999 16429 when applying patches. You can also change the order in which
belaran@999 16430 patches are applied by reordering their entries in the
belaran@999 16431 <filename role="special" moreinfo="none">series</filename> file.</para>
belaran@999 16432
belaran@999 16433 <para id="x_636">Placing the <filename role="special" moreinfo="none">series</filename>
belaran@999 16434 file under revision control is also supported; it is a good
belaran@999 16435 idea to place all of the patches that it refers to under
belaran@999 16436 revision control, as well. If you create a patch directory
belaran@999 16437 using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option>
belaran@999 16438 option to <command role="hg-ext-mq" moreinfo="none">qinit</command>, this will
belaran@999 16439 be done for you automatically.</para>
belaran@999 16440
belaran@999 16441 </sect2>
belaran@999 16442 <sect2>
belaran@999 16443 <title>The <filename role="special" moreinfo="none">status</filename>
belaran@999 16444 file</title>
belaran@999 16445
belaran@999 16446 <para id="x_637">The <filename role="special" moreinfo="none">status</filename> file
belaran@999 16447 contains the names and changeset hashes of all patches that MQ
belaran@999 16448 currently has applied. Unlike the <filename role="special" moreinfo="none">series</filename> file, this file is not
belaran@999 16449 intended for editing. You should not place this file under
belaran@999 16450 revision control, or modify it in any way. It is used by MQ
belaran@999 16451 strictly for internal book-keeping.</para>
belaran@999 16452
belaran@999 16453 </sect2>
belaran@999 16454 </sect1>
belaran@999 16455 </appendix>
belaran@999 16456
belaran@999 16457 <!--
belaran@999 16458 local variables:
belaran@999 16459 sgml-parent-document: ("00book.xml" "book" "appendix")
belaran@999 16460 end:
belaran@999 16461 -->
belaran@999 16462
belaran@999 16463 <!-- BEGIN appC -->
belaran@999 16464 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 16465
belaran@999 16466 <appendix id="chap:srcinstall">
belaran@999 16467 <?dbhtml filename="installing-mercurial-from-source.html"?>
belaran@999 16468 <title>Installer Mercurial à partir des sources</title>
belaran@999 16469
belaran@999 16470 <sect1 id="sec:srcinstall:unixlike">
belaran@999 16471 <title>Pour un système Unix ou similaire</title>
belaran@999 16472
belaran@999 16473 <para id="x_5e0">Si vous utilisez un système Unix ou similaire, pour lequel
belaran@999 16474 une version récente de Python (2.3 ou plus) est disponible, l'installation
belaran@999 16475 de Mercurial à partir des sources est simple.</para>
belaran@999 16476 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 16477 <listitem><para id="x_5e1">Téléchargez un paquet récent depuis <ulink url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para>
belaran@999 16478 </listitem>
belaran@999 16479 <listitem><para id="x_5e2">Extrayez le paquet : </para>
belaran@999 16480 <programlisting format="linespecific">gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting>
belaran@999 16481 </listitem>
belaran@999 16482 <listitem><para id="x_5e3">Allez dans le répertoires où les sources ont
belaran@999 16483 été extraites et exécutez le script d'installation. Ce dernier compilera
belaran@999 16484 Mercurial et l'installera dans votre répertoire utilisateur.</para>
belaran@999 16485 <programlisting format="linespecific">cd mercurial-MYVERSION
belaran@999 16486 python setup.py install --force --home=$HOME</programlisting>
belaran@999 16487 </listitem>
belaran@999 16488 </orderedlist>
belaran@999 16489 <para id="x_5e4">Lorsque l'installation est terminée, Mercurial se
belaran@999 16490 trouvera dans le répertoire <literal moreinfo="none">bin</literal> de votre répertoire
belaran@999 16491 utilisateur.
belaran@999 16492 N'oubliez pas de vérifier que ce répertoire se trouve dans la liste
belaran@999 16493 des répertoires où votre shell recherche les exécutables.</para>
belaran@999 16494
belaran@999 16495 <para id="x_5e5">Vous devrez vraisemblablement définir la variable
belaran@999 16496 d'environnement <envar>PYTHONPATH</envar> de manière à ce que
belaran@999 16497 l'exécutable de Mercurial puisse trouver le reste des paquets logiciels.
belaran@999 16498 Par exemple, sur mon ordinateur portable, je dois le définir ainsi:
belaran@999 16499 <literal moreinfo="none">/home/bos/lib/python</literal>. Le chemin exact à utiliser
belaran@999 16500 dépendra de la manière dont Python aura été construit pour votre
belaran@999 16501 système. Il ne devrait pas être difficile de le trouver. En cas de
belaran@999 16502 doute, lisez le texte généré lors de l'installation ci-dessus, et
belaran@999 16503 recherchez l'emplacement où le contenu du répertoire
belaran@999 16504 <literal moreinfo="none">mercurial</literal> a été installé.</para>
belaran@999 16505
belaran@999 16506 </sect1>
belaran@999 16507 <sect1>
belaran@999 16508 <title>Pour Windows</title>
belaran@999 16509
belaran@999 16510 <para id="x_5e6">Construire et installer Mercurial sous Windows nécessite
belaran@999 16511 des outils logiciels divers, une certaine connaissance technique et une
belaran@999 16512 bonne dose de patience. Je vous <emphasis>déconseille fortement</emphasis>
belaran@999 16513 de tenter de le faire si vous êtes un <quote>simple utilisateur</quote>.
belaran@999 16514 A moins que vous n'ayez l'intention de "hacker" Mercurial, je vous
belaran@999 16515 suggère d'avoir recours à un paquet d'installation de la version binaire.</para>
belaran@999 16516
belaran@999 16517 <para id="x_5e7">Si vous avez vraiment l'intention de construire
belaran@999 16518 Mercurial à partir des sources sous Windows, suivez les indications pour
belaran@999 16519 ce <quote>chemin laborieux</quote> sur le wiki de Mercurial : <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>,
belaran@999 16520 et préparez vous à un travail épineux.</para>
belaran@999 16521
belaran@999 16522 </sect1>
belaran@999 16523 </appendix>
belaran@999 16524
belaran@999 16525 <!--
belaran@999 16526 local variables:
belaran@999 16527 sgml-parent-document: ("00book.xml" "book" "appendix")
belaran@999 16528 end:
belaran@999 16529 -->
belaran@999 16530
belaran@999 16531 <!-- BEGIN appD -->
belaran@999 16532 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@999 16533
belaran@999 16534 <appendix id="cha:opl">
belaran@999 16535 <?dbhtml filename="open-publication-license.html"?>
belaran@999 16536 <title>Open Publication License</title>
belaran@999 16537
belaran@999 16538 <para id="x_638">Version 1.0, 8 June 1999</para>
belaran@999 16539
belaran@999 16540 <sect1>
belaran@999 16541 <title>Requirements on both unmodified and modified
belaran@999 16542 versions</title>
belaran@999 16543
belaran@999 16544 <para id="x_639">The Open Publication works may be reproduced and distributed
belaran@999 16545 in whole or in part, in any medium physical or electronic,
belaran@999 16546 provided that the terms of this license are adhered to, and that
belaran@999 16547 this license or an incorporation of it by reference (with any
belaran@999 16548 options elected by the author(s) and/or publisher) is displayed
belaran@999 16549 in the reproduction.</para>
belaran@999 16550
belaran@999 16551 <para id="x_63a">Proper form for an incorporation by reference is as
belaran@999 16552 follows:</para>
belaran@999 16553
belaran@999 16554 <blockquote>
belaran@999 16555 <para id="x_63b"> Copyright (c) <emphasis>year</emphasis> by
belaran@999 16556 <emphasis>author's name or designee</emphasis>. This material
belaran@999 16557 may be distributed only subject to the terms and conditions
belaran@999 16558 set forth in the Open Publication License,
belaran@999 16559 v<emphasis>x.y</emphasis> or later (the latest version is
belaran@999 16560 presently available at <ulink url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para>
belaran@999 16561 </blockquote>
belaran@999 16562
belaran@999 16563 <para id="x_63c">The reference must be immediately followed with any options
belaran@999 16564 elected by the author(s) and/or publisher of the document (see
belaran@999 16565 <xref linkend="sec:opl:options"/>).</para>
belaran@999 16566
belaran@999 16567 <para id="x_63d">Commercial redistribution of Open Publication-licensed
belaran@999 16568 material is permitted.</para>
belaran@999 16569
belaran@999 16570 <para id="x_63e">Any publication in standard (paper) book form shall require
belaran@999 16571 the citation of the original publisher and author. The publisher
belaran@999 16572 and author's names shall appear on all outer surfaces of the
belaran@999 16573 book. On all outer surfaces of the book the original publisher's
belaran@999 16574 name shall be as large as the title of the work and cited as
belaran@999 16575 possessive with respect to the title.</para>
belaran@999 16576
belaran@999 16577 </sect1>
belaran@999 16578 <sect1>
belaran@999 16579 <title>Copyright</title>
belaran@999 16580
belaran@999 16581 <para id="x_63f">The copyright to each Open Publication is owned by its
belaran@999 16582 author(s) or designee.</para>
belaran@999 16583
belaran@999 16584 </sect1>
belaran@999 16585 <sect1>
belaran@999 16586 <title>Scope of license</title>
belaran@999 16587
belaran@999 16588 <para id="x_640">The following license terms apply to all Open Publication
belaran@999 16589 works, unless otherwise explicitly stated in the
belaran@999 16590 document.</para>
belaran@999 16591
belaran@999 16592 <para id="x_641">Mere aggregation of Open Publication works or a portion of
belaran@999 16593 an Open Publication work with other works or programs on the
belaran@999 16594 same media shall not cause this license to apply to those other
belaran@999 16595 works. The aggregate work shall contain a notice specifying the
belaran@999 16596 inclusion of the Open Publication material and appropriate
belaran@999 16597 copyright notice.</para>
belaran@999 16598
belaran@999 16599 <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part
belaran@999 16600 of this license is found to be unenforceable in any
belaran@999 16601 jurisdiction, the remaining portions of the license remain in
belaran@999 16602 force.</para>
belaran@999 16603
belaran@999 16604 <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open
belaran@999 16605 Publication works are licensed and provided <quote>as is</quote>
belaran@999 16606 without warranty of any kind, express or implied, including, but
belaran@999 16607 not limited to, the implied warranties of merchantability and
belaran@999 16608 fitness for a particular purpose or a warranty of
belaran@999 16609 non-infringement.</para>
belaran@999 16610
belaran@999 16611 </sect1>
belaran@999 16612 <sect1>
belaran@999 16613 <title>Requirements on modified works</title>
belaran@999 16614
belaran@999 16615 <para id="x_644">All modified versions of documents covered by this license,
belaran@999 16616 including translations, anthologies, compilations and partial
belaran@999 16617 documents, must meet the following requirements:</para>
belaran@999 16618
belaran@999 16619 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 16620 <listitem><para id="x_645">The modified version must be labeled as
belaran@999 16621 such.</para>
belaran@999 16622 </listitem>
belaran@999 16623 <listitem><para id="x_646">The person making the modifications must be
belaran@999 16624 identified and the modifications dated.</para>
belaran@999 16625 </listitem>
belaran@999 16626 <listitem><para id="x_647">Acknowledgement of the original author and
belaran@999 16627 publisher if applicable must be retained according to normal
belaran@999 16628 academic citation practices.</para>
belaran@999 16629 </listitem>
belaran@999 16630 <listitem><para id="x_648">The location of the original unmodified document
belaran@999 16631 must be identified.</para>
belaran@999 16632 </listitem>
belaran@999 16633 <listitem><para id="x_649">The original author's (or authors') name(s) may
belaran@999 16634 not be used to assert or imply endorsement of the resulting
belaran@999 16635 document without the original author's (or authors')
belaran@999 16636 permission.</para>
belaran@999 16637 </listitem></orderedlist>
belaran@999 16638
belaran@999 16639 </sect1>
belaran@999 16640 <sect1>
belaran@999 16641 <title>Good-practice recommendations</title>
belaran@999 16642
belaran@999 16643 <para id="x_64a">In addition to the requirements of this license, it is
belaran@999 16644 requested from and strongly recommended of redistributors
belaran@999 16645 that:</para>
belaran@999 16646
belaran@999 16647 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 16648 <listitem><para id="x_64b">If you are distributing Open Publication works
belaran@999 16649 on hardcopy or CD-ROM, you provide email notification to the
belaran@999 16650 authors of your intent to redistribute at least thirty days
belaran@999 16651 before your manuscript or media freeze, to give the authors
belaran@999 16652 time to provide updated documents. This notification should
belaran@999 16653 describe modifications, if any, made to the document.</para>
belaran@999 16654 </listitem>
belaran@999 16655 <listitem><para id="x_64c">All substantive modifications (including
belaran@999 16656 deletions) be either clearly marked up in the document or
belaran@999 16657 else described in an attachment to the document.</para>
belaran@999 16658 </listitem>
belaran@999 16659 <listitem><para id="x_64d">Finally, while it is not mandatory under this
belaran@999 16660 license, it is considered good form to offer a free copy of
belaran@999 16661 any hardcopy and CD-ROM expression of an Open
belaran@999 16662 Publication-licensed work to its author(s).</para>
belaran@999 16663 </listitem></orderedlist>
belaran@999 16664
belaran@999 16665 </sect1>
belaran@999 16666 <sect1 id="sec:opl:options">
belaran@999 16667 <title>License options</title>
belaran@999 16668
belaran@999 16669 <para id="x_64e">The author(s) and/or publisher of an Open
belaran@999 16670 Publication-licensed document may elect certain options by
belaran@999 16671 appending language to the reference to or copy of the license.
belaran@999 16672 These options are considered part of the license instance and
belaran@999 16673 must be included with the license (or its incorporation by
belaran@999 16674 reference) in derived works.</para>
belaran@999 16675
belaran@999 16676 <orderedlist inheritnum="ignore" continuation="restarts">
belaran@999 16677 <listitem><para id="x_64f">To prohibit distribution of substantively
belaran@999 16678 modified versions without the explicit permission of the
belaran@999 16679 author(s). <quote>Substantive modification</quote> is
belaran@999 16680 defined as a change to the semantic content of the document,
belaran@999 16681 and excludes mere changes in format or typographical
belaran@999 16682 corrections.</para>
belaran@999 16683 </listitem>
belaran@999 16684 <listitem><para id="x_650"> To accomplish this, add the phrase
belaran@999 16685 <quote>Distribution of substantively modified versions of
belaran@999 16686 this document is prohibited without the explicit
belaran@999 16687 permission of the copyright holder.</quote> to the license
belaran@999 16688 reference or copy.</para>
belaran@999 16689 </listitem>
belaran@999 16690 <listitem><para id="x_651">To prohibit any publication of this work or
belaran@999 16691 derivative works in whole or in part in standard (paper)
belaran@999 16692 book form for commercial purposes is prohibited unless prior
belaran@999 16693 permission is obtained from the copyright holder.</para>
belaran@999 16694 </listitem>
belaran@999 16695 <listitem><para id="x_652">To accomplish this, add the phrase
belaran@999 16696 <quote>Distribution of the work or derivative of the work in
belaran@999 16697 any standard (paper) book form is prohibited unless prior
belaran@999 16698 permission is obtained from the copyright holder.</quote>
belaran@999 16699 to the license reference or copy.</para>
belaran@999 16700 </listitem></orderedlist>
belaran@999 16701
belaran@999 16702 </sect1>
belaran@999 16703 </appendix>
belaran@999 16704
belaran@999 16705 <!--
belaran@999 16706 local variables:
belaran@999 16707 sgml-parent-document: ("00book.xml" "book" "appendix")
belaran@999 16708 end:
belaran@999 16709 -->
belaran@999 16710
belaran@999 16711 </book>